适用于 Linux 服务端显示端口已监听,但远端客户端仍出现连接超时、拒绝连接或 TLS 握手失败的场景。命令基线为 iproute2 5.5+、systemd 245+、curl 7.68+;tcpdump 4.9+ 和 nft 0.9+ 为可选工具。示例端口为 8443、服务单元为 app.service,执行前必须替换为实际值。涉及抓包、规则和网络命名空间的命令通常需要 root 权限。
1. 先固定观察点并区分错误类型
在原始客户端记录时间、解析结果和连接过程:
date -u
getent ahosts api.example.com
curl -v --connect-timeout 5 https://api.example.com:8443/healthz
Connection refused 通常表示目标返回了 RST,优先检查监听地址和显式拒绝规则;超时表示在限定时间内没有完成连接,重点检查丢包、路由和静默丢弃规则;若已经收到 TLS 或 HTTP 错误,TCP 通路通常已建立,应转向证书、SNI、协议和应用日志。先保存完整错误,不要只记录“访问不了”。
2. 在服务端确认监听者与绑定地址
date -u
sudo ss -lntp 'sport = :8443'
systemctl show app.service -p ActiveState -p SubState -p MainPID
systemctl status app.service --no-pager
journalctl -u app.service --since '-10 min' --no-pager
监听在 127.0.0.1:8443 或 [::1]:8443 时,远端无法直接连接;监听在 0.0.0.0:8443 或 [::]:8443 才可能接收对应地址族的外部流量。ss 没有结果时,不要先改防火墙,应先确认进程是否启动、实际端口是否变化。
3. 从服务端本机验证应用层
若服务使用 HTTPS,使用真实主机名保留 Host 与 SNI,只把连接地址定向到本机:
curl -v --connect-timeout 3 \
--resolve api.example.com:8443:127.0.0.1 \
https://api.example.com:8443/healthz
不要用 -k 掩盖证书问题。若本机请求也失败,先处理应用、协议或监听问题;本机成功而远端失败,才继续检查主机外部链路。
4. 对照地址、回程路由与主机规则
ip -br address
ip route get CLIENT_IP
sudo nft list ruleset
将 CLIENT_IP 替换为原始客户端地址。ip route get 用于确认回包将从哪个接口、源地址和下一跳发出。只有系统实际使用 nftables 时才按 nft 输出判断;若主机由 firewalld、ufw、云安全组或外部负载均衡器管理,还要在对应控制面核对,但不要为了验证而清空整套规则。
5. 用少量抓包确定断点
在服务端发起一次客户端请求,同时执行:
sudo tcpdump -ni any 'tcp port 8443 and host CLIENT_IP' -c 20
判读顺序:服务端看不到 SYN,问题位于到达主机之前或客户端使用了错误地址;看到 SYN 但没有发出 SYN-ACK,检查本机丢弃规则、监听地址和资源状态;发出 SYN-ACK 却收不到 ACK,检查回程路由、非对称路径及客户端侧策略;三次握手完成后才失败,则继续看 TLS 和应用日志。抓包可能包含地址等敏感元数据,应限制过滤条件和包数。
6. 排除网络命名空间差异
容器或隔离服务中的 127.0.0.1 不等于宿主机。若 systemd 的 MainPID 大于 0,可只读比较并进入该进程的网络命名空间检查:
PID=$(systemctl show app.service -p MainPID --value)
readlink /proc/1/ns/net /proc/"$PID"/ns/net
sudo nsenter -t "$PID" -n ss -lntp 'sport = :8443'
nsenter 来自 util-linux;执行前先确认 PID 属于目标服务。若两个 net:[...] 标识不同,宿主机与服务看到的接口、路由和监听套接字不是同一组,需要再检查端口发布、代理或容器网络配置。
7. 闭环验证
每次只改变一个可解释的配置项。处理后至少重新确认:
sudo ss -lntp 'sport = :8443'
systemctl is-active app.service
journalctl -u app.service --since '-2 min' --no-pager
最后必须从最初失败的客户端再次执行同一条 curl,记录 UTC 时间、解析到的地址、连接结果和服务端对应日志。仅本机成功不能证明远端链路已经恢复。