2

我想扫描多个主机中的多个端口。我使用了这个脚本,但显示结果需要很长时间。

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

有些人建议使用telnetorNetCat代替,但我更喜欢在不安装任何新软件包的情况下这样做。那么,有什么方法可以通过多线程或其他方式来加速它。

4

3 回答 3

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 个,因此-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

基本上,我不是运行你的命令,而是将它们发送到stdinof,parallel这样它就可以用它们来发挥它的魔力。

于 2015-03-03T09:47:42.090 回答
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

您也可以通过在后台运行多个主机来添加并行性,但这应该是一个明显的扩展。

于 2015-03-03T08:36:30.077 回答
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
于 2018-05-06T11:08:01.997 回答