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


353

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

这些天来,我使用的系统没有安装telnet(出于安全原因),并且默认情况下,所有主机的出站连接都被阻止。随着时间的流逝,很容易失去对哪些端口开放给哪些主机的跟踪。

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



我遇到了同样的问题。@Subhranath Chunder的回答在下面很有帮助。但是,然后我发现安装Telnet只是运行的一个小问题brew install telnet。因此,我希望Linux用户可以使用yum和进行相同的操作apt-get
Mig82

Answers:


277

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.

因此,您可以使用如下所示的内容:

xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22
SSH-2.0-OpenSSH_6.2p2 Debian-6
^C pressed here

塔阿达!


这在MinGW中似乎也起作用。例如,192.168.2.100上的远程VNC服务器通过使用“ cat </dev/tcp/192.168.2.100/5900”来响应“ RFB 003.008”。
彼得·莫滕森

1
@lornix,好的,但是在这种情况下,我必须使用不带-z选项的nc才能获得相同的结果,但仍然无法正常工作:#nc -v -w5 127.0.0.1 18080连接至127.0.0.1 18080端口[tcp / *]成功!#cat </dev/tcp/127.0.0.1/18080只是挂起而没有任何结果。只想了解我何时可以使用“ / dev / tcp / host / port”选项
亚历山大

5
@Alexandr ...实际上,“挂起没有任何结果”是几乎可以预期的行为。 正在等待输入。 nc具有额外的智能功能,使其能够感知无数据挂起并停止尝试。 不是聪明。试试看cat < /dev/tcp/localhost/22,您应该得到sshd标头。显然,端口18080上的进程在发送任何内容之前先等待某些内容进入。端口22(ssh)向您问好它的版本和其他内容。试试看!
lornix

1
@lornix,非常感谢您的解释!现在限制很明确了。我认为使用nc应该是检查端口的首选方法。
亚历山大

2
当使用未安装任何东西的Docker容器时,这非常有用。能够快速验证容器是否可以通过DNS访问非容器化的数据库。例如:cat </ dev / tcp / hostname / 5432
Michael Hobbs

404

很好,很冗长!从手册页。
单端口:

nc -zv 127.0.0.1 80

多个端口:

nc -zv 127.0.0.1 22 80 8080

端口范围:

nc -zv 127.0.0.1 20-30

6
似乎是最好的答案,谢谢。;-)
lpapp 2014年

6
当在Ubuntu 14.04(Trusty Tahr)上尝试将远程服务器(相同的LAN)用于关闭的端口(在127秒后超时)时,此方法挂起-因此不适用于脚本。不过,对于端口已打开的服务,它确实起作用。使用选项“ -w2”可能是解决方案。
彼得·莫滕森

6
对UDP端口使用-u选项。
伊夫伦

8
在6.4版的ncat -z中,无法识别。我没有z就可以做到
smishra

5
您可以使用以下方法检查多个范围:nc -zv 127.0.0.1 22,80,8080,20-30,443-446(nc版本:1.107-4)。
bobbel '17

102

Netcat是一个有用的工具:

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

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


这是一个比我自己的答案更为优雅和可脚本化的答案。对于我来说,不幸的是,那些具有安全意识的系统管理员telnet也拒绝了nc(尽管-奇怪的是-不是curlor wget)。
史蒂夫HHH

是的,那是完全任意和愚蠢的。
thnee

3
FOR语句开始!
乍得哈里森

1
当在Ubuntu 14.04(Trusty Tahr)上尝试将远程服务器(相同的LAN)用于关闭的端口(大约127秒后超时)时,此方法挂起-因此不适用于脚本。但是对于打开端口的服务,它确实起作用,返回0。使用选项“ -w2”可能是解决方案。
彼得·莫滕森

1
我认为-G 2更适合TCP超时
AB

58

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

例子

假设我的网络上有一个名为的主机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

之所以要这样用echo > /dev/...括号括起来,(echo > /dev/...)是因为如果不这样做,则在测试连接断开的情况下,将显示这些类型的消息。

$ (echo > /dev/tcp/skinner/223) && echo hi
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused

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


太好了 希望它能获得最高票。我只在页面下方阅读了此内容,因为在关闭它之前我不小心滚动了它。
Still.Tony 2015年

@ Okuma.Tony-是的,Q总是一个问题,它有很多答案8-)。感谢您的反馈,不胜感激。
slm 2015年

46

我发现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

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

$ curl http://10.0.0.99:5672
curl: (56) Failure when receiving data from the peer
AMQP

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


5
如果curl不可用,则可能是wget。wget -qS -O- http://ip.add.re.ss:port应该有效地做同样的事情。
CVn

4
甚至可以使用主机名(例如)。curl myhost:22
에이바2014年

这可能是不正确的。我正在运行一个tomcat服务,但收到404错误。#curl -k 192.168.194.4:6443 <html> <head> <title> Apache Tomcat / 7.0.34-错误报告</ title> <style> <!-H1 --- HR {color:#525D76;} -> </ style> </ head> <body> <h1> HTTP状态404-/ </ h1> <HR size =“ 1” noshade =“ noshade”> <p> <b>类型</ b>状态报告</ p> <p> <b>消息</ b> <u> / </ u> </ p> <p> <b>描述</ b> <u>请求的资源不可用。 </ u> </ p> <HR size =“ 1” noshade =“ noshade”> <h3> Apache Tomcat / 7.0.34 </ h3> </ body> </ html>

用类似的方法查看我的帖子
kenorb 2015年

12
[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!

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


1
是的,这样更好-封闭端口几乎立即超时。
彼得·莫滕森

1
这是否总是使用TCP还是有办法让它检查UDP?
kmoe


6

我整天都在努力,因为这些答案似乎都不适合我。问题在于最新版本的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)

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


4

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

timeout 1 bash -c '</dev/tcp/127.0.0.1/22 && echo Port is open || echo Port is closed' || echo Connection timeout

卷毛的另一种方法可以到达任何端口

curl telnet://127.0.0.1:22

3

这是一个函数,它将根据系统上安装的内容选择一种方法:

# 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

2

它不应该在您的包装盒上提供,但请尝试使用nmap


4
nmap是一个很好的工具,但在这些系统上不可用。nmap我希望能够找到一种使用大多数Linux安装中可用的现有工具的方法,而不是下载,编译,将其安装到我的主目录,然后将其复制到所有其他系统。
史蒂夫HHH

1

供参考,扩展@peperunas的答案:

使用nmap进行测试的方法是:

nmap -p 22 127.0.0.1

(上面的示例使用localhost进行演示)


0

如果您要在系统上进行更多测试,则可以使用我们的测试工具dda-serverspec(https://github.com/DomainDrivenArchitecture/dda-serverspec-crate)执行此类任务。您可以定义您的期望

{:netcat [{:host "mywebserver.com" :port "443"}
          {:host "telnet mywebserver.com" :port "80"}
          {:host "telnet mywebserver.com" :port "8443"}]}

并针对localhost或远程主机(通过ssh连接)测试这些期望。对于远程测试,您必须定义一个目标:

{:existing [{:node-name "test-vm1"
             :node-ip "35.157.19.218"}
            {:node-name "test-vm2"
             :node-ip "18.194.113.138"}]
 :provisioning-user {:login "ubuntu"}}

您可以使用 java -jar dda-serverspec.jar --targets targets.edn serverspec.edn

在幕后,我们使用上面介绍的netcat ...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.