首页 > 解决方案 > 如何在 tcpdump 中捕获 TCP/IP 碎片?

问题描述

众所周知,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]设置为默认?天知道。

标签: tcptcpdumpfragmentation

解决方案


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

这不是真的。

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

  $ ifconfig lo
  lo: ...  mtu 65536

  $ ifconfig eth0
  eth0: ...  mtu 1500

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

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


推荐阅读