2.7.6 典型场景抓包分析与结论输出

6. 典型场景抓包分析与结论输出#

本节以“现象—抓包要点—结论输出—验证/修复”的方式组织,提供可复用的抓包流程、命令示例与练习题。所有抓包示例以 tcpdump 为主,必要时配合 ssiptablessysctl 等工具。

6.0 基础环境与抓包位置选择#

安装与准备(任选其一发行版):

# Debian/Ubuntu
sudo apt-get update
sudo apt-get install -y tcpdump wireshark tshark

# RHEL/CentOS
sudo yum install -y tcpdump wireshark

# 验证
tcpdump --version

抓包位置原则:优先在“问题链路两端 + 中间设备”抓包对比,形成证据链。
基础命令模板

# 1) 查看网卡
ip -br a

# 2) 基础抓包(显示时间、来源/目的、保存文件)
sudo tcpdump -i eth0 -nn -tttt -s 0 -w /tmp/cap.pcap

# 3) 抓包同时观察(不写文件)
sudo tcpdump -i eth0 -nn -tttt -s 0 'tcp port 80'

原理草图(抓包点选择)

文章图片

6.1 TCP 三次握手失败#

现象:连接超时或拒绝连接。
抓包要点:过滤 SYN,查看是否有 SYN-ACK、是否重传、是否 RST。

示例抓包

# 客户端抓包:只看握手
sudo tcpdump -i eth0 -nn -s 0 -vv 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' -w /tmp/hs_fail.pcap

# 同时查看端口监听情况
ss -lntp | grep ':8080'

分析结论与排错
- 仅见 SYN 多次重传:防火墙丢弃、路由不可达或端口未监听。
- 有 SYN-ACK 无 ACK:客户端侧丢包或回程被丢。
- 收到 RST:端口未监听或安全策略拒绝。

修复/验证命令

# 查看防火墙策略是否拦截
sudo iptables -L -n --line-numbers | sed -n '1,120p'

# 验证端口是否开放
nc -vz 10.0.0.12 8080

练习
1) 关闭服务端端口监听,观察客户端抓包 SYN 重传现象。
2) 开启端口后重新抓包对比。


6.2 TCP 连接被重置(RST)#

现象:短连接异常断开,应用报 “connection reset”。
抓包要点:定位 RST 方向,观察是否紧跟应用数据。

示例抓包

sudo tcpdump -i eth0 -nn -s 0 -vv 'tcp[tcpflags] & tcp-rst != 0'

分析结论与排错
- 服务端发 RST:应用进程崩溃、端口关闭或主动拒绝。
- 客户端发 RST:客户端超时关闭或本地安全策略。
- RST 紧跟大包发送:中间设备触发阈值。

修复建议
- 检查服务端日志与进程存活:systemctl status service
- 检查中间设备会话超时与 ACL。

练习
模拟服务端进程退出,确认客户端收到 RST。


6.3 连接建立成功但无响应#

现象:握手完成后业务超时。
抓包要点:确认应用请求是否发出、服务端是否回包,观察重传与窗口。

示例抓包

# 抓请求与响应,保存 pcap 供 Wireshark 分析
sudo tcpdump -i eth0 -nn -s 0 -w /tmp/app_noresp.pcap 'tcp port 8080'

# 查看应用层是否输出响应
curl -v --max-time 3 http://10.0.0.12:8080/health

结论输出
- 请求已发送但无响应:服务端应用阻塞或后端依赖故障。
- 响应已回但客户端无 ACK:客户端接收链路问题或丢包。
- 多次重传:链路丢包或拥塞。

修复验证

# 观察服务端线程或连接池
ss -s
top -H -p $(pidof your_app)

练习
使用 tc netem 模拟丢包,观察重传与超时。

sudo tc qdisc add dev eth0 root netem loss 10%
# 复现后再清理
sudo tc qdisc del dev eth0 root

6.4 DNS 解析慢或失败#

现象:域名解析超时,业务波动。
抓包要点:过滤 udp.port==53,查看请求/响应延迟与重试。

示例抓包

sudo tcpdump -i eth0 -nn -s 0 -w /tmp/dns.pcap 'udp port 53'
dig +time=1 +tries=1 example.com @10.0.0.53

结论输出
- 无响应且重试:DNS 服务器不可达或被防火墙拦截。
- 响应慢且多次切换服务器:上游 DNS 质量差。
- SERVFAIL/NXDOMAIN:配置或域名错误。

排错命令

# 查看 resolv.conf
cat /etc/resolv.conf

# 直接测试连通性
nc -vzu 10.0.0.53 53

练习
/etc/resolv.conf 临时指向不存在的 DNS,观察抓包中的重试与超时。


6.5 HTTP 访问慢或异常#

现象:网页慢、接口 5xx/4xx。
抓包要点:过滤 80/443,统计请求-响应时间,关注重传与窗口。

示例抓包

sudo tcpdump -i eth0 -nn -s 0 -w /tmp/http.pcap 'tcp port 80'
curl -w '\nconnect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n' -o /dev/null -s http://10.0.0.12/

结论输出
- TCP 正常但 HTTP 响应慢:应用处理慢或后端依赖迟缓。
- 频繁重传且 RTT 增大:链路拥塞或丢包。
- 413/414/431:请求体/头过大。

修复建议
- 调整 Nginx client_max_body_sizelarge_client_header_buffers

练习
构造超大请求头,验证 431。


6.6 MTU/分片导致的访问异常#

现象:小包正常,大包失败。
抓包要点:观察 DF 位与 ICMP “Fragmentation needed”。

示例抓包

# 发送带 DF 的大包探测 MTU
ping -M do -s 1472 10.0.0.12

# 抓 ICMP 报文
sudo tcpdump -i eth0 -nn -s 0 'icmp'

结论输出
- 无 ICMP 返回且大包失败:路径 MTU 黑洞。
- ICMP 返回明确:调整 MTU 或启用 MSS Clamp。

修复示例

# 临时降低网卡 MTU
sudo ip link set dev eth0 mtu 1400

# 重新探测
ping -M do -s 1372 10.0.0.12

练习
在两台机器之间设置不同 MTU,观察访问异常的包特征。


6.7 负载均衡后端不稳定#

现象:间歇性 502/504。
抓包要点:在 LB 与后端分别抓包比对。

示例抓包

# LB 上抓前后端
sudo tcpdump -i eth0 -nn -s 0 -w /tmp/lb_front.pcap 'tcp port 80'
sudo tcpdump -i eth1 -nn -s 0 -w /tmp/lb_back.pcap 'tcp port 8080'

# 访问测试
curl -I http://lb.example.com/

结论输出
- LB 出口无转发:健康检查失败或粘滞异常。
- 后端响应超时:后端性能不足或连接池耗尽。
- 后端返回正常但 LB 超时:LB 超时配置偏小。

排错建议
- 检查 LB 超时与重试参数;
- 检查后端线程/连接池。

练习
降低 LB 超时,观察 504。


6.8 TLS/HTTPS 握手失败#

现象:HTTPS 连接失败或证书错误。
抓包要点:观察 ClientHello/ServerHello、证书链与 Alert。

示例抓包

sudo tcpdump -i eth0 -nn -s 0 -w /tmp/tls.pcap 'tcp port 443'
openssl s_client -connect 10.0.0.12:443 -servername example.com -tls1_2

结论输出
- 无 ServerHello:服务端未监听 443 或中间设备拦截。
- handshake_failure:协议版本/加密套件不匹配。
- certificate_unknown:证书链缺失或过期。

修复建议
- 更新证书链,启用兼容套件。

练习
禁用 TLS1.2,观察握手失败的 Alert。


6.9 Redis/MySQL 连接抖动#

现象:连接池频繁断开重连。
抓包要点:查看 TCP keepalive、FIN/RST 方向。

示例抓包

# 观察连接的关闭方向
sudo tcpdump -i eth0 -nn -s 0 -w /tmp/db_conn.pcap 'tcp port 3306 or tcp port 6379'

# 查看服务端超时配置
mysql -e "SHOW VARIABLES LIKE 'wait_timeout';"
redis-cli CONFIG GET timeout

结论输出
- 服务端先发 FIN:空闲连接被服务器关闭。
- 中间设备发 RST:会话超时。
- 客户端先发 FIN:连接池回收策略激进。

修复示例

# MySQL 调大 wait_timeout
mysql -e "SET GLOBAL wait_timeout=28800;"

# Linux 开启 TCP keepalive
sudo sysctl -w net.ipv4.tcp_keepalive_time=300
sudo sysctl -w net.ipv4.tcp_keepalive_intvl=30
sudo sysctl -w net.ipv4.tcp_keepalive_probes=5

练习
调小 MySQL wait_timeout,观察连接断开方向。


6.10 结论输出模板(建议统一格式)#

模板(可直接复用):

现象描述:2024-xx-xx 10:00-10:15,订单服务间歇性超时,影响 20% 请求。
抓包位置:客户端 eth0、LB eth1、后端 eth0;涉及 IP 10.0.0.10/11/12。
证据点:客户端 SYN 重传 3 次,LB 无转发;后端无对应会话。
分析结论:LB 健康检查失败导致未转发;非链路丢包。
建议措施:修复健康检查路径,调整超时;恢复后验证无重传。

练习
任选一个场景,使用上述模板写出完整结论并标注关键证据包序号。