Bash 扫描仪优化

Bash scanner Optimization

我目前正在 bash 进行扫描。
这个想法是接收一个网络作为输入,并在遍历它的同时,ping IP 并探测端口以查看它们是否打开。

变量解释(示例):
输入 -> 要扫描的网络:192.168.1.0/24

起始IP:192.168.1.0 -> $i1.$i2.$i3.$i4
最后一个 IP:192.168.1.255 -> $m1.$m2.$m3.$m4

for oct1 in $(seq $i1 1 $m1); do
    for oct2 in $(seq $i2 1 $m2); do
        for oct3 in $(seq $i3 1 $m3); do
            for oct4 in $(seq $i4 1 $m4); do
                 ping -c 1 $oct1.$oct2.$oct3.$oct4 | grep "64 bytes" | cut -d" " -f4 | tr -d ":" >> scan.txt
                 nc -nvz $oct1.$oct2.$oct3.$oct4 80 2>&1 | grep succeeded | cut -d" " -f4 >> scan.txt
             done
         done
     done
done

文件 scan.txt 看起来像:

192.168.1.1
80
192.168.1.2
192.168.1.4
192.168.1.5
192.168.1.7
80
192.168.1.9
(...)

我唯一的问题是这个解决方案虽然有效,但需要太多时间。
扫描 192.168.1.0/24 网络时,我发现脚本可以正常启动,但在扫描大约 10 个 IP 后,它开始变慢,几乎到了卡住的地步。

我想这与 ping 和 nc 命令在后台留下作业 运行ning 有关。如果我将 & disown 添加到 ping 和 nc 命令的末尾,它 运行 会更平滑但会混淆输出。

它开始看起来像:

,而不是从 .1 到 .254
192.168.1.6
80
192.168.1.10
80

80
192.168.1.1
192.168.1.5
192.168.1.3
(...)

能否优化此代码(或以不同方式完成)以运行更快?

ping -c 1 $oct1.$oct2.$oct3.$oct4 | grep "64 bytes" | cut -d" " -f4 | tr -d ":" >> scan.txt

当 ping 没有产生“64 字节”消息时会发生什么?您的脚本停止了很长一段时间。在我的系统上,失败需要 10 秒,但我不确定该超时是否有任何特别标准。

$ time ping -c1 192.168.0.123
PING 192.168.0.123 (192.168.0.123) 56(84) bytes of data.

--- 192.168.0.123 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms


real    0m10.004s
user    0m0.000s
sys     0m0.000s

如今大多数 Linux 发行版都包含 timeout(1),因此您可以限制脚本等待的时间:

$ timeout 2 ping -c1 192.168.0.123 || echo no
PING 192.168.0.123 (192.168.0.123) 56(84) bytes of data.
no

对于并发处理(一次 ping 多个主机),您可以考虑使用 make(1) 和 -j 选项。使用脚本生成一组地址​​,每个地址一个文件名,然后定义 Makefile 规则为每个输入生成一个输出文件。作为最后一步,将所有输出连接在一起。

如果您的输入文件是 .ping 并且您的输出文件是 .pong,那么规则如下:

.ping.pong:
        ping -c 1 $^ \
        | grep "64 bytes" \
        | cut -d" " -f4 \
        | tr -d ":" > $@~
        nc -nvz $^ 80 2>&1 \
        | grep succeeded | cut -d" " -f4 >> $@~
        mv $@~ $@

会将每个 .ping 文件“编译”为 .pong 文件。 (上面的方法不太有效,因为您需要从文件名中删除后缀才能用作命令行参数。)

最后一点建议:如果您发现自己在管道中使用 grep、cut、sed 和 tr,awk(1) 是您的朋友。有 100 个原因,但也许最好的一个是您可以轻松地编写 awk 脚本,让意外的输入在您可以看到并处理的地方“漏掉”。使用 grep,所有意外的东西都会被丢弃,让您猜测(或询问)缺少什么。