6

我正在处理一个大型私有 /8 网络,需要枚举所有正在侦听端口 443 并在其 HTTP HEADER 响应中说明特定版本的网络服务器。

首先,我想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 不太熟悉,我不确定如何正确编写脚本 - 我必须:

  • 遍历所有 IP
  • 确保只有 X 个威胁并行运行
  • 理想情况下,将输出剪切为仅在一个文件中记下匹配主机的 IP
  • 理想情况下,确保只记下匹配的服务器版本

任何建议或指向一个方向都非常感谢。

4

2 回答 2

8

小规模 - 迭代

对于较小的IP 地址范围,可能建议像这样迭代:

for ip in 192.168.1.{1..10}; do ...

如this similar question所述。


大规模-并行!

鉴于您的问题涉及一个巨大的IP 地址跨度,您可能应该考虑一种不同的方法。

这要求使用gnu并行

使用gnu 并行在 bash 中并行迭代大量 IP 地址需要将逻辑拆分为多个文件(供并行命令使用)。

ip2int

#!/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"
}



scan_ip

#!/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的说法,朴素的 for 循环的运行时间(估计 256*256*256 地址需要 200 天)被改进到不到一天。

于 2014-08-20T12:12:44.650 回答
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)。

于 2014-08-22T06:34:22.797 回答