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

Ton*_*hen 0 tcp tcpdump fragmentation

众所周知,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);
Run Code Online (Sandbox Code Playgroud)

客户:

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))
Run Code Online (Sandbox Code Playgroud)

这是我使用的 tcpdump cmd:

须藤 tcpdump -i lo 端口 10086 -s 1514 -v

在此处输入图片说明

从代码上看,buf是8192,MSS是1460。所以,在我看来,数据包将被拆分为1460、1460、1460、1460、1460、892。但在截图中没有。

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

小智 7

我想补充一点,您不会使用 tcpdump 过滤器看到片段,因为您正在过滤端口号。IP 片段实际上没有端口号。只是数据包 ID 和偏移量以及协议号。因此,您应该使用 IP 源或目标来过滤 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


Ste*_*ich 5

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

这不是真的。

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

  $ ifconfig lo
  lo: ...  mtu 65536

  $ ifconfig eth0
  eth0: ...  mtu 1500
Run Code Online (Sandbox Code Playgroud)

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

[DF]您看到的(不要分段)是为了确保不会发生 IP 级分段,而是将数据包丢弃并通知发送方,以便可以发现路径 MTU(路径的最小 MTU)并针对 TCP 分段优化这是为了减少交付的开销。有关详细信息,请参阅路径 MTU 发现