网络排查方法论
分层排查模型
网络故障排查遵循自底向上的分层方法,从物理层开始逐层排查:
排查流程
各层排查工具
物理层 & 链路层
# 查看网卡状态
ip link show
ethtool eth0 # 查看网卡详细信息(速率、双工、连接状态)
ethtool -S eth0 # 查看网卡统计(丢包、错误)
# 网卡错误统计
cat /proc/net/dev # 查看所有网卡收发包统计
# 关注 errs(错误)、drop(丢弃)、fifo(溢出)列
# 查看/清除 ARP 缓存
ip neigh show
ip neigh flush dev eth0
# 检查网卡 bonding 状态
cat /proc/net/bonding/bond0
网络层
# === ping ===
ping -c 4 gateway_ip # 测试网关连通性
ping -c 4 8.8.8.8 # 测试外网连通性
ping -I eth0 target # 指定源接口
ping -s 1472 -M do target # 测试 MTU(不分片)
# === traceroute / tracepath ===
traceroute -n target # -n 不解析主机名(更快)
traceroute -T -p 80 target # TCP traceroute(防止 ICMP 被拦截)
tracepath target # 自动探测 MTU
# === mtr(综合 ping + traceroute)===
mtr -rn target # 生成报告模式
mtr --tcp -P 80 target # TCP 模式
# mtr 输出字段:
# Loss% - 丢包率 Snt - 发送包数
# Last - 最近延迟 Avg - 平均延迟
# Best - 最低延迟 Wrst - 最高延迟
# StDev - 标准差(越大越不稳定)
# === 路由排查 ===
ip route show # 查看路由表
ip route get target_ip # 查看到目标的路由
traceroute -n target # 跟踪路由路径
mtr 输出解读
HOST Loss% Snt Last Avg Best Wrst StDev
1. 10.0.0.1 0.0% 10 0.5 0.6 0.4 1.2 0.2
2. 172.16.0.1 0.0% 10 1.2 1.5 1.0 3.0 0.5
3. ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 ← ICMP 被禁
4. 10.20.0.1 10.0% 10 5.2 5.5 4.8 8.0 1.0 ← 丢包
5. target 0.0% 10 5.0 5.2 4.5 7.0 0.8
- 第 3 跳 100% Loss 但后续正常 → 中间路由器不回 ICMP,不是故障
- 第 4 跳开始有丢包且后续也有 → 从第 4 跳开始有问题
- 第 4 跳有丢包但第 5 跳(目标)无丢包 → 第 4 跳路由器限制 ICMP
传输层
# === 端口测试 ===
telnet target 80 # 测试 TCP 端口
nc -zv target 80 # netcat 端口扫描
nc -zv target 80-90 # 端口范围扫描
nc -zuv target 53 # UDP 端口测试
# === 连接状态分析 ===
ss -s # 连接状态概要
ss -ant # 所有 TCP 连接
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn # 按状态统计
ss -tnp # 查看连接的进程信息
ss -ant state time-wait # 查看特定状态的连接
ss -ant dst 10.0.0.100 # 查看到特定目标的连接
# === 端口监听 ===
ss -tlnp # 查看 TCP 监听端口
ss -ulnp # 查看 UDP 监听端口
lsof -i :80 # 查看占用 80 端口的进程
fuser 80/tcp # 查看占用 80 端口的 PID
应用层
# === HTTP 测试 ===
curl -v https://target # 详细输出
curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" URL
curl --connect-timeout 5 --max-time 10 URL # 超时控制
# === DNS 测试 ===
dig target
dig +trace target
dig @8.8.8.8 target
# === SSL/TLS 测试 ===
openssl s_client -connect target:443 -servername target
echo | openssl s_client -connect target:443 2>/dev/null | openssl x509 -noout -dates
tcpdump 抓包
常用抓包命令
# 基础抓包
tcpdump -i eth0 # 抓取 eth0 所有流量
tcpdump -i any # 抓取所有接口流量
# 按主机过滤
tcpdump -i any host 10.0.0.100 # 特定主机
tcpdump -i any src 10.0.0.1 # 源地址
tcpdump -i any dst 10.0.0.2 # 目标地址
# 按端口过滤
tcpdump -i any port 80 # 端口 80
tcpdump -i any portrange 8000-9000 # 端口范围
tcpdump -i any "port 80 or port 443" # 多端口
# 按协议过滤
tcpdump -i any tcp # TCP 流量
tcpdump -i any udp # UDP 流量
tcpdump -i any icmp # ICMP 流量
# 组合过滤
tcpdump -i any "host 10.0.0.1 and port 80 and tcp"
# 只抓 SYN 包(分析连接建立)
tcpdump -i any "tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0"
# 只抓 RST 包(连接被重置)
tcpdump -i any "tcp[tcpflags] & (tcp-rst) != 0"
# 常用选项
tcpdump -n # 不解析主机名
tcpdump -nn # 不解析主机名和端口名
tcpdump -c 100 # 抓 100 个包后停止
tcpdump -A # 以 ASCII 显示内容
tcpdump -X # 以 HEX+ASCII 显示
tcpdump -w capture.pcap # 保存为 pcap 文件
tcpdump -r capture.pcap # 读取 pcap 文件
tcpdump -s 0 # 抓取完整包(不截断)
抓包分析实战
场景 1:分析 TCP 连接问题
# 抓取 SYN 和 RST 包,分析连接是否被拒绝
tcpdump -i any -nn "host target and (tcp[tcpflags] & (tcp-syn|tcp-rst) != 0)" -c 50
# 输出解读:
# SYN → SYN,ACK → ACK 正常三次握手
# SYN → RST 端口未监听或被防火墙拒绝
# SYN → (无响应) 包被丢弃(防火墙 DROP)
# SYN → SYN,ACK → RST 客户端重置(可能是连接池问题)
场景 2:分析 HTTP 请求
# 抓取 HTTP 请求行
tcpdump -i any -nn -A port 80 | grep -E "^(GET|POST|PUT|DELETE|HTTP/)"
场景 3:分析 DNS 查询
# 抓取 DNS 流量
tcpdump -i any -nn port 53
# 输出:
# 10.0.0.1.52345 > 8.8.8.8.53: A? example.com → DNS 查询
# 8.8.8.8.53 > 10.0.0.1.52345: A 93.184.216.34 → DNS 响应
常见网络故障场景
场景 1:服务无法访问
# 1. 检查服务是否监听
ss -tlnp | grep PORT
# 2. 检查本机防火墙
iptables -L -n | grep PORT
firewall-cmd --list-all
# 3. 测试端口连通性
telnet target PORT
nc -zv target PORT
# 4. 检查安全组(云环境)
# 5. 抓包分析
tcpdump -i any port PORT -nn -c 20
场景 2:网络延迟高
# 1. 确认延迟位置
mtr -rn target
# 2. 检查带宽使用
iftop -i eth0 # 实时带宽监控
nethogs # 按进程查看带宽
nload # 网卡流量图
# 3. 检查 TCP 重传
netstat -s | grep retransmit
ss -ti | grep -E "rto:|retrans:"
# 4. 检查丢包
ping -c 100 target | tail -3 # 查看丢包率
场景 3:间歇性断连
# 1. 持续监测
mtr -rn -c 200 target # 长时间 mtr
# 2. 检查连接跟踪表(NAT 场景)
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# 如果 count 接近 max,会导致新连接被丢弃
# 扩大 conntrack 表
sysctl -w net.netfilter.nf_conntrack_max=524288
# 3. 检查 TCP keepalive
sysctl net.ipv4.tcp_keepalive_time
# 4. 检查网卡错误
ethtool -S eth0 | grep -i error
场景 4:DNS 解析异常
# 1. 确认本地 DNS 配置
cat /etc/resolv.conf
# 2. 对比不同 DNS 服务器
dig @8.8.8.8 domain
dig @1.1.1.1 domain
dig @local_dns domain
# 3. 追踪解析链路
dig +trace domain
# 4. 清除本地缓存
resolvectl flush-caches # systemd-resolved
systemctl restart nscd # nscd
实用排查脚本
network-check.sh
#!/bin/bash
# 快速网络诊断脚本
TARGET=${1:-"8.8.8.8"}
echo "===== 网络诊断: $TARGET ====="
echo ""
echo "[1] 网卡状态"
ip -br link show
echo ""
echo "[2] IP 地址"
ip -br addr show
echo ""
echo "[3] 默认路由"
ip route show default
echo ""
echo "[4] DNS 配置"
cat /etc/resolv.conf | grep nameserver
echo ""
echo "[5] Ping 网关"
GW=$(ip route show default | awk '{print $3}')
ping -c 2 -W 2 "$GW" 2>&1 | tail -3
echo ""
echo "[6] Ping 目标: $TARGET"
ping -c 4 -W 2 "$TARGET" 2>&1 | tail -3
echo ""
echo "[7] DNS 解析测试"
dig +short google.com
echo ""
echo "[8] TCP 连接状态统计"
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
echo ""
echo "[9] 监听端口"
ss -tlnp | head -20
echo ""
echo "===== 诊断完成 ====="
常见面试问题
Q1: 如何排查"网络不通"问题?
答案:
按 TCP/IP 分层自底向上排查:
- 物理层:
ip link show确认网卡 UP,ethtool查看连接状态 - 链路层:
arping gateway检查 ARP - 网络层:
ping gateway→ping 8.8.8.8→traceroute target - 传输层:
telnet target port/nc -zv target port - 应用层:
curl -v target/dig target
同时要 check 防火墙和安全组配置。
Q2: ping 通但 telnet 不通是什么原因?
答案:
ping 使用 ICMP 协议,telnet 使用 TCP。可能原因:
- 目标端口上没有服务监听
- 防火墙/安全组允许 ICMP 但不允许目标 TCP 端口
- 服务绑定了
127.0.0.1而非0.0.0.0 - TCP 连接数达到上限
使用 ss -tlnp | grep PORT 检查服务监听状态。
Q3: 如何分析网络丢包发生在哪一跳?
答案:
使用 mtr -rn target 持续监测。关注每一跳的 Loss%:
- 某一跳 100% 丢包但后续正常 → 该路由器不回 ICMP,不是故障
- 某一跳开始丢包且后续都有丢包 → 从该跳开始有问题
- 只有最后一跳丢包 → 目标主机自身的问题(CPU 高、接口限速等)
Q4: conntrack 表满了会有什么现象?怎么解决?
答案:
现象:新连接随机失败,dmesg 中出现 nf_conntrack: table full, dropping packet。
解决:
- 扩大 conntrack 表:
sysctl -w net.netfilter.nf_conntrack_max=524288 - 缩短超时时间:
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=1200
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 - 如果不需要 NAT 和状态跟踪,可以用
raw表 NOTRACK 跳过连接跟踪