我正在尝试使用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头几乎完全相同。我不知道出了什么问题。
感谢您的帮助
答案 0 :(得分:0)
从this answer判断,看起来你需要在创建套接字时传递IPPROTO_ICMP
选项。
您可以这样做:
my_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)