Python原始套接字没有收到ICMP数据包

时间:2012-11-28 00:15:26

标签: python sockets udp icmp

我正在尝试使用Python中的原始套接字将UDP数据包发送到主机,然后为数据包获取ICMP响应 - 基本上重新实现了traceroute。

我设法正确构建了我的IP和UDP标头并发送了数据包。我可以在Wireshark中看到它。我还看到Wireshark中的ICMP响应告诉我TTL超出了。

我有以下代码:

me = gethostbyname(gethostname())
my_socket = socket(AF_INET, SOCK_RAW)
my_socket.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)
my_socket.bind((me, 0))

hostname = 'www.google.com'
hostip = gethostbyname(hostname)

packet = create_packet(hostname)
send_socket.sendto(packet, (hostip , 0))

然后在发送数据包后,我调用另一个函数来侦听包含此代码段的传入数据包:

while True:
    ready = select.select([my_socket], [], [], time_left)
    if ready[0] == []:
        print "timeout"
    time_now = time.time()
    rec_packet, addr = my_socket.recvfrom(5120)

    unpacked_ip = unpack('!BBHHHBBH4s4s', rec_packet[0:20]) #0-20 is IP header
    prot = unpacked_ip[6] #gives the protocol id
    if prot == 1:
        #this is ICMP , let's do things

我能够成功解压缩IP头并检查协议,但它总是6或17(TCP或UDP)。我永远不会得到包含ICMP有效负载的IP数据包,即使它出现在Wireshark中。

我已经尝试将Wireshark中的ICMP数据包与我的程序看到的Wireshark中的其他数据包进行比较,并且IP头几乎完全相同。我不知道出了什么问题。

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

this answer判断,看起来你需要在创建套接字时传递IPPROTO_ICMP选项。

您可以这样做:

my_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)