测试远程系统上的端口是否可访问(无需 telnet)

Ste*_*HHH 430 networking linux port

在过去,我们过去常常telnet查看远程主机上的端口是否打开:telnet hostname port会尝试连接到任何主机上的任何端口并让您访问原始 TCP 流。

这些天,我工作的系统没有安装 telnet(出于安全原因),并且默认情况下会阻止所有主机的所有出站连接。随着时间的推移,很容易忘记哪些端口对哪些主机开放。

是否有另一种方法来测试远程系统上的端口是否打开——使用安装了数量有限的软件包telnet且不可用的 Linux 系统?

小智 481

好看又啰嗦!从手册页。
单端口:

nc -zv 127.0.0.1 80
Run Code Online (Sandbox Code Playgroud)

多个端口:

nc -zv 127.0.0.1 22 80 8080
Run Code Online (Sandbox Code Playgroud)

端口范围:

nc -zv 127.0.0.1 20-30
Run Code Online (Sandbox Code Playgroud)

  • 对 UDP 端口使用 -u 选项。 (8认同)
  • 无法识别 ncat -z 的 6.4 版。我可以不用 z (8认同)
  • 当在 [Ubuntu 14.04](https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_14.04_LTS_.28Trusty_Tahr.29) (Trusty Tahr) 上尝试关闭端口(它定时127 秒后退出) - 因此不太适合在脚本中使用。但它确实适用于打开端口的服务。使用选项“-w2”可能是解决方案。 (7认同)
  • 您可以使用以下命令检查多个范围:`nc -zv 127.0.0.1 22,80,8080,20-30,443-446`(nc 版本:1.107-4)。 (6认同)
  • 完美的!这输出一条明确的连接成功/失败消息,只有一行。请注意,多个范围似乎不适用于我的 ``nc`` 版本;仅测试第一个范围。 (2认同)
  • 太好了,但前提是 nc 确实安装了 (2认同)

lor*_*nix 350

Bash 已经能够访问TCPUDP端口一段时间了。从手册页:

/dev/tcp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a TCP connection to the corresponding socket.
/dev/udp/host/port
    If host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a UDP connection to the corresponding socket.
Run Code Online (Sandbox Code Playgroud)

所以你可以使用这样的东西:

xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22
SSH-2.0-OpenSSH_6.2p2 Debian-6
^C pressed here
Run Code Online (Sandbox Code Playgroud)

哒哒!

  • @Alexandr...实际上,“挂起而没有任何结果”几乎是预期的行为。**cat** 正在等待输入。**nc** 具有额外的智能,使其能够感知无数据挂起并停止尝试。**猫** 并不_相当_聪明。试试 `cat &lt; /dev/tcp/localhost/22`,你应该得到你的 sshd 标头。显然,您在端口 18080 上的进程在发送任何内容之前等待某些内容进入。端口 22 (**ssh**) 用它的版本和诸如此类的东西来迎接你。试试看! (6认同)
  • 当使用没有安装任何东西的 docker 容器时,这非常有用。能够快速验证容器是否可以通过 DNS 访问非容器化数据库。示例:cat &lt; /dev/tcp/hostname/5432 (4认同)
  • @lornix,好的,但在这种情况下,我必须使用不带 -z 选项的 nc 得到相同的结果,但它仍然不起作用: # nc -v -w5 127.0.0.1 18080 Connection to 127.0.0.1 18080 port [tcp /*]成功了!# cat &lt; /dev/tcp/127.0.0.1/18080 只是挂起,没有任何结果。只是想了解何时可以使用“/dev/tcp/host/port”选项 (2认同)

thn*_*nee 112

Netcat 是一个有用的工具:

nc 127.0.0.1 123 &> /dev/null; echo $?

0如果端口 123 打开,1如果关闭,将输出。

  • 这是一个比我自己的答案更加优雅和可编写脚本的答案。对我来说不幸的是,那些具有安全意识的系统管理员保留了“telnet”,也保留了“nc”(尽管奇怪的是,不是“curl”或“wget”)。 (3认同)
  • 让 `FOR` 语句开始! (3认同)
  • 当在 [Ubuntu 14.04](https://en.wikipedia.org/wiki/List_of_Ubuntu_releases#Ubuntu_14.04_LTS_.28Trusty_Tahr.29) (Trusty Tahr) 上尝试关闭端口(它定时大约 127 秒后退出) - 因此不太适合在脚本中使用。但它确实适用于打开端口的服务,返回 0。使用选项“-w2”可能是解决方案。 (2认同)

slm*_*slm 69

不使用其他工具(例如 )的最简单方法如socat上面@lornix 的回答中所述。这只是添加一个实际示例,说明/dev/tcp/...如果您想测试另一台服务器是否具有可通过命令行访问的给定端口,则如何在 Bash 中使用伪设备。

例子

假设我的网络上有一个名为skinner.

$ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \
    && echo "It's up" || echo "It's down"
It's up

$ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \
    echo "It's up" || echo "It's down"
It's down
Run Code Online (Sandbox Code Playgroud)

您想像这样将echo > /dev/...括号括起来的原因(echo > /dev/...)是,如果您不这样做,那么通过对断开的连接进行测试,您将看到这些类型的消息。

$ (echo > /dev/tcp/skinner/223) && echo hi
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused
Run Code Online (Sandbox Code Playgroud)

这些不能简单地重定向到,/dev/null因为它们来自尝试将数据写入设备/dev/tcp。因此,我们在子命令中捕获所有输出,即(...cmds...)并重定向子命令的输出。

  • 这太棒了。希望它能被选为最高层。我只读到了页面的最下方,因为我在关闭页面之前不小心滚动了它。 (2认同)

Ste*_*HHH 53

我发现这curl可能以类似于 的方式完成工作telnetcurl甚至会告诉您侦听器期望哪种协议。

从主机名和端口构造一个 HTTP URI 作为 的第一个参数curl。如果curl可以连接,它将报告协议不匹配并退出(如果侦听器不是 Web 服务)。如果curl无法连接,它将超时。

例如,主机 10.0.0.99 上的端口 5672 被防火墙关闭或阻止:

$ curl http://10.0.0.99:5672
curl: (7) couldn't connect to host
Run Code Online (Sandbox Code Playgroud)

但是,从不同的系统,可以访问主机 10.0.0.99 上的端口 5672,并且似乎正在运行 AMQP 侦听器。

$ curl http://10.0.0.99:5672
curl: (56) Failure when receiving data from the peer
AMQP
Run Code Online (Sandbox Code Playgroud)

区分不同的消息很重要:第一次失败是因为curl无法连接到端口。第二次失败是成功测试,但curl预期是 HTTP 侦听器而不是 AMQP 侦听器。

  • 如果 curl 不可用,则 wget 可能可用。`wget -qS -O- http://ip.add.re.ss:port` 应该有效地做同样的事情。 (6认同)
  • 这甚至适用于主机名,例如。`curl myhost:22`。 (4认同)

小智 14

[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.193.173 6443
nc: connect to 192.168.193.173 port 6443 (tcp) failed: Connection refused

[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.194.4 6443
Connection to 192.168.194.4 6443 port [tcp/sun-sr-https] succeeded!
Run Code Online (Sandbox Code Playgroud)

希望它能解决您的问题:)


ken*_*orb 12

这是单线:

</dev/tcp/localhost/11211 && echo Port is open || echo Port is closed
Run Code Online (Sandbox Code Playgroud)

使用@lornix answer 中解释的 Bash 语法。

欲了解更多信息,请查看:高级Bash脚本编程指南:29章/dev/proc


小智 9

我挣扎了一整天,因为这些答案似乎都不适合我。问题是最新版本的nc不再具有该-z标志,而当无法访问主机时,通过 TCP 的直接访问(根据@lornix 和@slm)会失败。我最终找到了这个页面,在那里我终于找到了两个工作示例:

  1. nc -w1 127.0.0.1 22 </dev/null

    -w标志负责超时,并</dev/null替换-z标志)

  2. timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'

    timeout命令负责超时,其余来自@slm)

然后,只需使用&&和/或||(甚至$?)来提取结果。希望有人会发现这些信息有用。


Mig*_*ira 9

结合@kenorb 和@Azukikuru 的答案,您可以测试端口打开/关闭/防火墙。

timeout 1 bash -c '</dev/tcp/127.0.0.1/22 && echo Port is open || echo Port is closed' || echo Connection timeout
Run Code Online (Sandbox Code Playgroud)

使用 curl 到达任何端口的另一种方法

curl telnet://127.0.0.1:22
Run Code Online (Sandbox Code Playgroud)


小智 6

下面的函数将根据系统上安装的内容选择一种方法:

# Check_port <address> <port> 
check_port() {
if [ "$(which nc)" != "" ]; then 
    tool=nc
elif [ "$(which curl)" != "" ]; then
     tool=curl
elif [ "$(which telnet)" != "" ]; then
     tool=telnet
elif [ -e /dev/tcp ]; then
      if [ "$(which gtimeout)" != "" ]; then  
       tool=gtimeout
      elif [ "$(which timeout)" != "" ]; then  
       tool=timeout
      else
       tool=devtcp
      fi
fi
echo "Using $tool to test access to $1:$2"
case $tool in
nc) nc -v -G 5 -z -w2 $1 $2 ;;
curl) curl --connect-timeout 10 http://$1:$2 ;;
telnet) telnet $1 $2 ;;
gtimeout)  gtimeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
timeout)  timeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
devtcp)  </dev/tcp/${1}/${2} && echo Port is open || echo Port is closed ;;
*) echo "no tools available to test $1 port $2";;
esac

}
export check_port
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您安装了curl:

curl -v telnet://$host:$port/$path
Run Code Online (Sandbox Code Playgroud)

  • (1) 我认为您的意思是“curl -v telnet://”、**`:`** 和(最后的)`/` 是字面意思,而 `$host` 和 `$port ` 是相关主机的名称/地址和相关端口号的占位符。用户应该使用什么作为“$path”? (2) 如果端口打开,但未实现 HTTP,则我们可以预期此命令会失败。那么如何区分由于端口未打开而导致的失败和由于端口不是 HTTP 而导致的失败呢? ……(续) (2认同)