Linux ss 监听排查:先看地址和命名空间,再判断端口是否可达

10-01 4阅读

“端口已经开了”可能指应用完成绑定,也可能指远端请求能够到达,两者需要不同证据。ss 读取的是套接字信息,适合先确定当前环境里谁在什么地址监听。本文使用 Linux 的 iproute2 工具与 Python 3.9 以上版本;先通过 ss -V 记录实际版本,只演示读取状态,不修改防火墙,也不终止未知进程。

Linux ss 监听排查:先看地址和命名空间,再判断端口是否可达

AI生成概念配图:检查服务监听入口以及对应连接位置。仅作概念说明,不代表实际界面或实测结果。

先建立一个可控的回环服务

在终端一运行以下命令,仅在临时目录放一个无敏感内容的测试文件。18080 是演示端口,启动失败并提示地址占用时,应换一个空闲端口,并同步修改后续查询。不要为了完成演练直接杀掉占用它的进程。

work=$(mktemp -d)
printf 'socket demo\n' > "$work/index.html"
python3 -m http.server 18080 --bind 127.0.0.1 --directory "$work"

这个服务器只用于短暂本机演练,不适合作为生产服务。明确 --directory 可避免意外把当前项目目录暴露出去,明确 --bind 可限制为 IPv4 回环地址。保持终端一运行,在同一网络命名空间中的终端二读取状态;测试完在终端一按 Ctrl+C 停止刚才启动的服务。

使用精确过滤,避免端口号误匹配

ss -V
ss -ltnp 'sport = :18080'
ss -4 -ltn 'sport = :18080'
ss -6 -ltn 'sport = :18080'

-l 选择监听套接字,-t 限定 TCP,-n 保留数字地址和端口,-p 尝试显示关联进程。sport 过滤本地端口,比 grep 18080 更准确,后者还可能匹配到远端地址或其他字段。单引号把表达式作为整体交给 ss;查询为空时先检查过滤条件、协议和命名空间,不要立即断言服务没有启动。

本演练预期在 IPv4 查询中看到 127.0.0.1:18080,IPv6 查询没有对应条目。进程名和进程号可能因权限或运行环境而不可见,不能把缺少 users 字段理解为“没有进程拥有它”。排查需要更高权限时,应遵循管理员授权流程,而不是为每个命令习惯性附加提权。

若命令出现权限不足、无法打开 netlink 等警告,即使仍显示部分结果,也应标记观察范围受限。不要忽略错误信息,只截取空白输出作为结论;先确认当前工具可提供哪些信息,再由获得授权的管理员补足证据。

监听地址决定接受连接的范围

127.0.0.1 表示当前网络环境的回环入口,0.0.0.0 表示 IPv4 通配绑定;二者都不能单独证明远端网络可达。IPv6 的 [::] 是通配地址,是否同时接受映射的 IPv4 连接还与套接字选项及系统配置有关。因此看到 [::]:端口 后,应分别验证 IPv4 和 IPv6,不能只凭显示形式判断双栈行为。

curl --noproxy '*' --max-time 3 http://127.0.0.1:18080/
ss -lunp 'sport = :18080'

curl 成功时应得到 socket demo,说明演练中的本地 HTTP 路径可用。--noproxy 用来避免环境代理把本地测试绕到其他服务;超时参数限制等待。UDP 查询预期为空,因为这个示例只创建 TCP 服务。UDP 没有 TCP 那样的监听握手过程,常见 UNCONN 状态也不能简单套用“连接失败”的解释。

检查位置和证据层次必须一致

容器、宿主机和独立网络命名空间可能各有不同套接字视图。在宿主机上没找到容器内部监听,不代表应用没有监听;宿主机映射端口也可能通过转发实现,不能要求它一定呈现为同名进程的一条普通监听记录。先标明命令在哪个环境运行,再到获得授权的对应环境中做相同查询。

若本地请求成功而远端失败,接着分层核对目标地址、路由、防火墙、端口映射和服务绑定范围。ss 不能替代这些检查,也不能证明应用业务健康。记录精确命令、执行位置和时间,比只发一张“端口存在”的截图更有助于协作;共享结果前还应去掉不相关进程、地址和用户信息。

参考资料

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。