LabHub
学习 学习路径 课程

网络排障

怎么读抓包 (概念)

在 LabHub 中继续学习

一句话总结

抓包是判断“到底谁在说谎”的终极裁判。不过,本实验环境没有抓包权限,因此先从概念上掌握如何阅读抓包结果,实际操作则用 ss/proc/net 代替。

概念图: 如何阅读抓包结果 · 不解析 · TCP 标志的表示法 · refused

为什么需要抓包

日志是应用程序的一面之词,而 ss 是内核提供的摘要。两者都不能直接呈现“数据包实际是怎样往返的”。因此,在下面三种情况下,最终还是需要抓包。

  1. 两端日志各执一词时(客户端称已经发送,服务器却称没有收到)
  2. 需要观察重传、分片等只发生在内核中的事件时
  3. 需要确认中间设备(代理、负载均衡器、NAT)是否改写了某些内容时

它是如何工作的

tcpdump 真正必需的选项屈指可数。

tcpdump -nn -i any 'host 10.0.3.11 and tcp port 8080'
tcpdump -nn -i any 'icmp[icmptype] == 3 and icmp[icmpcode] == 4'
tcpdump -nn -i any -w /tmp/cap.pcap -c 2000

阅读时最关键的是理解 TCP 标志的表示法

表示 含义 此时发生的事情
[S] SYN 尝试建立连接
[S.] SYN+ACK 对端接受连接
[.] ACK 确认数据
[P.] PSH+ACK 传输数据
[F.] FIN+ACK 开始正常关闭
[R] / [R.] RST 拒绝连接或强制关闭

只要掌握这张表,就能一眼区分两类故障。

诊断 MTU 黑洞时,要捕获 ICMP 类型 3、代码 4(Fragmentation needed)。这也解释了为什么“为了安全而封锁全部 ICMP”的策略本身会成为故障原因。最多只能考虑阻止 echo request/reply,类型 3、代码 4 必须放行。在 IPv6 中,Packet Too Big(类型 2)承担同样的职责,而且此时甚至没有选择余地。

实际工作中会遇到的情况

在容器中抓包并不容易。 像本实验环境这样移除 capability 后,tcpdump 就无法打开套接字。在 Kubernetes 中,标准的绕行方法是使用临时容器(kubectl debug),将诊断 Pod 接入同一个网络命名空间。如果能够登录节点,也可以在节点上指定 Pod 的 veth 进行抓包。

因此,实际工作中的处理顺序逐渐固定下来:先用 sscurl -w 尽可能缩小范围,只有双方的说法依然矛盾时才开始抓包。 抓包非常强大,但成本也很高。

接下来要做什么

本课程的所有实验都无需抓包。作为替代,其中包含直接读取 /proc/net/tcp、确认内核所保存套接字状态的步骤——这是不抓包时最接近内核真相的方法。