2012-11-28 131 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

相關問題