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

gue*_*tli 6 python ip mtu

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

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

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

Tor*_*xed 3

我想补充一点,您也可以使用原始套接字。
scapy是一个很好的抽象层,它为您带来了很多魔力,但平心而论,如果您打算降低水平,您可以一路走来获得学习体验。(请注意,在大多数现代操作系统中,原始套接字需要提升权限,并且随着您的深入,Windows 和 Linux 的实现可能会有所不同。)

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个基于原始数据包的套接字,它实际上为您提供所有帧。Windows 和 Linux 之间略有不同,但在这个答案中我将坚持使用 Linux。另请注意,此套接字可能不会拾取所有传出数据包,如果您需要该功能(嗅探东西),请考虑搜索与混杂模式相关的命中。

您现在需要做的就是将每个数据包视为它们进入或进入的段,例如 - 解包以太网和 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)
Run Code Online (Sandbox Code Playgroud)

考虑到您自己构建数据包,有效负载将“容易”。
无论它不是最传统的方法还是最初最快的方法,但您都可以实现您想要的任何方法。

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

关于 MTU,这是您必须自己实现的逻辑,因为据我所知,没有预构建的库可以执行此操作。

但这是我对使用 Python 发送原始 IP 流量的贡献。