我想扫描多个主机中的多个端口。我使用了这个脚本,但显示结果需要很长时间。
#!/bin/bash
hosts=(
"server1"
"server2"
)
for host in "${hosts[@]}"
do
echo "=========================================="
echo "Scanning $host"
echo "=========================================="
for port in {21,22,80}
do
echo "" > /dev/tcp/$host/$port && echo "Port $port is open"
done 2>/dev/null
done
有些人建议使用telnet
或NetCat
,但我更喜欢不安装任何新软件包。那么,有没有办法通过多线程或其他方式加快速度。
答案 0 :(得分:2)
您可以使用GNU Parallel并行运行所有检查。我不是最好的使用它,@ OleTange(作者)通常必须纠正我,但我一直在努力。所以,让我们试试你的情况,慢慢地建立它:
parallel echo {1} {2} ::: 192.168.0.1 192.168.0.8 ::: 21 22 80
192.168.0.8 22
192.168.0.8 80
192.168.0.8 21
192.168.0.1 80
192.168.0.1 22
192.168.0.1 21
对我来说看起来很有希望。然后我添加-k
以保持结果的顺序,并提供一个函数,将这些IP地址和端口作为参数:
parallel -k 'echo "" > /dev/tcp/{1}/{2} && echo {1}:{2} is open' ::: 192.168.0.1 192.168.0.8 ::: 21 22 80 2>/dev/null
192.168.0.1:80 is open
192.168.0.8:21 is open
192.168.0.8:22 is open
192.168.0.8:80 is open
如果您的CPU有8个内核,这将并行运行8个作业,但是echo
不是非常耗费资源,因此您可以并行运行32个,因此在{{1}之后添加-j 32
}。
如果您想更接近自己的脚本,可以这样做:
-k
基本上,我只是将它们发送到#!/bin/bash
hosts=(
"192.168.0.1"
"192.168.0.8"
)
for host in "${hosts[@]}"
do
for port in {21,22,80}
do
echo "(echo > /dev/tcp/$host/$port) 2>/dev/null && echo Host:$host Port:$port is open"
done
done | parallel -k -j 32
的{{1}},而不是运行您的命令,因此它可以与它们一起发挥作用。
答案 1 :(得分:1)
你可以在后台运行所有三个戳,然后等待它们全部完成,并可能将运行时间减少到1/3。
for port in 21 22 80; do
echo "" > /dev/tcp/$host/$port 2>/dev/null &
pid[$port]=$!
done
for port in 21 22 80; do
wait $pid[$port] && echo "Port $port" is open"
done
您也可以通过在后台运行多个主机来添加并行性,但这应该是一个明显的扩展。
答案 2 :(得分:1)
#!/bin/bash
function alarm {
local timeout=$1; shift;
# execute command, store PID
bash -c "$@" &
local pid=$!
# sleep for $timeout seconds, then attempt to kill PID
{
sleep "$timeout"
kill $pid 2> /dev/null
} &
wait $pid 2> /dev/null
return $?
}
function scan {
if [[ -z $1 || -z $2 ]]; then
echo "Usage: ./scanner <host> <port, ports, or port-range>"
echo "Example: ./scanner google.com 79-81"
return
fi
local host=$1
local ports=()
# store user-provided ports in array
case $2 in
*-*)
IFS=- read start end <<< "$2"
for ((port=start; port <= end; port++)); do
ports+=($port)
done
;;
*,*)
IFS=, read -ra ports <<< "$2"
;;
*)
ports+=($2)
;;
esac
# attempt to write to each port, print open if successful, closed if not
for port in "${ports[@]}"; do
alarm 1 "echo >/dev/tcp/$host/$port" &&
echo "$port/tcp open" ||
echo "$port/tcp closed"
done
}
scan $1 $2