无法从Python中的原始套接字发送ICMP数据包

Har*_*vey 6 python sockets udp wireshark

我有一个原始的Python套接字初始化如下:

mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
mySocket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
Run Code Online (Sandbox Code Playgroud)

我的问题是我不能从套接字发送任何数据包,我的IP头中的协议字段被指定为'1'(ICMP).如果这个字段是其他任何东西它就可以正常工作,例如包括'17'(UDP).我没有收到任何错误,数据包只是没有显示在Wireshark中,我无法在我的服务器上收到它.

我正在生成IP头,如下所示:

def getIPHeader(src, dst, proto):
    version = 4
    IHL = 5
    DSCP = 0
    ECN = 0
    totalLength = 40
    identification = 333
    flags = 0
    fragmentOffset = 0
    timeToLive = 128
    protocol = proto
    headerChecksum = 0
    sourceIP = socket.inet_aton(src)
    destIP = socket.inet_aton(dst)
    options = 0

    version_IHL = (version << 4) | IHL
    DSCP_ECN = (DSCP << 2) | ECN
    flags_fragmentOffset = (flags << 13) | fragmentOffset

    # The '!' ensures all arguments are converted to network byte order
    header = struct.pack("!BBHHHBBH4s4s", version_IHL, DSCP_ECN, totalLength, identification, flags_fragmentOffset, timeToLive, protocol, headerChecksum, sourceIP, destIP)
    return header
Run Code Online (Sandbox Code Playgroud)

像这样发送:

icmpHeader = struct.pack("!bbHHh", 8, 0, 0, 666, 0)
packet = getIPHeader("192.168.2.15", "8.8.8.8", 1) + icmpHeader
mySocket.sendto(packet, ("8.8.8.8", 0))
Run Code Online (Sandbox Code Playgroud)

使用UDP协议集发送工作(显然格式不正确):

icmpHeader = struct.pack("!bbHHh", 8, 0, 0, 666, 0)
packet = getIPHeader("192.168.2.15", "8.8.8.8", 17) + icmpHeader
mySocket.sendto(packet, ("8.8.8.8", 0))
Run Code Online (Sandbox Code Playgroud)

最糟糕的是如果我从命令行发送ping,然后将Wireshark中IP和ICMP数据的确切十六进制复制到我的代码中,它仍然无效,如下所示:

packet = b'\x45\x00\x00\x3c\x24\xad\x00\x00\x80\x01\x43\x4d\xc0\xa8\x02\x0f\x08\x08\x08\x08\x08\x00\x4d\x44\x00\x01\x00\x17\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x61\x62\x63\x64\x65\x66\x67\x68\x69'
mySocket.sendto(packet, ("8.8.8.8", 0))
Run Code Online (Sandbox Code Playgroud)

但是,和以前一样,如果我将硬编码数据的第10个字节更改为'\ x11'(17十进制,UDP),我可以在Wireshark中看到它(显然有一个格式错误的UDP部分,因为其余的数据包是ICMP ).

我正在运行Windows 10,Python 3.4.1,我的防火墙已关闭.有任何想法吗?

更新:我在两台不同的计算机上尝试过这种方法,一台Windows 8和一台Windows 10机器都工作了,所以它与我的电脑有关,情节变厚......