DdnsAutoLogin: Unterschied zwischen den Versionen

Aus
(Erste Version dieses Artikels)
 
Zeile 177: Zeile 177:
#Allgemeine Einstellungen / Benutzer: root
#Allgemeine Einstellungen / Benutzer: root
#Befehl ausführen: /volume1/install/scripts/dyndnsAutoLogin (hier den richtigen absoluten Pfad und Namen zu seinem vorher gespeicherten Script)
#Befehl ausführen: /volume1/install/scripts/dyndnsAutoLogin (hier den richtigen absoluten Pfad und Namen zu seinem vorher gespeicherten Script)
#Unter Zeitplan nun das gewünschte Intervall einstellen (Ich empfehle einmal Täglich. Mindestens jedoch mehr als einmal im Monat!)
#Unter Zeitplan nun das gewünschte Intervall einstellen (Ich empfehle einmal täglich. Mindestens jedoch mehr als einmal im Monat!)
#Fertig!
#Fertig!



Version vom 30. Mai 2013, 23:00 Uhr

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.

Voraussetzungen

  • DSM >= 3.2
  • Python >= 2.6

Python kann problemlos über das DSM-Paketzentrum gedownloadet und installiert 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:])

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.
  • Einstellungen (Benutzername, Passwort und Logfile) eintragen
  • Das Script mit dem Namen "dyndnsAutoLogin" speichern (Wichtig: ohne Dateiendung)
  • 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
3x3cut0r 17:00, 30. Mai 2013 (CEST)