Linux 查看开放端口:ss、netstat、lsof、nmap
- 2026年9月15日
- 09:00
- 作者: Adrien Roche
- 更新于 2026年10月3日
- 网络

用 ss 检查开放端口,当前的标准做法
Linux 系统上每一个开放端口都源于某个进程请求内核在其上监听。如今用来查看这些套接字的工具是 ss(socket statistics),它属于 iproute2 套件,每个现代发行版都已安装。一条命令即可覆盖大多数场景:
sudo ss -tulpn每个选项各司其职:
-t:包含 TCP 套接字-u:包含 UDP 套接字-l:仅显示监听中的套接字(去掉它还会显示已建立的连接)-p:显示占用每个套接字的进程;这正是需要sudo的原因,否则只能看到你自己的进程-n:数字化输出,打印:22而不是:ssh,并跳过反向 DNS 查询,命令也因此更快
典型的一行输出如下所示:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=712,fd=3))从安全角度看,Local Address 列才是关键。0.0.0.0:22 表示该套接字在所有 IPv4 接口上接受连接,[::]:22 是其 IPv6 等价形式,而 127.0.0.1:5432 表示服务只在回环地址上响应,完全无法从网络访问。
几个值得记住的变体:
ss -tlnp # TCP listeners only
ss -ulnp # UDP listeners only
sudo ss -tlnp 'sport = :22' # who is listening on port 22
ss -tn state established # active TCP connections right nownetstat 仍可用,但已属遗留工具
无数教程至今仍在写 netstat -tulpn,其选项与上面的 ss 命令一一对应,所以肌肉记忆在两个方向都能迁移。差别在底层:netstat 属于处于维护模式的 net-tools 包,通过读取 /proc 文件工作,而 ss 经由 netlink 直接查询内核,在同时处理数千套接字的机器上明显更快。
多数当前发行版已不再默认安装 net-tools。如果你确实需要它:
sudo netstat -tulpn
# if the command is missing:
sudo apt install net-tools # Debian / Ubuntu
sudo dnf install net-tools # RHEL / Fedora没有理由在新服务器上安装它。把 netstat 当作接手旧系统时的兼容性备选,其他场合一律使用 ss。
lsof:从进程视角看端口
在 Linux 上一切皆文件,网络套接字也不例外,因此 lsof(list open files)也能充当端口检查工具。当你习惯以进程而非端口来思考时,它尤为好用:
sudo lsof -i -P -n # every process with a network socket
sudo lsof -iTCP -sTCP:LISTEN -P -n # TCP listeners only
sudo lsof -i :443 # everything touching port 443-P 与 -n 分别关闭端口名和主机名解析,思路与 ss -tulpn 里的 -n 相同。第三种形式最常用:指定一个端口,就能在一张易读的表里得到命令名、PID、用户和文件描述符。与 ss 不同,lsof 还会在列出监听者的同时列出每个进程已建立的连接,这在你想知道当前是谁在与某个服务通信、而不仅是该服务存在时很有帮助。
nmap:监听不等于可访问
到目前为止的一切只回答了一个问题:这台机器上有什么在监听。而对安全更重要的是另一个问题:从外部实际能访问到什么。两份清单很少完全一致,因为主机防火墙、服务商层面的过滤以及仅绑定回环的做法都会在两者之间造成落差。这也解释了为什么自己扫自己意义不大:nmap localhost 走的是回环接口,完全绕过外部防火墙规则,会心安理得地报告攻击者永远触及不到的服务。
请从另一台机器发起扫描,目标指向服务器的公网 IP:
nmap 203.0.113.10 # top 1000 TCP ports
nmap -p- 203.0.113.10 # all 65535 TCP ports
sudo nmap -sU --top-ports 100 203.0.113.10 # common UDP ports (slow)nmap 报告的三种状态值得理解:open 表示有服务响应,closed 表示数据包已到达但该处无人监听,filtered 表示数据包被静默丢弃,几乎总是防火墙所为。ss 显示为 LISTEN 而远程 nmap 报告为 filtered 的端口,正是防火墙正常工作的样子。有一条规则毫无例外:只扫描你拥有或已获明确授权测试的主机。
精确找出占用端口的进程
假设有什么东西霸占了 8080 端口,导致你的应用无法绑定。有三条路可以找到 PID:
sudo ss -tlnp 'sport = :8080'
sudo lsof -i :8080
sudo fuser -v 8080/tcpfuser 最为简洁:它打印 PID,加上 -v 还会给出用户和命令名。它甚至可以用 fuser -k 8080/tcp 直接杀死占用者,但那只是发送信号、不做任何服务层面的清理,所以应视为最后手段。拿到 PID 后,ps -fp PID 会显示完整命令行,systemctl status PID 则告诉你是哪个 systemd 单元启动了它。
当你手上完全没有工具时(例如一个精简的容器镜像),内核自己的表始终在那里:cat /proc/net/tcp。端口以十六进制显示(0016 即 22),状态 0A 表示 LISTEN。这张原始表正是其他工具解析并格式化后呈现给你的数据。
任何绑定套接字的东西都会以同样的方式出现在这些列表中,无论是数据库还是代理栈。例如一个 V2Ray inbound,也只是在你所配置端口上的又一个监听者,详见我们的 V2Ray 协议指南。
关闭开放端口:kill 还是防火墙
端口开放是因为有进程在监听,这给了你两个截然不同的手段:移除监听者,或阻断可达性。二者不可互相替代,在任何重要系统上通常都该两手一起用。
干净的做法是停止并禁用占用该套接字的服务。杀掉 PID 看着更快,却很少奏效:systemd 会自动重启受管服务,你还没重新运行 ss,端口就已经回来了。kill 只留给你手动启动的进程。要查看正在运行什么并关掉不需要的部分,我们关于 用 systemctl 列出服务 的指南完整讲解了这套流程。
sudo systemctl stop cups
sudo systemctl disable cups第二个手段交给防火墙。在 Ubuntu 上,启用 ufw 之前务必先放行 SSH,否则你会把自己锁在机器之外:
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw enable在 RHEL 系系统上,firewalld 的默认区域已经丢弃未经请求的流量;用 firewall-cmd --permanent --remove-port=8080/tcp 移除此前开放的内容,再执行 firewall-cmd --reload。有一件事并不算解决办法:把服务改到非标准端口。这能躲过最偷懒的扫描、让日志更清静,但 nmap -p- 几分钟内就能找到新端口。隐藏不等于安全:要么关闭端口,要么用防火墙拦住它。
新服务器的五分钟端口审计
在刚开通的机器上首次登录后,用 sudo ss -tulpn 做一次清点。干净的最小化安装应该几乎看不到什么:22 端口上的 sshd,以及在使用 systemd-resolved 的发行版上位于 127.0.0.53:53 的 DNS stub。其他任何东西都需要一个解释。然后按这份清单逐项处理:
- 按进程名和 PID 识别每一个监听者;禁用任何你没有主动要求的服务。
- 质疑每一个绑定到
0.0.0.0或[::]的监听:数据库和管理面板应当留在127.0.0.1,除非它们确实需要对外提供服务。 - 做到常见端口一眼即识:22 SSH、80/443 web、3306 MySQL、5432 PostgreSQL、6379 Redis。3389 端口是远程桌面;在 Linux 上它意味着 xrdp 正在运行,该端口的暴露与加固规则正是我们 RDP 3389 端口指南 的主题。
- 从你自己的机器用
nmap -p-扫描公网 IP,并将结果与ss的清单对比;每一处不一致,要么是防火墙在起作用,要么是回环绑定。 - 最后用默认拒绝的防火墙收尾,只允许你有意对外暴露的端口。
这里是整套工具箱,每样一行:
| 命令 | 显示内容 | 适用场景 |
|---|---|---|
sudo ss -tulpn | 监听中的 TCP/UDP 套接字及所属进程 | 任何机器上的日常首选查看方式 |
netstat -tulpn | 通过遗留 net-tools 得到同样的视图 | 没有 ss 的老旧系统 |
sudo lsof -i :PORT | 某一端口上的进程与连接 | 把端口与进程及其文件对应起来 |
sudo fuser -v PORT/tcp | 绑定到某端口的 PID | 快速查 PID、写脚本 |
nmap SERVER_IP(远程) | 从外部真正可访问的端口 | 验证防火墙与真实暴露面 |
cat /proc/net/tcp | 原始内核套接字表(十六进制) | 未安装任何工具的精简容器 |
只有在一台你真正拥有 root、且没有要紧东西会被弄坏的机器上,这些命令才会变成条件反射。来自 rdp.monster 的 Linux VPS 正好提供这样的沙盒:完整管理员权限、独享 CPU 与内存、无限流量(合理使用)、无需 KYC,而且服务器在付款确认后约 10 秒即上线,快到你能在咖啡放凉之前跑完第一条 ss -tulpn。
常见问题
在 Linux 上检查开放端口需要 root 权限吗?
ss -tuln 或读取 /proc/net/tcp,所以监听端口的清单从不隐藏。限制出现在 -p 选项上:没有 root 权限时,ss、lsof 和 fuser 只会显示属于你自己用户的进程,其他套接字的进程列为空。对 nmap 而言,默认的 SYN 扫描(-sS)需要 root;非特权的替代方案是连接扫描(-sT),它同样可用,只是噪音稍大一些。如何检查远程服务器上某个特定端口是否开放?
nc -zv example.com 443 会尝试建立 TCP 连接并报告成功或失败,不发送任何数据。如果没有 netcat,纯 Bash 也能做到:timeout 3 bash -c '</dev/tcp/example.com/443' && echo open。两者都只能证明有东西接受了连接:它们不说明是哪个服务在响应,也不说明它是否健康。UDP 没有可靠的快速测试方法,因为一个沉默的端口可能是 open 也可能是 filtered;这时请用 nmap -sU。为什么 ss 显示端口在监听,我却无法从外部连接?
127.0.0.1:PORT 或 [::1]:PORT 表示该服务只接受本地连接,这对数据库来说是有意为之且很常见的设置。如果它绑定在 0.0.0.0,那就是数据包在路径上某处被过滤了:可能是 ufw、firewalld 或原生 nftables 之类的主机防火墙,也可能是服务商的边缘过滤。外部 nmap 扫描把该端口报告为 filtered 即可确认存在防火墙;closed 则意味着流量到达了,但该接口上没有进程监听。一台全新的 Linux 服务器应该开放哪些端口?
sshd。位于 127.0.0.53:53 的 DNS stub 解析器(systemd-resolved)属正常现象,且从外部无法访问。云镜像有时会额外加上代理程序或监控守护进程;用 ss -tulpn 识别每个监听者,并禁用任何你没有主动要求的东西。之后安装的每个服务都应默认绑定回环,除非它确实需要对网络提供服务,同时让防火墙只放行真正需要公开的部分。Adrien Roche, 基础设施与主机托管编辑
系统工程师,拥有 10 年以上运维 Windows Server 和 Linux 集群的经验。Adrien 负责 rdp.monster 的基础设施文档,并撰写关于 RDP、VPS 托管、服务器管理、网络和隐私工具的指南。




