从通过Python原始套接字接收的ICMP消息中读取TTL

时间:2016-04-21 19:15:29

标签: python sockets datagram icmp raw-sockets

我正在构建一个traceroute-ish工具来确定UDP数据包仅使用一个探测到达地址所需的跳数。为此,我想从发送探测后收到的ICMP消息中提取TTL。我正在执行以下操作并成功接收ICMP消息:

data, source = in_socket.recvfrom(d_bufsize)

但我不知道如何将data变成我可以读取TTL的东西。 in_socket声明如下:

in_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp_proto)

此处,icmp_proto只是ICMP的协议号(通过icmp_proto = socket.getprotobyname("icmp")获得)。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

  

但我不知道如何将data变成我能读到的东西   TTL来自。

pyping这样做:

    def header2dict(self, names, struct_format, data):
        """ unpack the raw received IP and ICMP header informations to a dict """
        unpacked_data = struct.unpack(struct_format, data)
        return dict(zip(names, unpacked_data))
…

            packet_data, address = current_socket.recvfrom(ICMP_MAX_RECV)

            icmp_header = self.header2dict(
                names=[
                    "type", "code", "checksum",
                    "packet_id", "seq_number"
                ],
                struct_format="!BBHHH",
                data=packet_data[20:28]
            )

            if icmp_header["packet_id"] == self.own_id: # Our packet
                ip_header = self.header2dict(
                    names=[
                        "version", "type", "length",
                        "id", "flags", "ttl", "protocol",
                        "checksum", "src_ip", "dest_ip"
                    ],
                    struct_format="!BBHHHBBHII",
                    data=packet_data[:20]
                )
                packet_size = len(packet_data) - 28
                ip = socket.inet_ntoa(struct.pack("!I", ip_header["src_ip"]))

然后可以从ip_header["ttl"]读取TTL。