使用Python发送原始IP流量:检测MTU

时间:2016-04-04 11:56:30

标签: python ip mtu

如何使用Python实现手动MTU发现?

来自:https://networkengineering.stackexchange.com/a/28988/23983

  

向目标发送ping,在我的示例中,我将使用Google的DNS服务器(8.8.8.8)。将ping中的DF位设置为on,以防止ping被分段。将数据包大小设置为某个较大的数字,或标准MTU为1500.请注意,某些ping实现仅设置有效负载的大小,这意味着您必须考虑8字节的ICMP标头和20字节的IP标头。

2 个答案:

答案 0 :(得分:2)

我想补充一点,你也可以使用原始套接字。
scapy是一个很好的抽象层,可以为你带来很多魔力,但平心而论,如果你想要变低,你可以一路走向学习体验。 (请注意,在大多数现代操作系统中,原始套接字需要提升权限,随着时间的推移,实施可能会因Windows和Linux而异。)

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))

这将为您提供一个基于数据包的原始套接字,可以为您提供所有帧。它在Windows和Linux之间有所不同,但在这个答案中我会坚持使用Linux。另请注意,如果您需要该功能(嗅探内容)考虑搜索promiscuous mode相关匹配,则此套接字可能无法获取所有传出数据包。

现在您需要做的就是将每个数据包视为它们进入或进入的段,例如 - 解压缩以太网和IP帧看起来像这样:

frame, meta = s.recvfrom(65565)
print(frame, meta)

ethernet = frame[0:14]
ethernet_segments = struct.unpack("!6s6s2s", ethernet)

mac_source, mac_dest = (binascii.hexlify(mac) for mac in ethernet_segments[:2])

ip = frame[14:34]
ip_segments = struct.unpack("!12s4s4s", ip)

ip_source, ip_dest = (socket.inet_ntoa(section) for section in ip_segments[1:3])

print('MAC Source:', b':'.join(mac_source[i:i+2] for i in range(0, len(mac_source), 2)))
print('MAC Dest:', b':'.join(mac_dest[i:i+2] for i in range(0, len(mac_dest), 2)))
print('IP Source:', ip_source)
print('IP Dest:', ip_dest)

考虑到您自己构建数据包,因此预付费将是“轻松”#34; 所有这些都不是最传统的方式或最初的最快方式,但你能够实现你想要的任何方式。

发送同样简单,使用struct并查看那里的许多ICMP示例,包括那些带校验和计算的示例:

关于MTU,这是你必须自己实施的逻辑,因为没有预先构建的库能够实现我所知道的。

但这是我通过Python发送原始IP流量的贡献。

答案 1 :(得分:1)

在python中发送任何原始内容,你正在使用scapy。

有关如何发送ping消息的信息:

http://www.secdev.org/projects/scapy/doc/usage.html#icmp-ping

设置DF标志:

IP(flags='DF')

如何调整特定大小以便模拟碎片:

Adding payload in packet (scapy)

全部放在一起:

data = "x" * 1473
ans,unans = sr(IP(dst="<target_ip>", flags='DF' )/ICMP() / Raw(load=data))

如果你真的没有兴趣创建这些东西,那么这个问题是重复的:How to find mtu value of network through code(in python)?