Linux 网络排障实战:从 ss、tcpdump 到 conntrack 与内核参数调优 原创

温馨提示:
本文最后更新于 2026-10-19,已超过 0 天没有更新。 若文章内的图片失效(无法正常加载),请留言反馈或直接 联系我。

服务器网络出问题,最常见的话术是「ping 不通」「端口连不上」「请求超时」。但 ping 通不代表 TCP 能握手,TCP 能握手不代表应用层能返回——每一层都有自己的排查工具。这篇把四层模型从下到上捋一遍,配合 ss、tcpdump、conntrack、sysctl 四个工具,给出一套可以照着走的决策路径。

一、先定位层:从 L3 到 L7 的三连问

收到「连不上」的反馈,先别急着改配置。三个命令快速定位问题在哪一层:

# L3 网络可达性
ping -c 3 -W 2 target_ip

# L4 TCP 握手
nc -zv -w 3 target_ip 443
# 或
ss -tan state syn-sent '( dport = :443 )'

# L7 应用层
curl -v --max-time 5 https://target_ip/ -k

ping 通但 nc 不通 → 防火墙或端口没监听;nc 通但 curl 失败 → 应用层问题(证书、协议、后端);ping 都不通 → 路由或安全组问题。先分清层,再上对应工具。

二、ss:看清当前的连接状态

netstat 已被 ss 全面替代,速度差一个数量级。常用组合:

# 谁在监听 443
ss -tlnp | grep :443

# 当前所有 TIME_WAIT(高并发服务的隐患)
ss -tan state time-wait | wc -l

# 按目标端口统计
ss -tan '( dport = :3306 )' | awk '{print $1}' | sort | uniq -c

# 查看连接的拥塞窗口、RTT
ss -ti

关键状态解读:

状态 含义 常见异常
SYN-SENT 客户端发出 SYN 没收到 ACK 对端防火墙 DROP、路由不通
SYN-RECV 服务端回了 SYN+ACK 等 ACK SYN 攻击、半连接队列满
ESTABLISHED 正常连接 数量过多 → 连接池泄漏
CLOSE-WAIT 对端关了,本地还没 close 应用代码忘 close → 句柄耗尽
TIME-WAIT 主动关闭方的等待期 几万级 → 短连接过多

实战里最常踩的坑是 CLOSE-WAIT 堆积:看到上千个 CLOSE-WAIT 基本就是应用 bug,代码里拿到连接后没有 finally close。重启治标,改代码治本。

三、tcpdump:抓包验证猜想

ss 告诉你「现状是什么」,tcpdump 告诉你「过程发生了什么」。三个高频场景:

# 场景 1:验证 SYN 到底发没发出去 / 回没回来
tcpdump -i any -nn 'tcp port 443 and host 1.2.3.4' -c 20

# 场景 2:定位 RST 来源(谁重置了连接)
tcpdump -i any -nn 'tcp[tcpflags] & (tcp-rst) != 0' -c 50

# 场景 3:抓 HTTP 请求看响应码
tcpdump -i any -nn -A 'tcp port 80' | grep -E '^(GET|POST|HTTP)'

抓包结果的标准读法:

  • 只有 S 没有 S. → SYN 没回应,对端或链路丢包
  • S → S. → R → 对端立刻 RST,端口没监听或被 REJECT
  • S → S. → . 之后 N 秒没数据 → 应用层卡死,查后端
  • 看到 [S] 反复重传 → 中间链路丢包,mtr 定位

四、conntrack:被低估的连接跟踪表

NAT、Docker、K8s、iptables 都依赖 conntrack。表满了之后新连接直接被丢,现象是「偶发超时」,最难排查。

# 当前连接数 vs 上限
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

# 满了会看到日志
dmesg | grep -i 'conntrack'
# nf_conntrack: table full, dropping packet

# 临时调大
sysctl -w net.netfilter.nf_conntrack_max=1048576
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30

典型事故:容器节点 QPS 一上来就丢新连接,ss 看 ESTABLISHED 不多,但 nf_conntrack_count 顶到了默认 262144。把 max 调到百万级、把 TIME_WAIT 超时从默认 120s 降到 30s,立刻恢复。

五、内核参数:高并发服务的必调项

默认内核是为通用场景设计的,跑 Web / 网关 / 数据库要针对性调。常用最小集合:

# /etc/sysctl.d/99-net-tuning.conf
net.core.somaxconn = 4096                  # listen backlog
net.ipv4.tcp_max_syn_backlog = 8192        # 半连接队列
net.ipv4.tcp_tw_reuse = 1                  # TIME_WAIT 复用(仅出站安全)
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 1024 65535  # 出站端口范围
net.ipv4.tcp_keepalive_time = 300
net.core.netdev_max_backlog = 16384        # 网卡队列

执行 sysctl --system 生效。注意 tcp_tw_recycle 在 4.12 已被移除,且 NAT 环境下开启会丢连接,不要再设。

六、一页决策图

把上面的工具串成一条路径,下次故障直接对照走:

现象 第一怀疑 验证命令 常见处置
ping 不通 路由 / 安全组 mtr、traceroute 改路由或 ACL
SYN 没回应 对端丢包 tcpdump 看 S/S. 防火墙 DROP → ACCEPT
SYN 立即 RST 端口没监听 ss -tlnp 启动服务或改 bind
握手成功但无响应 后端卡死 ss -ti、strace 查应用锁/慢查询
偶发新连接失败 conntrack 满 nf_conntrack_count 调 max + 降 timeout
CLOSE-WAIT 堆积 应用没 close ss -tan state close-wait 修代码 + 重启
TIME_WAIT 上万 短连接过多 ss -s 连接池 / Keep-Alive

结语

网络排错的难点不在工具,在于能否快速把「连不上」翻译成「哪一层的哪个状态不对」。ss 看现状、tcpdump 看过程、conntrack 看内核表、sysctl 调参数,四件套配合决策表,95% 的网络问题都能在十分钟内定位到根因。剩下 5% 通常需要配合应用日志,那就是下一篇要讲的链路追踪了。