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

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

从:https://networkengineering.stackexchange.com/a/28988/23983

Send a ping to a target, in my example, I’ll use Google’s DNS server (8.8.8.8). Set your DF bit in your ping to on, to prevent your ping from being fragmented. Set your packet size to some large number, or the standard MTU of 1500. Note that some ping implementations set the size of just the payload, which means you have to account for the 8 byte ICMP header, and 20 byte IP header.

解决方法:

我想补充一点,您也可以使用原始套接字.
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)

考虑到您自己构建数据包,有效负载将“轻松”.
所有这些都不是最传统的方法,也不是最初最快的方法,但是您将能够实现所需的任何东西.

发送同样容易,请使用struct,并查看其中的许多ICMP示例,包括带有校验和计算的示例:

> https://www.g-loaded.eu/2009/10/30/python-ping/
> https://gist.github.com/pklaus/856268

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

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

上一篇:TCP最大报文段长度MSS


下一篇:浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)