RDP Monster

Linux 查看开放端口:ss、netstat、lsof、nmap

Linux 查看开放端口:ss、netstat、lsof、nmap

用 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 now

netstat 仍可用,但已属遗留工具

无数教程至今仍在写 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/tcp

fuser 最为简洁:它打印 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。其他任何东西都需要一个解释。然后按这份清单逐项处理:

  1. 按进程名和 PID 识别每一个监听者;禁用任何你没有主动要求的服务。
  2. 质疑每一个绑定到 0.0.0.0 或 [::] 的监听:数据库和管理面板应当留在 127.0.0.1,除非它们确实需要对外提供服务。
  3. 做到常见端口一眼即识:22 SSH、80/443 web、3306 MySQL、5432 PostgreSQL、6379 Redis。3389 端口是远程桌面;在 Linux 上它意味着 xrdp 正在运行,该端口的暴露与加固规则正是我们 RDP 3389 端口指南 的主题。
  4. 从你自己的机器用 nmap -p- 扫描公网 IP,并将结果与 ss 的清单对比;每一处不一致,要么是防火墙在起作用,要么是回环绑定。
  5. 最后用默认拒绝的防火墙收尾,只允许你有意对外暴露的端口。

这里是整套工具箱,每样一行:

命令显示内容适用场景
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),它同样可用,只是噪音稍大一些。

如何检查远程服务器上某个特定端口是否开放?

用 netcat:nc -zv host port 立刻给出答案。
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 显示端口在监听,我却无法从外部连接?

套接字绑定在回环地址上,或者防火墙丢弃了流量。
先看 Local Address 列:127.0.0.1:PORT 或 [::1]:PORT 表示该服务只接受本地连接,这对数据库来说是有意为之且很常见的设置。如果它绑定在 0.0.0.0,那就是数据包在路径上某处被过滤了:可能是 ufw、firewalld 或原生 nftables 之类的主机防火墙,也可能是服务商的边缘过滤。外部 nmap 扫描把该端口报告为 filtered 即可确认存在防火墙;closed 则意味着流量到达了,但该接口上没有进程监听。

一台全新的 Linux 服务器应该开放哪些端口?

一个:SSH。干净安装上的其他任何端口都需要一个解释。
最小化安装的 Debian、Ubuntu 或 Rocky 只应向网络暴露 22 端口上的 sshd。位于 127.0.0.53:53 的 DNS stub 解析器(systemd-resolved)属正常现象,且从外部无法访问。云镜像有时会额外加上代理程序或监控守护进程;用 ss -tulpn 识别每个监听者,并禁用任何你没有主动要求的东西。之后安装的每个服务都应默认绑定回环,除非它确实需要对网络提供服务,同时让防火墙只放行真正需要公开的部分。

Adrien Roche, 基础设施与主机托管编辑

系统工程师,拥有 10 年以上运维 Windows Server 和 Linux 集群的经验。Adrien 负责 rdp.monster 的基础设施文档,并撰写关于 RDP、VPS 托管、服务器管理、网络和隐私工具的指南。

注册加入我们的分销商计划

您的信息

如有任何疑问, contact us by clicking here !
姓名(必填)
请填写您的邮箱地址,您必须拥有以下网站的账号: manager.rdp.monster !

您的公司

如果您有网站,请填写网址
请简要说明您打算如何向客户销售服务,例如在论坛上与人交流推广。

我们使用 cookie !

我们使用 cookie 来改善您的浏览体验、提供个性化的广告或内容,并分析我们的流量。点击「接受」即表示您同意我们使用 cookie。