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

时间:2018-05-27 09:56:11

标签: 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);

客户端:

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 port 10086 -s 1514 -v

enter image description here

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

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

3 个答案:

答案 0 :(得分:4)

  

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

事实并非如此。

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

  $ ifconfig lo
  lo: ...  mtu 65536

  $ ifconfig eth0
  eth0: ...  mtu 1500

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

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

答案 1 :(得分: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

答案 2 :(得分:1)

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

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