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,所有意外的东西都会被丢弃,让您猜测(或询问)缺少什么。
我目前正在 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 到 .254192.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,所有意外的东西都会被丢弃,让您猜测(或询问)缺少什么。