2016-04-21 29 views
1

Ich erstelle ein traceroute-ish-Tool, um die Anzahl der Hops zu ermitteln, die für ein UDP-Paket benötigt werden, um eine Adresse mit nur einer Sonde zu erreichen. Zu diesem Zweck möchte ich die TTL aus der ICMP-Nachricht, die ich nach dem Senden der Sonde erhalte, extrahieren. Ich mache das folgende und erfolgreich die ICMP-Nachricht empfangen:TTL aus einer ICMP-Nachricht lesen, die über Python-Raw-Sockets empfangen wurde

data, source = in_socket.recvfrom(d_bufsize) 

Aber ich habe keine Ahnung, wie data zu etwas machen, dass ich die TTL aus lesen kann. in_socket wird wie folgt erklärt:

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

Hier icmp_proto nur die Protokollnummer für ICMP ist (erhalten durch icmp_proto = socket.getprotobyname("icmp") tun).

Jede Hilfe wäre sehr willkommen!

+0

Die TTL ist im IP-Header, nicht Teil von ICMP. Wenn dies nicht das gesamte IP-Paket zurückgibt, können Sie es nicht tun. – Barmar

+0

@Barmar: Der Trick ist, dass die ICMP-Nachricht einen Teil des Datagramms enthält, das den Fehler ausgelöst hat. Indem Sie also ein Datagramm mit einer bekannten TTL aussenden und dann den enthaltenen Teil des fehlerauslösenden Datagramms verwenden, um seine TTL bei der Ankunft zu bestimmen, sollten Sie in der Lage sein, die Anzahl der Hops zu bestimmen. – hexaflexagonal

+0

Oh, ich dachte, Sie sprachen über die TTL des empfangenen Datagramms, nicht über die TTL des gesendeten Datagramms, das den ICMP ausgelöst hat. – Barmar

Antwort

1

Aber ich habe keine Ahnung, wie data zu etwas zu machen, das ich von die TTL lesen kann.

pyping tut es so aus:

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"])) 

Die TTL kann dann von ip_header["ttl"] gelesen werden.