如何在 Linux 或 Unix 上检查端口是否正在使用
验证哪些端口正在监听服务器的网络接口非常重要。您需要注意打开的端口以检测入侵。除了入侵之外,为了进行故障排除,可能需要检查服务器上的其他应用程序是否已在使用端口。例如,您可能在同一系统上安装 Apache 和 Nginx 服务器。因此,有必要知道 Apache 或 Nginx 是否正在使用 TCP 端口 # 80/443。本快速教程提供了使用 netstat、nmap 和 lsof 命令检查正在使用的端口并查看正在使用该端口的应用程序的步骤。
教程详细信息 | |
---|---|
难度等级 | 简单的 |
Root 权限 | 是的 |
要求 | Linux 或 Unix 终端 |
类别 | 网络实用程序 |
先决条件 | lsof/ss/netstat 命令 |
操作系统兼容性 | *BSD • Linux • macOS • Unix • WSL |
预计阅读时间 | 8 分钟 |
如何检查端口是否正在使用
要检查Linux上的监听端口和应用程序:
- 打开终端应用程序,即 shell 提示符。
- 在 Linux 上运行以下任意一个命令即可查看开放的端口:
$ sudo lsof -i -P -n | grep LISTEN
$ sudo netstat -tulpn | grep LISTEN
$ sudo ss -tulpn | grep LISTEN
$ sudo lsof -i:22 ## see a specific port such as 22 ##
$ sudo nmap -sTU -O IP-address-Here - 对于最新版本的 Linux,请使用 ss 命令。例如,ss -tulw
让我们详细了解命令及其输出。
选项 #1:lsof 命令
语法是:
示例输出:
$ sudo lsof -i -P -n
$ sudo lsof -i -P -n | grep LISTEN
$ doas lsof -i -P -n | grep LISTEN # OpenBSD #
图01:使用 lsof 命令检查监听端口和应用程序
sshd 85379 root 3u IPv4 0xffff80000039e000 0t0 TCP 10.86.128.138:22 (LISTEN)
- sshd是应用程序的名称。
- 10.86.128.138是 sshd 应用程序绑定到的 IP 地址(LISTEN)
- 22正在使用的 TCP 端口(LISTEN)
- 85379是 sshd 进程的进程 ID
查看 Internet 网络服务列表
/etc/services是一个文本文件,用于映射互联网服务的人性化文本名称及其底层分配的端口号和协议类型。使用cat 命令或 more 命令/less 命令查看它:
$ less /etc/services
示例文件:
tcpmux 1/tcp # TCP port service multiplexer echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null systat 11/tcp users daytime 13/tcp daytime 13/udp netstat 15/tcp qotd 17/tcp quote chargen 19/tcp ttytst source chargen 19/udp ttytst source ftp-data 20/tcp ftp 21/tcp fsp 21/udp fspd ssh 22/tcp # SSH Remote Login Protocol telnet 23/tcp smtp 25/tcp mail time 37/tcp timserver time 37/udp timserver whois 43/tcp nicname tacacs 49/tcp # Login Host Protocol (TACACS) tacacs 49/udp domain 53/tcp # Domain Name Server domain 53/udp
每行描述一项服务,格式如下:
#service-name port/protocol [aliases ...] ssh 22/tcp # SSH Remote Login Protocol time 37/tcp timserver
选项 #2:netstat 或 ss 命令
您可以使用netstat检查监听端口和应用程序,如下所示。
Linux netstat 语法
默认情况下,您的系统上可能未安装netstat命令。因此,请使用Alpine Linux 上的apk 命令、 RHEL 等上的dnf 命令/ yum 命令、Debian、Ubuntu 等上的apt 命令/ apt-get 命令、SUSE/OpenSUSE 上的 zypper 命令、Arch Linux 上的 pacman 命令来安装netstat。
$ netstat -tulpn | grep LISTEN
$ netstat -tulpn | more
$ netstat -tulpn | grep ':443'
- -t:选择所有 TCP 端口
- -u:选择所有 UDP 端口
- -l:显示监听服务器套接字(以列表状态打开 TCP 和 UDP 端口)
- -p:显示套接字的 PID/程序名称。换句话说,此选项告诉谁打开了 TCP 或 UDP 端口。例如,在我的系统上,Nginx 打开了 TCP 端口 80/443,因此我将 /usr/sbin/nginx 或其 PID。
- -n:不解析名称(避免 DNS 查找,这会加快繁忙的 Linux/Unix 服务器上的 netstat 速度)
netstat 命令在 Linux 上已弃用一段时间。因此,您需要使用 ss 命令,如下所示:
其中,ss 命令选项如下:
$ sudo ss -tulw
$ sudo ss -tulwn
$ sudo ss -tulwn | grep LISTEN
- -t:仅显示 Linux 上的 TCP 套接字
- -u:仅显示 Linux 上的 UDP 套接字
- -l:显示正在监听的套接字。例如,SSHD 服务器打开了 TCP 端口 22。
- -p:列出打开套接字的进程名称
- -n:不解析服务名称,即不使用 DNS
FreeBSD/macOS(OS X)netstat 语法
语法如下:
您也可以在 macOS 或 FreeBSD 上使用 sockstat 命令来显示打开的 TCP 或 UDP 端口。例如:来自我的FreeBSD 服务器版本13.xx
的输出:
$ netstat -anp tcp | grep LISTEN
$ netstat -anp udp | grep LISTEN
{vivek@freebsd13-server:~}$ sudo sockstat -4 -6 -l
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS root master 1723 13 tcp4 127.0.0.1:25 *:* root master 1723 14 tcp4 192.168.2.20:25 *:* root sshd 1627 3 tcp6 *:22 *:* root sshd 1627 4 tcp4 *:22 *:* ntpd ntpd 1615 20 udp6 *:123 *:* ntpd ntpd 1615 21 udp4 *:123 *:* ntpd ntpd 1615 22 udp4 192.168.2.20:123 *:* ntpd ntpd 1615 23 udp6 ::1:123 *:* ntpd ntpd 1615 24 udp6 fe80::1%lo0:123 *:* ntpd ntpd 1615 25 udp4 127.0.0.1:123 *:* ntpd ntpd 1615 26 udp4 172.16.0.5:123 *:* root syslogd 1085 6 udp6 *:514 *:* root syslogd 1085 7 udp4 *:514 *:* ? ? ? ? udp4 *:17890 *:* ? ? ? ? udp6 *:17890 *:*
OpenBSD netstat 语法
$ netstat -na -f inet | grep LISTEN
$ netstat -nat | grep LISTEN
选项 #3:nmap 命令
语法是:
$ sudo nmap -sT -O localhost
# search for open port IP address 192.168.2.13
$ sudo nmap -sU -O 192.168.2.13 ##[ list open UDP ports ]
$ sudo nmap -sT -O 192.168.2.13 ##[ list open TCP ports ]
图 02:使用 nmap 确定哪些端口正在监听 TCP 连接
$ sudo nmap -sTU -O 192.168.2.13
关于 Windows 用户的说明
您可以使用以下命令检查 Windows 操作系统的端口使用情况:
$ netstat -bano | more
$ netstat -bano | grep LISTENING
$ netstat -bano | findstr /R /C:"[LISTEING]"
使用 Bash 脚本测试端口是否打开
使用 Bash 时,可以使用“ /dev/tcp/{HostName}_OR_{IPAddrress}>/{port} ”语法检查 Linux 或 Unix 计算机上的 TCP 端口是否打开。换句话说,以下是 Bash 特有的功能。让我们看看 localhost 和 192.168.2.20 上的 TCP 端口 22 是否打开:
现在我们可以构建一些逻辑,如下所示:
$ (echo >/dev/tcp/localhost/23) &>/dev/null && echo "open" || echo "close"
$ (echo >/dev/tcp/192.168.2.20/22) &>/dev/null && echo "open" || echo "close"
#!/bin/bash dest_box="aws-prod-server-42" echo "Testing the ssh connectivity ... " if ! (echo >/dev/tcp/$dest_box/22) &>/dev/null then echo "$0 cannot connect to the $dest_box. Check your vpn connectivity." else echo "Running the ansible playboook ..." ansible-playbook -i hosts --ask-vault-pass --extra-vars '@cluster.data.yml' main.yaml fi
如果我不使用 Bash 会怎样?
尝试如下 nc 命令:
更新后的 Bash 脚本:
$ nc -w {timeout} -zv {server_IP_hostname} {tcp_port} &>/dev/null && echo "Open" || echo "Close"
$ nc -w 5 -zv 192.168.2.20 23 &>/dev/null && echo "TCP/23 Open" || echo "TCP/23 Close"
#!/bin/bash dest_box="aws-prod-server-42" timeout="5" # timeouts in seconds echo "Testing the ssh connectivity in $timeout seconds ... " # make sure 'nc' is installed, else die .. if ! type -a nc &>/dev/null then echo "$0 - nc command not found. Please install nc and run the script again." exit 1 fi if ! nc -w "$timeout" -zv "${dest_box}" 22 &>/dev/null then echo "$0 cannot connect to the $dest_box. Check your vpn connectivity." exit 1 else echo "Running the ansible playboook ..." ansible-playbook -i hosts --ask-vault-pass --extra-vars '@cluster.data.yml' main.yaml fi
使用 Perl 检查 Linux 或 Unix 中的 TCP 端口是否打开
下面是一个 Perl 脚本,使用IO::Socket::INET检查OpenSSH 的 TCP 端口 22 是否打开,超时时间为 5 秒:
#!/usr/bin/perl -w use IO::Socket::INET; # Set server name and port here $my_server="192.168.2.20"; $my_server_tcp_port="22"; # make a new object my $server_test = IO::Socket::INET->new( PeerAddr => "$my_server", PeerPort => "$my_server_tcp_port", Proto => 'tcp', Timeout => 5 ); # test it and die or continue as per your needs if ($server_test) { print "TCP port $my_server_tcp_port is open for the $my_server.\n"; print "Now doing something ...\n"; close $server_test; } else { print "TCP port $my_server_tcp_port is closed or timed out for the $my_server.\n"; }
Python 示例检查 Linux 或 Unix 中 TCP 端口是否打开
尝试一下这个使用低级套接字网络功能的简单代码。例如:
#!/usr/bin/python3 # Tested on Python 3.6.xx and 3.8.xx only (updated from Python 2.x) import socket # Create a new function def check_server_tcp_port(my_host_ip_name, my_tcp_port, timeout=5): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(timeout) try: s.connect((my_host_ip_name, my_tcp_port)) print(f"TCP port {my_tcp_port} is open for the {my_host_ip_name}.") s.close() return True except socket.timeout: print(f"TCP port {my_tcp_port} is closed or timed out for the {my_host_ip_name}.") return False # Test it check_server_tcp_port("localhost", 22) check_server_tcp_port("192.168.2.20", 22)
结论
本页解释了用于确定 Linux 或类 Unix 服务器上端口是否正在使用的命令。有关更多信息,请参阅此处的nmap 命令和 lsof 命令在线页面,或键入 man 命令,如下所示:
$ man lsof
$ man ss
$ man netstat
$ man nmap
$ man 5 services
$ man nc