我正在处理一个大型的private / 8网络,需要枚举所有正在侦听端口443并在HTTP HEADER响应中声明的特定版本的Web服务器。
首先,我考虑使用连接扫描运行nmap
并通过输出文件grep自己,但结果发现许多误报在nmap
声明端口被“过滤”的同时它实际上是“开放的”(使用连接扫描:nmap -sT -sV -Pn -n -oA foo 10.0.0.0/8 -p 443
)。
所以现在我想用bash和curl
编写脚本 - 伪代码就像:
for each IP in 10.0.0.0/8
do:
curl --head https://{IP}:443 | grep -iE "(Server\:\ Target)" > {IP}_info.txt;
done
由于我不熟悉bash,我不确定如何正确编写脚本 - 我必须:
高度赞赏任何建议或指向方向。
答案 0 :(得分:8)
对于较小的 IP地址范围,可能会建议像这样迭代:
for ip in 192.168.1.{1..10}; do ...
如similar question所述。
鉴于您的问题涉及巨大 IP地址范围,您应该考虑采用不同的方法。
使用gnu parallel在bash中并行迭代大量IP地址需要将逻辑拆分为多个文件(对于要使用的并行命令)。
#!/bin/bash
set -e
function ip_to_int()
{
local IP="$1"
local A=$(echo $IP | cut -d. -f1)
local B=$(echo $IP | cut -d. -f2)
local C=$(echo $IP | cut -d. -f3)
local D=$(echo $IP | cut -d. -f4)
local INT
INT=$(expr 256 "*" 256 "*" 256 "*" $A)
INT=$(expr 256 "*" 256 "*" $B + $INT)
INT=$(expr 256 "*" $C + $INT)
INT=$(expr $D + $INT)
echo $INT
}
function int_to_ip()
{
local INT="$1"
local D=$(expr $INT % 256)
local C=$(expr '(' $INT - $D ')' / 256 % 256)
local B=$(expr '(' $INT - $C - $D ')' / 65536 % 256)
local A=$(expr '(' $INT - $B - $C - $D ')' / 16777216 % 256)
echo "$A.$B.$C.$D"
}
#!/bin/bash
set -e
source ip2int
if [[ $# -ne 1 ]]; then
echo "Usage: $(basename "$0") ip_address_number"
exit 1
fi
CONNECT_TIMEOUT=2 # in seconds
IP_ADDRESS="$(int_to_ip ${1})"
set +e
data=$(curl --head -vs -m ${CONNECT_TIMEOUT} https://${IP_ADDRESS}:443 2>&1)
exit_code="$?"
data=$(echo -e "${data}" | grep "Server: ")
# wasn't sure what are you looking for in your servers
set -e
if [[ ${exit_code} -eq 0 ]]; then
if [[ -n "${data}" ]]; then
echo "${IP_ADDRESS} - ${data}"
else
echo "${IP_ADDRESS} - Got empty data for server!"
fi
else
echo "${IP_ADDRESS} - no server."
fi
#!/bin/bash
set -e
source ip2int
START_ADDRESS="10.0.0.0"
NUM_OF_ADDRESSES="16777216" # 256 * 256 * 256
start_address_num=$(ip_to_int ${START_ADDRESS})
end_address_num=$(( start_address_num + NUM_OF_ADDRESSES ))
seq ${start_address_num} ${end_address_num} | parallel -P0 ./scan_ip
# This parallel call does the same as this:
#
# for ip_num in $(seq ${start_address_num} ${end_address_num}); do
# ./scan_ip ${ip_num}
# done
#
# only a LOT faster!
根据@skrskrskr的说法,naive for循环的运行时间(对于256 * 256 * 256地址估计需要200天)被改善为 。
答案 1 :(得分:2)
更短的:
mycurl() {
curl --head https://${1}:443 | grep -iE "(Server\:\ Target)" > ${1}_info.txt;
}
export -f mycurl
parallel -j0 --tag mycurl {1}.{2}.{3}.{4} ::: {10..10} ::: {0..255} ::: {0..255} ::: {0..255}
使用--tag而不是许多_info.txt文件略有不同:
parallel -j0 --tag curl --head https://{1}.{2}.{3}.{4}:443 ::: {10..10} ::: {0..255} ::: {0..255} ::: {0..255} | grep -iE "(Server\:\ Target)" > info.txt
扇出并行运行超过500个:
parallel echo {1}.{2}.{3}.{4} ::: {10..10} ::: {0..255} ::: {0..255} ::: {0..255} | \
parallel -j100 --pipe -N1000 --load 100% --delay 1 parallel -j250 --tag -I ,,,, curl --head https://,,,,:443 | grep -iE "(Server\:\ Target)" > info.txt
这将产生多达100 * 250个作业,但会尝试找到任何CPU没有空闲时间的最佳作业数。在我的8核系统7500上。确保你有足够的RAM来运行最大潜力(在这种情况下为25000)。