如何在 tcpdump 中捕获 TCP/IP 碎片?

Posted

技术标签:

【中文标题】如何在 tcpdump 中捕获 TCP/IP 碎片?【英文标题】:How to capture TCP/IP fragmentation in tcpdump? 【发布时间】:2018-11-06 03:18:19 【问题描述】:

众所周知,MTU是1500,TCP的MSS是1460。所以当recv函数中使用的buf大于1460字节时,TCP会被拆分成很多部分。

我写了一个简单的 echo prog,想用 tcpdump 来检查碎片。但是在buf很小的时候不显示碎片,而是在buf在20K左右的时候显示。

代码如下:

服务器:

import socket
import sys
import os

addr = ('10.0.0.2',10086)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(addr)
server.listen(5)

while True:
    connfd, addr= server.accept()
    print 'connection ip:', addr
    data = connfd.recv(8192);

客户:

import socket
import os
import sys

addr = ('10.0.0.2', 10086)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)

data = '';
for num in range(0,8192):
    data += '1'

client.sendall(bytes(data))

这是我使用的 tcpdump cmd:

sudo tcpdump -i lo 端口 10086 -s 1514 -v

从代码看,buf是8192,MSS是1460。所以,在我看来,数据包会被分成1460、1460、1460、1460、1460、892。但在截图中不是。

另外,我不确定这是否是由 [DF] 标志引起的。 prog使用python,所以内置sockopt [DF]设置为默认?天知道。

【问题讨论】:

【参考方案1】:

众所周知,MTU 是 1500,而 TCP 的 MSS 是 1460

这不是真的。

MTU 取决于传输介质,而 1500 的 MTU 特定于以太网。但是根据您的 tcpdump,您没有使用以太网接口(即两台机器之间的有线 LAN 连接),而是在同一台机器上拥有客户端和服务器,因此使用 lo 接口(@98​​7654323@)。 localhost 接口的 MTU 通常要高得多:

  $ ifconfig lo
  lo: ...  mtu 65536

  $ ifconfig eth0
  eth0: ...  mtu 1500

除此之外,您可能根本看不到任何碎片。如果数据包大于 MTU,您将看到 TCP 分段(不是分段),即操作系统会将 TCP 流分成不同的分段,每个分段如果不大于 MSS。相反,碎片发生在较低层,例如,如果 IP 数据包需要进一步拆分,因为到目标的路径中的某处是具有较小 MTU 的设备。

您看到的[DF](不要分段)是为了确保不会发生 IP 级分段,而是丢弃数据包并通知发送方,以便可以发现路径 MTU(路径的最小 MTU)以及为此优化的 TCP 分段,以减少传递的开销。请参阅Path MTU discovery 了解更多信息。

【讨论】:

非常感谢。我忽略了lo接口的MTU。我尝试在两台主机上进行测试,现在可以看到 TCP 分段数据包。更重要的是,我还关闭了tso。 IIRC,它将TCP分段转发到数据链路层,而不是在TCP层。【参考方案2】:

我想补充一点,您不会使用 tcpdump 过滤器看到片段,因为您正在过滤端口号。 IP 片段实际上没有端口号。只是数据包 ID 和偏移量以及协议号。因此,您应该使用 IP src 或目标过滤 UDP。 或使用此过滤器查看片段: tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))'

信用:https://github.com/SergK/cheatsheat-tcpdump/blob/master/tcpdump_advanced_filters.txt

【讨论】:

这个过滤器只显示分段的 IP 数据包,包括第一个 IP 数据包。这很有用!【参考方案3】:

您正在一台主机内从本地主机向本地主机发送数据。 因此,以太网的 MTU (1500) 不会限制 MSS 的大小,因为数据不会通过以太网。

尝试在两个不同的主机之间重复测试。

【讨论】:

以上是关于如何在 tcpdump 中捕获 TCP/IP 碎片?的主要内容,如果未能解决你的问题,请参考以下文章

Tcpdump抓包命令

《TCP-IP详解卷1:协议》PDF下载

LinuxLinux 下tcpdump抓包实战

在 tcpdump 中捕获传入流量

Pcap 数据包捕获格式详解

Pcap 数据包捕获格式详解