检查远程端口是否开放
网络连通性验证,是服务器环境搭建的重要任务之一。检查目标机器的服务端口是否可连通,常见的端口检测方法有 telnet、nc 等方法,并提供了一份批量检测脚本,整理如下。
telnet
telnet 是最普遍的方法。非常简单,语法如下:
telnet $host $port
输出如下,表示端口联通(通过ctl+]
退出):
maoshuai@ms:/tmp$ telnet 127.0.0.1 22
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
如下,表示端口不通:
maoshuai@ms:/tmp$ telnet 127.0.0.1 222
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
nc
telnet 是交互式的,适合单次手工检测,对于批量检测,利用nc更为方便。基本用法如下:
nc -z $host $port
然后检测上述命令的exit code,为0表示可联通,否则表示不联通:
maoshuai@ms:/tmp$ nc -z 127.0.0.1 22
maoshuai@ms:/tmp$ echo $?
0
maoshuai@ms:/tmp$ nc -z 127.0.0.1 222
maoshuai@ms:/tmp$ echo $?
1
假如需要检测一批IP下的端口是否联通,可以用下面的脚本:
#!/bin/bash
# checking network connectivity
# IPs and ports to check
# Ignore blank lines and treat hash sign as comments
# comments will be kept as a comment of result
IP_PORT="
# local host
127.0.0.1 22
127.0.0.1 21
# well known sites
www.google.com 80
www.baidu.com 80
"
# checking
echo "$IP_PORT" | grep -Ev "^$" |
while read line;do
# simply print comment line
echo "$line" | grep -qE "^#"
if [ $? -eq 0 ];then
echo "$line"
continue
fi
# normal line with ip and port
connectFlag="DOWN"
nc -z -w 1 $line
if [ $? -eq 0 ];then
connectFlag="UP"
fi
printf "%-20s %5s %5s\n" $line $connectFlag
done
上述脚本,可能输出如下,最后一列UP表示联通,否则DOWN为不通:
# local host
127.0.0.1 22 UP
127.0.0.1 21 DOWN
# well known sites
www.google.com 80 UP
www.baidu.com 80 UP
脚本中增加了-w
选项,用于控制最大探测超时时间为1秒。
当然,也可以通过-v
选项直接输出探测信息,适合单次手工查验,:
maoshuai@ms:/tmp$ nc -zv 127.0.0.1 22
Connection to 127.0.0.1 22 port [tcp/ssh] succeeded!
maoshuai@ms:/tmp$ nc -zv 127.0.0.1 222
nc: connect to 127.0.0.1 port 222 (tcp) failed: Connection refused
通过写入设备文件
由于Linux里,一切都是文件,网络连接也对应一个文件。因此可以通过直接写入文件判断端口是否联通。
这种方法有点awkward,但是最兼容的方法。如果所在的服务器中没有安装nc甚至telnet命令(比如某些docker容器中),用法如下:
echo > /dev/tcp/$host/$port
判断上述命令的退出码:
maoshuai@ms:/dev$ echo > /dev/tcp/127.0.0.1/22
maoshuai@ms:/dev$ echo $?
0
maoshuai@ms:/dev$ echo > /dev/tcp/127.0.0.1/222
bash: connect: Connection refused
bash: /dev/tcp/127.0.0.1/222: Connection refused
maoshuai@ms:/dev$ echo $?
1
当然,也可以通过脚本,批量检测:
#!/bin/bash
# checking network connectivity
# IPs and ports to check
# Ignore blank lines and treat hash sign as comments
# comments will be kept as a comment of result
IP_PORT="
# local host
127.0.0.1 22
127.0.0.1 21
# well known sites
www.google.com 80
www.baidu.com 80
"
# checking
echo "$IP_PORT" | grep -Ev "^$" |
while read line;do
# simply print comment line
echo "$line" | grep -qE "^#"
if [ $? -eq 0 ];then
echo "$line"
continue
fi
# normal line with ip and port
connectFlag="DOWN"
ip=$(echo $line | awk '{print $1}')
port=$(echo $line | awk '{print $2}')
(echo > /dev/tcp/$ip/$port) >/dev/null 2>&1
if [ $? -eq 0 ];then
connectFlag="UP"
fi
printf "%-20s %5s %5s\n" $line $connectFlag
done
输出结果和第一个方法一样,但有个地方注意,必须用bash执行写入。
在服务部署前检测端口
有些情况,我们需要在服务部署前检测该服务的端口是否可访问。问题是此时这个端口并没有被监听,直接检测的结果自然是不通,我们需要排除,这不是因为网络本身不通(比如有防火墙)造成的。
一种办法是,在目标机器的该端口部署一个简单的监听,而nc
命令恰巧可以完成,参数-l
表示监听,后面跟着监听的端口:
nc -l 22
然后我们再次运行之前的脚本,会发现22端口显示为UP了。
参考文档
- Check whether a remote server port is open on Linux
- Test from shell script if remote TCP port is open
- bash and /dev/tcp - how does that work ?
- 5 Linux Utility to Test Network Connectivity
-------------------------
本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可。转载请注明来源:https://wiki.imshuai.com/remoe-server-port-checking.html 欢迎指正或在下方评论。