traceRoute mit Ortsangabe

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Nikolas
User
Beiträge: 102
Registriert: Dienstag 25. Dezember 2007, 22:53
Wohnort: Freiburg im Breisgau

Hallo

Ich höre gerade Systeme 2 (Netzwerke) und da wir uns dort gerade mit TCP/IP, Routing, usw beschäfigen wollte ich mal sehen, wo meine Packete durch die Gegend ziehen. TraceRoute bietet unter Unix diese Möglichkeit, gibt aber nur die IPAdressen der benutzten Router aus. Per whois kann man dann für größere Server noch zusätzliche Informationen besorgen.
Ich habe also einfach normales traceRoute ausgeführt und für jede Adresse ein whois gestartet und die Rückgabe nach der Stadt geparst.
Jetzt kann man einfach eine beliebige IP eingeben und bekommt die Städte ausgegeben, durch die das Packet reist. (Solange die Server bei whois angemeldet sind). Gibt man eine www-Adresse ein, wird ein einzelner ping durchgeführt, dei ip geparst und dann das traceroute durchgeführt.
Bevor die Städte ausgegeben werden, wird gewartet bis das traceroute durch ist, wenn das stecken bleibt wird auch nichts ausgegeben, auch wenn schon ein paar Server durchlaufen wurden.

Das werde ich vielleicht noch ändern, damit man sehen kann, wo das Packet geblieben ist, aber bis jetzt habe ich subprocess noch nicht weit genug verstanden, um das so zu machen.

Ich habe gestern meine Uni gesucht (Freiburg) und habe gesehen, dass das Packet über Sulzbach (Taunus)(da sitzt Arcor), Frankfurt und Karlsruhe gelaufen ist. Luftlinie zum Rechenzentrum sind grob 3km :lol:

Viel Spaß

// mich würde besonders interessieren, ob das Programm auch unter Linux läuft, bei windows dürfte es nicht laufen.

Code: Alles auswählen

#!/usr/bin/python

from urllib2 import urlopen
import re
import string
import os, popen2, subprocess
from optparse import OptionParser 

# Ermittlung der Stadt in dem der Router mit dieser IP steht
def getAdress(ip):
    l = executeInTerminal(["whois",ip]);

    # der erste String in der Adresse,
    # der 5 Zahlen beinhaltet, wird zurueckgegegben. 
    for line in l[10:]: # erster Abschnitt beinhaltet Adresse von Ripe Network Coordination Center
        m = re.match('address:.*\d{5}.*',line)
        if m!=None:
            x = m.string
            x = string.replace(x,"address:","")
            return string.lstrip(x)

    return "AdressError"


# traceroute mit Ortsangabe der Router
def traceEnhanced(ip):
    
    l = executeInTerminal(['traceroute',ip])
    
    for s in l[:-1]:
        start = s.find("(")
        end   = s.find(")")
        ipAdress = s[start+1:end]
        
        if s.rfind("localhost")>-1:
            print s[:start]+" "+ipAdress
            continue
        
        print s[:start]+" "+ipAdress+"  \t"+getAdress(ipAdress)

# die uebergebenen Befehle werden im Terminal ausgefuehrt, 
# wenn sie fertig sind, wird die Ausgabe als Zeilen liste zurueckgegeben
def executeInTerminal(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    process.wait()
    lines =  process.stdout.read()
    return string.split(lines,"\n")


parser = OptionParser()
(options,args) = parser.parse_args()

# Adresse aus dem Paramezer
ip = args[0]

# falls eine www-Adresse angegeben wurde, wird ein einzelnes Packet
# hingeschickt, um die IP zu ermitteln
if args[0].rfind("www")>-1:
    lines = executeInTerminal(['ping','-c 1',args[0]]);
    s = lines[1]
    start = s.find("from ")
    end = s.find(":")
    ip = s[start+5:end]


traceEnhanced(ip) 

Erwarte das Beste und sei auf das Schlimmste vorbereitet.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du solltest keine Code auf Modul-Ebene ausführen, dann kannst du es nur schlecht wiederverwenden. Verdecke diesen besser mit einem:

Code: Alles auswählen

if __name__ == "__main__":
    ....
Bezüglich der Funktionsnamen solltest du vielleicht noch einmal PEP8 lesen und an der ein oder anderen stelle Kommentare einfügen. Die "magic numbers" sollltest du eventuell noch durch Konstaten ersetzen, sonst bist du schon in einem Monat am überlegen, was diese eigentlich bedeuten.

Falls nicht alle Parameter übergeben wurden, wäre eine Fehlermeldung natürlich auch noch schön.

P.S.: Es heißt "address" ;-)
Zuletzt geändert von EyDu am Sonntag 29. Juni 2008, 11:41, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Übrigens: statt den Hostnamen mit Ping aufzulösen kannst du ``socket.gethostbyname()`` verwenden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nikolas
User
Beiträge: 102
Registriert: Dienstag 25. Dezember 2007, 22:53
Wohnort: Freiburg im Breisgau

Dann noch mal:

Wenn ich das Progrmm per cntr-c abbreche, bekomme ich eine mehrzeilige Meldung über den Programmzustand als der KeyboardInterrupt kam. Wie kann ich das denn abschalten? Im Endeffekt will ich gar nicht mehr erkennen müssen, dass das Programm in Python geschrieben wurde.

Code: Alles auswählen

#!/usr/bin/python

from urllib2 import urlopen
import re
import string
import os, popen2, subprocess
from optparse import OptionParser 
import socket

# Ermittlung der Stadt in dem der Router mit dieser IP steht
def getAdress(ip):
    l = executeInTerminal(["whois",ip]);

    # der erste String in der Adresse,
    # der 5 Zahlen beinhaltet, wird zurueckgegeben. 
    for line in l[10:]: # erster Abschnitt beinhaltet Adresse von Ripe Network Coordination Center
        m = re.match('address:.*\d{5}.*',line)
        if m!=None:
            x = m.string
            x = string.replace(x,"address:","")
            return string.lstrip(x)

    return "AddressError"


# traceroute mit Ortsangabe der Router
def traceEnhanced(ip):
    
    l = executeInTerminal(['traceroute',ip])
    
    for s in l[:-1]:
        start = s.find("(")
        end   = s.find(")")
        ipAdress = s[start+1:end]
        
        if s.rfind("localhost")>-1:
            print s[:start]+" "+ipAdress
            continue
        
        print s[:start]+" "+ipAdress+"  \t"+getAdress(ipAdress)

# die uebergebenen Befehle werden im Terminal ausgefuehrt, 
# wenn sie fertig sind, wird die Ausgabe als Zeilen liste zurueckgegeben
def executeInTerminal(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    process.wait()
    lines =  process.stdout.read()
    return string.split(lines,"\n")


if __name__ == "__main__": 

	parser = OptionParser()
	(options,args) = parser.parse_args()


	# Adresse aus dem Parameter
	try: 
		ip = args[0]
	except:
		print "no address given"
		quit()
		
	# ermittlung der IP aus der www-Adresse
	if args[0].rfind("www")>-1:
		ip = socket.gethostbyname(args[0])
    	
	traceEnhanced(ip) 
	
Erwarte das Beste und sei auf das Schlimmste vorbereitet.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Der KeyboardInterrput ist nicht mehr als eine Exception, die Anpassung um diese Abzufangen ist minimal:

Code: Alles auswählen

if __name__ == "__main__":
    try:
        #Hier der bisherige Inhalt
    except KeyboardInterrupt:
        #Hier einfügen, was bei Ctrl+C passieren soll
Du solltest übrigens kein "except" verwenden, ohne anzugeben welche Excpetions abgefangen werden soll. Andernfalls wir der Code sehr schwer zu debuggen, da alles verschluckt wird. Du solltest also noch etwas anpassen:

Code: Alles auswählen

try:
    ip = args[0]
except IndexError:
    ...
Und da du args[0] an ip gebunden hast, kannst du es natürlich danach auch verwenden und musst nicht wieder zurück auf args[0] greifen. Möchtest du nur testen, dann reicht auch:

Code: Alles auswählen

try:
    args[0]
except IndexError:
    ...
Edit:

Statt

Code: Alles auswählen

 print x+" "+y+" "+....
kannst du auch

Code: Alles auswählen

print x, y, ...
schreiben.

Das "continue" in der "traceEnhanced"-Funktion kannst du durch ein "else" ersetzen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

EyDu hat geschrieben:Du solltest übrigens kein "except" verwenden, ohne anzugeben welche Excpetions abgefangen werden soll. Andernfalls wir der Code sehr schwer zu debuggen, da alles verschluckt wird. Du solltest also noch etwas anpassen:
Aber da sieht man dann dass es ein Python-Programm ist. Man könnte ja except und dann das Programm mit der Ausgabe "Segmentation fault" teminieren lassen, dann ist es von einem C-Programm kaum zu unterscheiden :twisted:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nikolas
User
Beiträge: 102
Registriert: Dienstag 25. Dezember 2007, 22:53
Wohnort: Freiburg im Breisgau

So mal eine neue Version:

In jeder Zeile werden jetzt ipAdresse und Stadt rechtsbündig dargestellt.
Ist die Zeile zu kurz wird der Name des Servers gekürzt.

Code: Alles auswählen

#!/usr/bin/python

from urllib2 import urlopen
import re
import string
import os, popen2, subprocess
from optparse import OptionParser 
import socket


## Berechnung der Terminalgroese
def ioctl_GWINSZ(fd):                  #### TABULATION FUNCTIONS
     try:                                ### Discover terminal width
         import fcntl, termios, struct, os
         cr = struct.unpack('hh',
                            fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
     except:
         return None
     return cr

def terminal_size():
     ### decide on *some* terminal size
     # try open fds
     cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
     if not cr:
         # ...then ctty
         try:
             fd = os.open(os.ctermid(), os.O_RDONLY)
             cr = ioctl_GWINSZ(fd)
             os.close(fd)
         except:
             pass
     if not cr:
         # env vars or finally defaults
         try:
             cr = (env['LINES'], env['COLUMNS'])
         except:
             cr = (25, 80)
     # reverse rows, cols
     return int(cr[1]), int(cr[0])
# Ende Terminalgroese



# Ermittlung der Stadt in dem der Router mit dieser IP steht
def getAddress(ip):
    l = executeInTerminal(["whois",ip]);

    # der erste String in der Adresse,
    # der 5 Zahlen beinhaltet, wird zurueckgegeben. 
    for line in l[10:]: # erster Abschnitt beinhaltet Adresse von Ripe Network Coordination Center
        m = re.match('address:.*\d{5}.*',line)
        if m!=None:
            x = m.string
            x = string.replace(x,"address:","")
            return string.lstrip(x)

    return "AddressError"


# traceroute mit Ortsangabe der Router
def traceEnhanced(ip):
    
     l = executeInTerminal(['traceroute',ip])

     for s in l[:-1]:
          start = s.find("(")
          end   = s.find(")")
          ipAddress = s[start+1:end]

          if s.rfind("localhost")>-1:
               print s[:start]+" "+ipAddress
               continue

          # zeichen pro Zeile im Terminal
          length = terminal_size()[0]


          leftString = s[:start]
          address = getAddress(ipAddress)

          string = leftString.ljust(length-len(ipAddress)-len(address)-2)+ipAddress+"  "+address

          print string

# die uebergebenen Befehle werden im Terminal ausgefuehrt, 
# wenn sie fertig sind, wird die Ausgabe als Zeilen liste zurueckgegeben
def executeInTerminal(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE)

    process.wait()
    lines =  process.stdout.read()
    return string.split(lines,"\n")


if __name__ == "__main__":

     print terminal_size()[0]
	
     try:
          parser = OptionParser()
          (options,args) = parser.parse_args()


   # Adresse aus dem Parameter
          try: 
                  ip = args[0]
          except IndexError:
                  print "no address given"
                  quit()
   
          # ermittlung der IP aus der www-Adresse
          if ip.rfind("www")>-1:
                  ip = socket.gethostbyname(args[0])
   
          traceEnhanced(ip) 
     except KeyboardInterrupt:
          pass
Erwarte das Beste und sei auf das Schlimmste vorbereitet.
farid
User
Beiträge: 95
Registriert: Mittwoch 8. Oktober 2008, 15:37

Nikolas hat geschrieben:Ich habe also einfach normales traceRoute ausgeführt und für jede Adresse ein whois gestartet und die Rückgabe nach der Stadt geparst.
Oh nein, bitte nicht so! Damit kannst Du Dir schneller einen Ban von Whois-Serverbetreibern einhandeln als Dir lieb ist.

Ausserdem, gibt's das nicht schon?

http://www.freshports.org/net/ntraceroute

ftp://ftp.netbsd.org/pub/pkgsrc/current ... e-as/DESCR

Hintergrund:

http://www.research.att.com/~jiawang/as_traceroute/
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@Nikolas: Hast Du Dir die Tipps auch einmal durchgelesen? Du scheinst außer dem Verbannen von Code aus der Modulebene nichts weiter geändert zu haben ...
Antworten