3

我正在尝试使用 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)。即使它出现在 Wireshark 中,我也从未收到包含 ICMP 有效负载的 IP 数据包。

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

谢谢您的帮助

4

1 回答 1

0

这个答案来看,您似乎需要IPPROTO_ICMP在创建套接字时传递该选项。

你可以这样做:

my_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
于 2012-11-28T01:00:05.833 回答