Python原始套接字未收到ICMP数据包
问题描述:
我试图在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标头非常相似。我不知道什么是错的。
感谢您的帮助
答
从this answer来看,它看起来像你需要传递,当你创建你的插座在IPPROTO_ICMP
选项。
可以做到这一点,如:
my_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
+0
我认为这只会筛选传入的数据包,因为添加它会导致我的程序挂起(看起来等待ICMP数据包到达,然后超时)。一旦我得到这个工作,但它绝对看起来像一个很好的补充,所以我不必每次手动检查协议,因为我目前做。 – Rafael
如果我在IP设置TTL = 0报头相同的一段代码并检测所述ICMP应答。当然,这是无用的,但认为它可能有助于检测问题... – Rafael