DyndnsAutoLogin

Aus Synology Wiki
Wechseln zu: Navigation, Suche

In diesem Artikel geht es um die Möglichkeit, sich bei DynDNS mittels Python-Script automatisch anmelden zu können.

Die neue SLA von DynDNS schreibt allen FreeUser-Accounts vor, sich einmal im Monat online einzuloggen. Anderenfalls werden die eingetragenen Hosts gelöscht und müssen neu eingetragen werden. Alternative hierzu wäre der offizielle Weg, ein Pro-Account für 25$ im Jahr.

Inhaltsverzeichnis

Voraussetzungen

  • DSM >= 3.2
  • Python >= 2.6 (nicht kompatibel mit 3.x!)

Python 2.x kann problemlos über das DSM-Paketzentrum gedownloadet und auch bei installiertem Python 3.x parallel installiert und betrieben werden.

Das Script: dyndnsAutoLogin

#!/volume1/@appstore/Python/usr/local/bin/python

import urllib
import urllib2
import cookielib
import getopt
import sys
import logging

def getRandHTMLResponse(response):
    target = "<form id=\'login"
    targetresponse = "<div id=\'loginbox\'"

    response = response[response.find(targetresponse):len(response)]
    return response[response.find(target)+len(target):response.find(target)+len(target):response.find(target)+len(target)+4]

def getHiddenRandHTMLResponse(response):
    target = "<input type=\'hidden\' name=\'multiform\' value=\'"
    targetresponse = "<div id=\'loginbox\'"
    parsedres = response[response.find(targetresponse):len(response)]
    return parsedres[parsedres.find(target)+len(target):parsedres.find(target)+len(target)+34]

def checkLogin(response):
    target = "<title>My Dyn Account</title>"
    if response.find(target) == -1:
        return False
    return True

def usage():
    print "usage: ./dyndnsAutoLogin [options]"
    print ""
    print "options:"
    print "-h, --help 	 show this help message and exit"
    print "-u, --username   set your DynDns login_username"
    print "-p, --password   set your DynDns login_password"
    print ""
    print "example:"
    print "./dyndnsAutoLogin -u username -p password"

class HTMLSession:
    cj = None
    opener = None
    txHeaders = None
    
    def __init__(self, txHeaders):
        #The CookieJar will hold any cookies necessary throughout the login process.
        self.cj = cookielib.MozillaCookieJar()
        self.txHeaders = txHeaders
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
        urllib2.install_opener(self.opener)

    def setHeaders(self, txheaders):
        self.txHeaders = txHeaders

    def getHeaders(self):
        return self.txHeaders

    def openURI(self, uri, txdata):
        try:
            req = urllib2.Request(uri, txdata, self.txHeaders)
            # create a request object

            handle = urllib2.urlopen(req)
            # and open it to return a handle on the url

        except IOError as e:
            print 'we failed to open "%s".' % uri

            if hasattr(e, 'code'):
                print 'We failed with error code - %s.' % e.code
                logging.error('We failed with error code - %s.' % e.code)
            elif hasattr(e, 'reason'):
                print "The error object has the following 'reason' attribute :"
                print e.reason
                print "This usually means the server doesn't exist,'"
                print "is down, or we don't have an internet connection."
                return None
        else:
            return handle.read()

def main(argv):
    username = ""
    password = ""
    logfile = "/var/log/dyndnsAutoLogin.log"
    hiddenval = ""
    theurl = "https://account.dyn.com/entrance/"
    thelogouturl = "https://account.dyn.com/entrance/?__logout=1"
    txdata = None
    txheaders =  {'User-agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
    # fake a user agent, some websites (like google) don't like automated exploration
    logging.basicConfig(filename=logfile,level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y/%m/%d %H:%M:%S')

    try:
        opts, args = getopt.getopt(argv, "hu:p:", ["help", "username=","password="])
    except getopt.GetoptError:
        usage()
        logging.warning('Manual login with incorrect parameters')
        exit(2)
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            exit(2)
        elif opt in ("-u", "--username"):
            username = arg
        elif opt in ("-p", "--password"):
            password = arg

    myhtmlsession = HTMLSession(txheaders)
    response = myhtmlsession.openURI(theurl, None)

    if response == None:
        sys.exit(0)

    hiddenval = getHiddenRandHTMLResponse(response)
    txdata = urllib.urlencode({'username':username, 'password':password, 'multiform':hiddenval, 'submit': "Log in"})

    response = myhtmlsession.openURI(theurl, txdata)
    if response == None:
        sys.exit(0)
    
    #we should sleep here for about 10 seconds.
    if checkLogin(response):
        print 'We have succesfully logged into DynDNS.'
        logging.info('We have succesfully logged into DynDNS.')
    else:
        print 'Login failed'
        logging.info('Login failed')

    response = myhtmlsession.openURI(thelogouturl, None)
    if response == None:
        sys.exit(0)

if __name__ == "__main__":
    main(sys.argv[1:])


Ab DSM 5.x muss die erste Zeile mit folgender ersetzen werden:

#!/usr/local/packages/@appstore/Python/usr/local/bin/python

Einstellungen und Parameter

In der "def main" (Zeile 81) lassen sich folgende Einstellungen treffen:

  • username: Dein DynDNS Benutzername
  • password: Dein DynDNS Passwort
  • logfile: Der Pfad zum Logfile (Standardmäßig /var/log/dyndnsAutoLogin.log, hier empfiehlt sich aber ein Pfad, der auch über die File Station erreichbar ist, um das Logfile auch mit der DSM auslesen, bzw. herunterladen zu können. Beispielsweise einen Gemeinsamen Ordner)
  • hiddenval: Wert für versteckte Elemente in Formularen (bei DynDNS nicht nötig)
  • theurl: Die URL zur Login-Seite
  • thelogouturl: Die URL zur Logout-Seite
  • txdata: Muss auf "None" stehen!
  • txheaders: Als welcher Browser sich das Script ausgeben soll (hier Mozilla/4.0)

Wichtig ist hier alles in doppelten Anführungszeichen zu schreiben ( " " )

Für Konsolen-Benutzer: Benutzername und Passwort können auch über die jeweiligen Parameter (-u username -p password) dem Script übergeben werden.

Installation und Einbinden mittels DSM Aufgabenplaner

  • Das Script in die Zwischenablage kopieren und in einen Editor seiner Wahl einfügen. (Der Editor muss "Line ending = LF" unterstützen und es muss auch eingestellt sein! Im selben Zug kann man auch schauen ob der Editor Tabs durch 4 Leerzeichen ersetzt und dies auch einstellen. Wenn man das Script hier rauskopiert entfällt das, da die Tabs schon ersetzt wurden.)
  • Einstellungen (Benutzername, Passwort und Logfile) eintragen
  • Das Script mit dem Namen "dyndnsAutoLogin" speichern (Wichtig: ohne Dateiendung und wie schon erwähnt mit "Line ending = LF"!)
  • Kopieren des Scripts auf die NAS. Am besten mit der File Station oder über eine Netzfreigabe in einen Ordner seiner Wahl. (Ich habe es bei mir nach /volume1/install/scripts/ kopiert)
  • Aufrufen des Aufgabenplaners in der DSM-Systemsteuerung
  1. Erstellen / Benutzer-definiertes Skript
  2. Allgemeine Einstellungen / Vorgang: dyndnsAutoLogin (Beliebiger Name für den Aufgabenplan)
  3. Allgemeine Einstellungen / Benutzer: root
  4. Befehl ausführen: /volume1/install/scripts/dyndnsAutoLogin (hier den richtigen absoluten Pfad und Namen zu seinem vorher gespeicherten Script)
  5. Unter Zeitplan nun das gewünschte Intervall einstellen (Ich empfehle einmal täglich. Mindestens jedoch mehr als einmal im Monat!)
  6. Fertig!

Um zu prüfen ob das Script ordnungsgemäß funktioniert liest man einfach in seiner Logfile (/var/log/dyndnsAutoLogin.log) nach. Diese sieht so aus:

2013/05/30 00:00:06 - INFO - We have succesfully logged into DynDNS.
2013/05/30 08:00:05 - INFO - We have succesfully logged into DynDNS.
2013/05/30 16:00:04 - INFO - We have succesfully logged into DynDNS.
2013/05/30 17:36:43 - INFO - Login failed

Häufige Fehler

  • Beim Kopieren bzw. Bearbeiten des Scripts wurden Tabs anstelle von Leerzeichen verwendet (1 Tab muss durch 4 Leerzeichen ersetzt werden!)
  • Der Benutzername, das Passwort oder die Logfile wurde ohne doppelte Anführungszeichen ( " " ) in das Script eingetragen
  • Das Logging funktioniert nicht bei gesetztem relativen Pfad (logfile = "./dyndnsAutoLogin.log") wenn man den Aufgabenplaner benutzt.
  • Falsche Python Version installiert. Python < 2.6 wirft folgende Fehlermeldung:
DiskStation> ./dyndnsAutoLogin 
./dyndnsAutoLogin:66: Warning: 'as' will become a reserved keyword in Python 2.6
  File "./dyndnsAutoLogin", line 66
    except IOError as e:
                    ^
SyntaxError: invalid syntax

Wenn Python mittels Paketmanager installiert wurde (>=2.6) und dieser Fehler kommt stimmt möglicherweise der interne symbolische Link auf python2.7 nicht bzw. wurde nicht gesetzt. Dann mal probieren die erste Zeile mit folgender zu ersetzen:

#!/volume1/@appstore/Python/usr/local/bin/python2.7


  • Das Script lässt sich nicht ausführen und die Konsole meldet ein
/bin/sh: ./dyndnsAutoLogin: not found

Hierfür kann es mehrere Ursachen geben:

  1. Das Script wurde von einem nicht vorhandenen Pfad heraus aufgerufen. Einfach mal versuchen den vollständigen Pfad anzugeben:
    DiskStation> /volume1/install/scripts/dyndnsAutoLogin
  2. Die erste Zeile im Script, die sogenannte Shebang-Zeile (oder auch Magic Line) ist nicht richtig.
    #!/volume1/@appstore/Python/usr/local/bin/python
    in diesem Zug prüfen ob python (bzw python2.7) auch im Ordner /volume1/@appstore/Python/usr/local/bin/ vorhanden ist. Den Ordner sich auf der Konsole einfach mal listen lassen:
    DiskStation> ls -la /volume1/@appstore/Python/usr/local/bin/
    Hier sind vorallem folgende Einträge wichtig:
    lrwxrwxrwx 1 root root       9 2013-07-11 15:54 python -> python2.7
    lrwxrwxrwx 1 root root       9 2013-07-11 15:54 python2 -> python2.7
    -rwxr-xr-x 1 root root 2794888 2013-05-31 14:02 python2.7
  3. Der verwendete Editor hat das falsche "Line ending" benutzt. Statt LF (UNIX) wurde CRLF (Windows) verwendet. In diesem Fall sieht ein
    DiskStation> cat /volume1/install/scripts/dyndnsAutoLogin
    dann so aus:
    #!/volume1/@appstore/Python/usr/local/bin/python^M
    ^M
    import urllib^M
    import urllib2^M
    import cookielib^M
    import getopt^M
    import sys^M
    import logging^M
    ^M
    ...
    
    Die fehlerhaften Zeilenumbrüche "^M" müssen dann entweder händisch, mit vi beispielsweise, entfernt werfen oder das Script muss mit den richtigen Line endings erneut kopiert werden!


3x3cut0r 17:00, 30. Mai 2013 (CEST)
Weitere Webseiten