Linux运维7 min read

Linux 网络故障排查完全指南

网络问题排查的系统方法论

网络问题是最让人头疼的故障类型之一——现象模糊、原因复杂、影响面广。本文建立一套自底向上的排查体系,从物理层到应用层逐层排查,确保不错过任何可能。

排查路线图

应用层 ── curl / telnet / nc / strace
  ↑
传输层 ── ss / netstat / tcpdump
  ↑
网络层 ── ping / traceroute / ip route
  ↑
链路层 ── ip link / ethtool / arp
  ↑
物理层 ── 网线 / 灯 / dmesg

第一层:物理与链路检查

# 网卡状态
ip link show
# 关注: state UP/DOWN, 是否有 NO-CARRIER

# 网卡详细信息和错误统计
ip -s link show eth0
# RX errors/dropped/overruns > 0 表示有问题

# 网卡协商速率
ethtool eth0 | grep -E "Speed|Duplex|Link"
# 期望: Speed: 1000Mb/s, Duplex: Full

# 网卡驱动信息
ethtool -i eth0

# 内核网卡相关日志
dmesg | grep -i eth0 | tail -20
# 关键词: link up/down, reset, timeout

常见物理层问题

  • 网线松动 / 水晶头氧化 → RX errors 增多
  • 速率协商不匹配 → 半双工导致碰撞
  • 网卡驱动 bug → dmesg 中出现 reset

第二层:IP 和路由检查

# IP 地址
ip addr show

# 路由表
ip route show
# 确认默认路由存在: default via x.x.x.x dev eth0

# ARP 表(局域网通信基础)
ip neigh show
# STALE 状态 = 正常,FAILED = 不可达

# 到目标主机的路径
traceroute -n 8.8.8.8
mtr -r -c 10 8.8.8.8   # 更直观(组合 ping + traceroute)
# MTR 输出示例(关注 Loss% 和 Avg)
# HOST          Loss%   Snt   Avg  Best  Wrst
# 1. 10.0.0.1    0.0%    10   1.2   0.8   3.5
# 2. 100.64.0.1   0.0%    10   5.3   4.1   8.2
# 3. ???         100.0%    10   0.0   0.0   0.0   ← 中间节点不响应 ICMP,正常
# 4. 8.8.8.8      0.0%    10  35.2  33.1  38.7

第三层:TCP/UDP 连接检查

# 监听端口
ss -tlnp        # TCP 监听
ss -ulnp        # UDP 监听

# 所有连接(按状态统计)
ss -s
# 关注: TIME-WAIT 过多 (>几千) 需要调内核参数

# 查看特定端口的连接
ss -tnp 'sport = :80 or dport = :80'

# 进程的网络连接
ss -tnp | grep <pid>

# 连接数量 Top N(来源 IP)
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

TCP 状态机关键状态

LISTEN      → 服务端等待连接
SYN-SENT    → 客户端发送 SYN 后(可能被防火墙拦截)
SYN-RECV    → 服务端收到 SYN(可能遭遇 SYN Flood)
ESTABLISHED → 正常连接
FIN-WAIT-1  → 主动关闭,等待对方 ACK
CLOSE-WAIT  → 对方已关闭,本端未关闭(程序 bug!)
TIME-WAIT   → 主动关闭方等待 2MSL

第四层:DNS 检查

# DNS 解析测试
nslookup example.com
dig example.com +short
host example.com

# 查看 DNS 解析过程
dig +trace example.com

# 指定 DNS 服务器测试
dig @8.8.8.8 example.com

# 反向解析
dig -x 8.8.8.8

# 本地 DNS 缓存(systemd-resolved)
resolvectl status
resolvectl query example.com

常见 DNS 问题

  • /etc/resolv.conf 被错误覆盖
  • systemd-resolved 与 NetworkManager 冲突
  • DNS 服务器不可达 / 限流

tcpdump 抓包分析

# 基础抓包
tcpdump -i eth0 -nn port 80

# 抓取特定主机的 HTTP 流量
tcpdump -i eth0 -nn -A 'host 10.0.1.100 and port 80'

# 抓取 TCP SYN 包(排查建连问题)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'

# 抓取并保存到文件(用 Wireshark 分析)
tcpdump -i eth0 -w capture.pcap port 3306

# 抓取特定时长的包
timeout 30 tcpdump -i eth0 -w capture.pcap

# 限制抓包大小(每个包只抓前100字节)
tcpdump -i eth0 -s 100 -w capture.pcap

快速定位 TCP 握手问题

# 观察是否有 SYN 发出但无 SYN-ACK 返回(防火墙拦截)
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'

# 观察是否有大量 RST(连接被拒绝)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'
# RST 常见原因:
# 1. 端口未监听 → 服务未启动
# 2. 防火墙 DROP → iptables -L -n -v
# 3. 应用层拒绝 → 程序主动 reset
# 4. 连接超时 → connect timeout 后系统发 RST

防火墙排查

# iptables 规则查看
iptables -L -n -v --line-numbers
iptables -t nat -L -n -v

# 检查是否有 DROP 规则
iptables -L -n -v | grep DROP

# firewalld 状态(CentOS 7+)
firewall-cmd --state
firewall-cmd --list-all

# 临时关闭防火墙排查(仅测试!)
systemctl stop firewalld
# 或
iptables -P INPUT ACCEPT && iptables -F

# ufw 状态(Ubuntu)
ufw status verbose

strace 追踪系统调用

# 追踪 nginx 的网络相关系统调用
strace -f -e trace=network -p $(pgrep nginx | head -1)

# 追踪 connect(看连接到了哪里)
strace -e trace=connect curl http://example.com 2>&1 | grep connect

# 追踪 sendto/recvfrom(看数据发送和接收)
strace -e trace=sendto,recvfrom -p <pid>

# 常见发现:
# - connect(...) = -1 ECONNREFUSED  → 目标端口未监听
# - connect(...) = -1 ETIMEDOUT     → 防火墙拦截或路由不通
# - connect(...) = -1 ENETUNREACH   → 网络不可达

实战案例:Web 服务超时排查

现象:用户反馈网站访问偶尔超时,持续 5-10 秒后恢复。

排查步骤

# 1. 确认问题范围
#    是所有用户还是个别用户?所有页面还是特定接口?

# 2. 检查服务器连接数
ss -s                                    # TIME-WAIT 8000+ → 需要调优

# 3. 抓包看 TCP 握手情况
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' | head -50
# 发现大量 SYN 重传 → SYN Cookie 被触发

# 4. 检查 SYN 队列
netstat -s | grep -i listen
# 出现 SYNs to LISTEN sockets dropped → SYN 队列溢出

# 5. 调优
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf

# 6. Nginx 端
# listen 80 backlog=65535;
nginx -s reload

排查心法:不要凭直觉猜测,用数据说话。每一个结论都要有命令输出的支撑,每一个假设都要用抓包或日志来验证。

分享:

相关文章