2012-11-28 81 views
3

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

我已经设法正确构建我的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)。即使它出现在Wireshark中,我也不会得到包含ICMP有效载荷的IP数据包。

我试过将Wireshark中的ICMP数据包与Wireshark中的其他数据包进行比较,我的程序确实看到和IP标头非常相似。我不知道什么是错的。

感谢您的帮助

+0

如果我在IP设置TTL = 0报头相同的一段代码并检测所述ICMP应答。当然,这是无用的,但认为它可能有助于检测问题... – Rafael

回答

0

this answer来看,它看起来像你需要传递,当你创建你的插座在IPPROTO_ICMP选项。

可以做到这一点,如:

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

我认为这只会筛选传入的数据包,因为添加它会导致我的程序挂起(看起来等待ICMP数据包到达,然后超时)。一旦我得到这个工作,但它绝对看起来像一个很好的补充,所以我不必每次手动检查协议,因为我目前做。 – Rafael

相关问题