Projekte

Aussenzugriff bei dynamischer IP

Internet GlobeWer im Heimnetzwerk einen Server oder eine NAS betreibt und gerne von ausserhalb auf die selbstgehosteten Dienste zugreifen möchte, braucht eine statische Anlaufstelle von der aus auf die dynamische Adresse des Heimnetzwerkes zugegriffen werden kann. Die Internetprovider ändern in der Regel die eigene IP regelmässig oder beim Booten des Modems. Zu diesem Zweck gibt es Anbieter (wie z.B. https://www.dynip.com), die für 30$ pro Jahr einen entsprechenden Service anbieten. Es geht aber auch kostenlos mit einer eigenen Lösung.


Das Prinzip für den Aussenzugriff in Eigenregie ist ganz einfach.

  1. Die aktuelle dynamische IP herausfinden
  2. Prüfen, ob sich die IP überhaupt verändert hat
  3. Falls ja, wird die neue IP lokal gespeichert
  4. Eine html-Datei mit der neuen IP aktualisieren
  5. Hochladen der geänderten html-Datei


Es gibt eine wichtige Voraussetzung, man muss Zugriff auf einen Server ausserhalb des Heimnetzwerkes haben. Das kann z.B. eine eigene Homepage sein, die bei einem Provider gehostet wird oder aber der Server eines Bekannten. Dieser Server muss auf jeden Fall über einen statischen Domänennamen erreichbar sein was aber immer der Fall sein sollte.

Der Zugriff erfolgt dann so:
Aufruf von z.B.: www.hanswurst.ch/dynip.html. Dabei ist www.hanswurst.ch der statische Teil, der sich nicht ändern darf. Die Datei dynip.html wird von uns selbst generiert und verweist auf die aktuelle dynamische IP des Heimnetzwerkes. In der Datei erfolgt eine Umleitung auf eine beliebige Adresse im Heimnetzwerk, z.B. auf den Filemanager einer NAS.

Nun kommt die Schritt-für-Schritt Anleitung. Alle Schritte finden in einem einfachen Phython Skript statt das am Ende des Artikels zum Download bereitsteht.


1. Die aktuelle dynamische IP herausfinden

Dazu kann man den Service von dyndns.org verwenden. Durch Aufruf der URL (http://checkip.dyndns.org) wird die aktuelle dynamische IP geliefert, kannst du gleich einmal im Webbrowser ausprobieren. Das Skript liest dann die IP aus dem Ergebnis.

Hier der Code dazu:

# return the current dynamic ip
def get_ip():
    page = str(urllib.request.urlopen("http://checkip.dyndns.org/").read())
    start_string = ":"
    end_string = "</body>"
    offset = 2
    start_pos = page.find(start_string, 0) + offset
    end_pos = page.find(end_string, start_pos)
    ip = page[start_pos:end_pos]
    ip = ip.strip()
    return ip


2. Prüfen, ob sich die IP überhaupt verändert hat .. und ..
3. Falls ja, wird die neue IP lokal gespeichert

Beim Aufruf des Skripts wird die ermittelte IP immer gespeichert. Dadurch kann man prüfen, ob sich bei einem erneuten Aufruf die IP überhaupt verändert hat. Falls sie unverändert ist, muss nämlich gar nichts gemacht werden weil der Aussenzugriff ja immern noch funktioniert.

Hier der Code zu Schritt 2 und 3:

# compare old with new ip and write new ip to file if different to old ip
def compare_ips(new_ip):
    filename = 'dynip.txt'
    if os.path.exists(filename):
        changed = False
        f = open(filename, 'r')
        old_ip = f.read()
        f.close()
        old_ip = old_ip.strip()
    else:
        old_ip = ''
    
    if new_ip != old_ip:
        f = open(filename, 'w')
        f.write(new_ip)
        changed = True
        f.close()
    return changed, old_ip


4. Eine html-Datei mit der neuen IP aktualisieren

Falls der Service eine geänderte IP geliefert hat, muss die html-Datei angepasst werden.

Mit diesem Code:

# update dynip.html file with new ip
def update_html(old_ip, new_ip):
    f = open(FILENAME, 'r')
    htm = f.read()
    f.close()
    htm = htm.replace(old_ip, new_ip)
    f = open(FILENAME, 'w')
    f.write(htm)
    f.close()


5. Hochladen der geänderten html-Datei

Im letzten Schritt wird die geänderte html-Datei per FTP auf den Aussenserver hochgeladen:

# upload html file to FTP server
def upload_html():
    ftpsrv = 'hanswurst.ch'    # FTP Server path
    ftpusr = 'username'        # FTP Username
    ftppsw = 'password'        # FTP Password
    ftpdir = 'html/something/' # FTP Directory
    
    print("Connecting to FTP server ...")
    ftp = ftplib.FTP(ftpsrv)   # connect
    print(ftp.getwelcome())
    try:
        ftp.login(ftpusr, ftppsw)
        ftp.cwd(ftpdir)
        f = open(FILENAME, "rb")
        ftp.storbinary('STOR ' + FILENAME, f)    # upload file
        f.close()
        print(FILENAME + ' uploaded successfully')
    except:
        print('Upload to FTP server failed')
    finally:
        ftp.quit()


Die aktualisierte html-Datei sieht dann z.B. so aus:

<html>
<head>
<meta http-equiv="Refresh" content="0; URL=http://56.77.21.40:443">
</head>
<body></body>
</html>

Aktualisert wurde nur der Teil '56.77.21.40'. Der Port ':443' ist fester Bestandteil der html-Datei und kann nach eigenem Gusto gesetzt werden falls nötig.

 

Das ZIP Archiv enthält drei Dateien:

  • dynip.py - Das Python3 Skript
  • dynip.txt - Für das lokale Speichern der aktuellen IP
  • dynip.html - Die html-Datei, die auf den Server hochgeladen wird

Dynip-ZIP-Archiv