Shell脚本端口扫描程序

时间:2015-03-03 08:18:54

标签: shell port-scanning

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

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

有些人建议使用telnetNetCat,但我更喜欢不安装任何新软件包。那么,有没有办法通过多线程或其他方式加快速度。

3 个答案:

答案 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