c't 19/2023
S. 140
Praxis
Fritzbox-Bash-Skript
Bild: KI Stable Diffusion | Bearbeitung c’t

Frag Fritzchen!

Fritzbox-Daten per Bash-Script abrufen und verarbeiten

Fritzboxen sammeln intern eine Vielzahl wissenswerter Statusdaten, die sie aber erst nach Authentifizierung rausrücken. Wir zeigen, wie man sie dem Router per Bash-Skript entlockt. Dank Hashing-Technik klappt das sogar, ohne das Passwort im Klartext zu speichern.

Von Mirko Dölle

Die Fritzbox ist in Ihrem HeimnetzDoktor Allwissend: Sie verteilt per DHCP die IP-Adressen und weiß daher genau, welcher Rechner wie erreichbar ist, kennt das WLAN-Passwort, die aktuelle Leitungsauslastung und die Nummer des letzten Anrufers. Diese und viele weitere Informationen lassen sich aus der Fritzbox über die TR-064-Schnittstelle abrufen. Dafür benötigen Sie keine Programmiersprache wie Python oder NodeJS: Mit dem Wissen um die richtigen XML-Werkzeuge und die Protokoll-Details können Sie leicht selbst Informationen aus der Fritzbox in der Bash abrufen und verarbeiten.

Eine Frage, die die Fritzbox bestens beantworten kann, ist die nach der MAC-Adresse eines bestimmten Hosts in Ihrem Heimnetz. Um Strom zu sparen, sollte man Rechner, die man gerade nicht benötigt ausschalten und wieder wecken, sobald man etwa Daten von ihnen herunterkopieren möchte. Dafür bietet sich die komfortable Wake-on-LAN-Technik an, mit der man schlafende und auch heruntergefahrene Geräte per Netzwerkpaket von einem Zweitrechner aufweckt [1]. Auf diese Weckmethode reagieren praktisch alle aktuellen PCs, doch um den richtigen anzuschubsen, benötigen Sie die MAC-Adresse seiner Netzwerkschnittstelle. Diese halten Netzwerkgeräte zwar im ARP-Cache vor, wenn sie miteinander kommuniziert haben, aber nach einer Weile räumen sie auf und die Adresse verschwindet aus dem Cache.

Die Fritzbox hingegen hat ein Elefantengedächtnis und merkt sich MAC-Adressen dauerhaft. Das können Sie mit unserem in [1] vorgestellten Skript ewake anzapfen.

Fritzchen für Fritz

Viele Informationen rückt die Fritzbox nur an angemeldete Benutzer heraus, darunter die Netzwerkdetails. Dazu könnten Sie sich mit dem Passwort des automatisch angelegten Fritz-Benutzers anmelden, doch dieses Benutzerkonto ist quasi allmächtig. Deshalb empfehlen wir, unter „System/FRITZ!Box-Benutzer“ ein neues Konto mit dem Namen fritzchen anzulegen und ihm nur die Berechtigungen zuzuteilen, die Sie für Ihre Skripte tatsächlich benötigen.

Dazu klicken Sie unterhalb der Liste der bereits eingerichteten Benutzerkonten auf „Benutzer hinzufügen“ und geben als Benutzernamen fritzchen sowie ein sicheres Passwort ein.

Damit Shell-Skripte sicher auf die Fritzbox zugreifen, legen Sie ein neues Benutzerkonto an und erteilen ihm nur die notwendigsten Rechte. Ein langes, sicheres Passwort schützt außerdem vor lokalen Angreifern.
Damit Shell-Skripte sicher auf die Fritzbox zugreifen, legen Sie ein neues Benutzerkonto an und erteilen ihm nur die notwendigsten Rechte. Ein langes, sicheres Passwort schützt außerdem vor lokalen Angreifern.

Damit Fritzchen Auskunft zu den Netzwerkeinstellungen erhält, müssen Sie ihm mindestens die Berechtigung „Fritzbox-Einstellungen“ geben, worin automatisch auch „Sprachnachrichten, Faxnachrichten, FritzApp Fon und Anrufliste“ sowie „Smart Home“ enthalten sind. Zugang aus dem Internet sollten Sie Fritzchen jedoch nicht gestatten. Falls das erforderlich ist, richten Sie lieber eine VPN-Verbindung zur Fritzbox ein und nutzen die Skripte darüber.

Hash statt husch-husch

Damit das Passwort von Fritzchen nicht im Klartext im Skript steht, nutzen wir das Konzept der Fritzbox-Authentifizierung und speichern stattdessen einen vorberechneten Hash-Wert. Wie die Authentifizierung im Detail abläuft, beschreibt AVM im Handbuch „TR-064: First Steps“ (ct.de/yju8): Fordert ein Client die Authentifizierung für eine geschützte Information per SOAP an, einem XML-basierten Netzwerkprotokoll, so liefert die Fritzbox einen Realm, der den Authentifizierungszweck angibt, sowie eine bei jedem Aufruf neue Zufallszahl im hexadezimalen Format (Nonce). Um sich also anzumelden, muss der Client den Benutzernamen, Nonce, den Realm und den Hash liefern. Das Passwort wird nicht übertragen und kann folglich nicht von Angreifern mitgelesen werden.

Eine Besonderheit der Fritzbox ist, dass der Hashwert für die Anmeldung zweistufig berechnet wird. So gibt der Pseudocode aus der Dokumentation vor, zunächst den MD5-Hash aus Benutzernamen, Realm und dem Passwort zu berechnen:

secret = MD5(concat(uid,":",realm,":",pwd))

Erst im zweiten Schritt findet dann die Nonce Eingang in den Hash:

response = MD5(concat(secret,":",sn))

Hierbei können Sie ausnutzen, dass der Realm bei der Fritzbox stets F!Box SOAP-Auth lautet, dies ist der Verwendungszweck. Der secret-Hash aus Benutzername, Realm und Passwort ist somit für alle Aufrufe des Benutzers fritzchen gleich. Er muss nur dann neu berechnet werden, wenn Sie den Benutzernamen oder das Passwort ändern oder die Fritzbox in einer künftigen Firmware-Version einen anderen Realm verwenden sollte.

Übersetzungshilfe

Pseudocode wird in technischer Dokumentation häufig verwendet, um Datenformate präzise zu beschreiben. Es ist selten echter, lauffähiger Code einer bestimmten Programmiersprache, sondern beschreibt umgangssprachlich, welche Funktionen anzuwenden sind. Im Beispiel der Fritzbox-Authentifizierung steht MD5() für die Bildung des MD5-Hashwerts in hexadezimaler Darstellung und concat() fügt mehrere Teil-Strings zu einer Zeichenkette zusammen. Die Bash kennt keinen der beiden Funktionsaufrufe, man muss den Pseudocode also erst in Shell-Code übersetzen.

Für die Variable secret werden gemäß Pseudocode zunächst die Variablen uid, realm und pwd verkettet, jeweils per Doppelpunkt getrennt. Ein Funktionsaufruf wie concat() ist in der Bash dafür nicht erforderlich, es genügt, die Bestandteile der Zeichenkette in Anführungszeichen einzuschließen:

"${uid}:${realm}:${pwd}"

Das Berechnen des MD5-Hashes überträgt man dem Befehl md5sum. Er ermittelt den Hash einer Datei oder liest die Daten von der Standardeingabe ein, wenn nichts angegeben wird. Um die Zeichenkette an md5sum weiterzugeben, gibt es in der Bash prinzipiell zwei Möglichkeiten, per Umleitung (Here String) oder über eine Pipe:

secret=$(md5sum <<< \
"${uid}:${realm}:${pwd}")
secret=$(echo \
"${uid}:${realm}:${pwd}" | md5sum)

Das Problem: Beide Methoden hängen ein Newline-Zeichen an, sodass md5sum einen anderen Hashwert errechnet als die Fritzbox. Mit echo -n bleibt das Newline weg. Damit lautet der komplette Bash-Befehl

secret=$(echo -n \
"${uid}:${realm}:${pwd}" | md5sum)

Aufgeräumt

Jedoch liefert md5sum nicht nur den Hashwert, sondern dahinter zusätzlich ein Leerzeichen, den Dateinamen, auf den sich der Hash bezieht, und ein Newline. Kommt die Eingabe aus der Pipe, lautet der Dateiname „-“. Um nur den Hashwert zu erhalten, entfernt man also die letzten drei Zeichen. Das geht beispielsweise, indem man einen Substring ab dem Anfang bis drei Zeichen vor dem Ende bildet:

secret=${secret:0:-3}

Den vollständigen Code des Skripts fbsec, das den Secret Hash ermittelt, finden Sie im gleichnamigen Kasten auf Seite 144 und als Download auf ct.de/yju8. Es benutzt den unverschlüsselten TR-064-Zugang der Fritzbox, der standardmäßig unter http://fritz.box:49000 allen Benutzern im lokalen Netzwerk offen steht. Besonders viel Raum nimmt der curl-Aufruf ein, der die Liste der Hosts per SOAP abfragt (X_AVM-DE_GetHostListPath). Es muss nicht die Host-Liste sein, fbsec muss lediglich auf eine passwortgeschützte Funktion der Fritzbox zugreifen, damit sie den Authentifizierungsvorgang auslöst und dabei unter anderem den Realm preisgibt. Den ermittelt der Befehl xmlstarlet in Zeile 35, das zentrale Tool zur XML-Datenverarbeitung in der Shell.

Das Passwort liest das Skript in Zeile 37 mit der Bash-internen Funktion read ein. Die Parameter -r und -s bewirken, dass der Backslash als reguläres Zeichen behandelt und die Eingabe nicht angezeigt wird. Der Prompt steht hinter dem Parameter -p und das Ergebnis landet in der Variablen FBsec. Da nur eine Variable angegeben ist, fungiert das Leerzeichen nicht als Trennzeichen und es funktionieren auch Passwörter, die eines enthalten.

Der Benutzername und der hexadezimale Hashwert secret sind alles, was Sie brauchen, um künftig geschützte Funktionen der Fritzbox zu verwenden. Das Passwort von fritzchen können Sie gleich wieder vergessen, weil Sie es normalerweise nicht mehr brauchen. Sollte sich der Realm jemals ändern, vergeben Sie für Fritzchen einfach ein neues Passwort.

Entscheidend für die Sicherheit ist ein langes, komplexes Passwort. Da Sie es nur ein einziges Mal in fbsec eingeben müssen, sollte es über 20 Zeichen lang sein und viele Sonderzeichen enthalten. Denn der Hash ist anfällig für einen Angriff etwa mit dem Passwort-Recovery-Tool hashcat: Da der Benutzername im Klartext im Skript steht und der Realm der Fritzbox kein Geheimnis ist, könnte ein lokaler Benutzer anhand des Hashwerts das Passwort knacken. Es ist letztlich nur eine Frage des Rechenaufwands. Deshalb sollten Sie dieses Passwort wie alle anderen nirgendwo sonst benutzen.

Der curl-Aufruf von Zeile 16 bis 33 bedarf einiger Erklärungen. Zunächst einmal die Parameter: -s entspricht --silent und unterdrückt die sonst übliche Ausgabe der Download-Statistik, mit -k genehmigen Sie selbstsignierte Zertifikate bei verschlüsselten Verbindungen und mit -m 5 setzen Sie für die Anfrage einen Timeout von 5 Sekunden.

Das Skript fbsec verwendet für den Datenaustausch HTTP oder HTTPS, die Nachricht steckt in einem Envelope. Die Fritzbox verwendet verschiedene XML-Namespaces (xmlns, Namensräume), um die Daten zu strukturieren. Die Grundform sieht so aus:

<?xml version='1.0' encoding='utf-8'?>
<s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' «
»xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>
<s:Header>
...
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>

Die URLs für Kodierung und Namensraum sind keineswegs Platzhalter, sondern führen zu ebenfalls in XML verfassten Definitionen, die das Datenformat beschreiben. Eine Anfrage an die Fritzbox besteht also stets aus einem Envelope, der falls nötig ein <Header>-Element, in jedem Fall aber ein <Body>-Element enthält.

Der Body ist für alle Anfragen gleich und besteht aus dem Namen und der Namespace-URI der gewünschten Funktion als action:

<s:Body>
<u:${action} xmlns:u='${service}'>
</u:${action}>
</s:Body>

Welche Funktionen es gibt, ist in der Service Control Protocol Definition (SCPD) beschrieben. Davon gibt es in der Fritzbox etliche, die zentrale Anlaufstelle ist die TR-064-Definition, die Sie unter http://fritz.box:49000/tr64desc.xml abrufen können. Sie enthält Verweise auf weiterführende Definitionen. Eine davon ist die der Hosts-Dienste, hier ein Auszug:

<service>
<serviceType>urn:dslforum-org:service:Hosts:1</serviceType>
<serviceId>urn:LanDeviceHosts-com:serviceId:Hosts1</serviceId>
<controlURL>/upnp/control/hosts</controlURL>
<eventSubURL>/upnp/control/hosts</eventSubURL>
<SCPDURL>/hostsSCPD.xml</SCPDURL>
</service>
Welche Funktionen die Fritzbox über TR-064 anbietet, ist in den Service Control Protocol Definitionen (SCDP) beschrieben. Die erste Anlaufstelle liegt bei http://fritz.box:49000/tr64desc.xml, dort sind die SCDPs verlinkt.
Welche Funktionen die Fritzbox über TR-064 anbietet, ist in den Service Control Protocol Definitionen (SCDP) beschrieben. Die erste Anlaufstelle liegt bei http://fritz.box:49000/tr64desc.xml, dort sind die SCDPs verlinkt.

Die Definition der Hosts-Dienste finden Sie unter der SCPDURL verlinkt. Dort ist die Funktion X_AVM-DE_GetHostListPath beschrieben, mit der Sie Daten über die Geräte im Netzwerk abrufen können, darunter die MAC-Adresse. Diese Funktion dürfen nur authentifizierte Benutzer verwenden, was fbsec ausnutzt, um den Realm zu ermitteln:

<action>
<name>X_AVM-DE_GetHostListPath</name>
...
</action>

Mit den Angaben aus den Definitionen tr64dec.xml und hostsSCPD.xml können Sie die für die SOAP-Anfrage erforderlichen Daten von <serviceType>, <controlURL> und <action> ermitteln:

service='urn:dslforum-org:service:Hosts:1'
control="/upnp/control/hosts"
action='X_AVM-DE_GetHostListPath'

Außerdem müssen Sie curl veranlassen, im HTTP-Header ebenfalls den Service und die gewünschte Funktion anzugeben. Dies geschieht mit folgendem Parameter:

-H "SoapAction:${service}#${action}"

Für die Authentifizierung verlangt die Fritzbox eine <InitChallenge> mit dem Benutzernamen im Header der Anfrage:

<s:Header>
<h:InitChallenge xmlns:h='http://soap-authentication.org/digest/2001/10/»s:mustUnderstand='1'>
<UserID>${usr}</UserID>
</h:InitChallenge>
</s:Header>

Auffällig ist auch hier der gesondert ausgewiesene Namespace: <UserID> befindet sich innerhalb von <InitChallenge> im Namespace h. Die verschiedenen Namensräume spielen auch bei der folgenden Auswertung der Antwort eine große Rolle.

In den Zeilen 19 bis 33 des Listings von fbsec finden Sie die vollständige SOAP-Anfrage mit dem Envelope, Header und Body. Die Fritzbox antwortet ebenfalls per XML, hier ein Auszug:

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" «
»s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Header>
<h:Challenge xmlns:h="http://soap-authentication.org/digest/2001/10/"«
» s:mustUnderstand="1">
<Status>Unauthenticated</Status>
<Nonce>DDDD3D22513464BC</Nonce>
<Realm>F!Box SOAP-Auth</Realm>
</h:Challenge>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>

Die Antwort enthält zwei Namespace-Definitionen: s bei <Envelope>, dessen Definition auf xmlsoap.org liegt, und h bei <Challenge> mit der Definition von soap-authentication.org. Wo welcher Namespace gilt, legen die Prefixe s: respektive h: vor den Tags fest: s bei <s:Envelope> und <s:Header>, h nur bei <h:Challenge>.

Für die Berechnung der Variablen secret benötigt fbsec den Realm. Zum Verarbeiten von XML-Daten in Shell-Skripten ist xmlstarlet erste Wahl, weil es bei Angabe des XML-Pfads einzelne Elemente aus einer XML-Struktur herausprokelt. Das folgende Beispiel liefert alle Werte (-v) unterhalb des Elements <Header> im Namespace s:

xmlstarlet sel -t \
-v "/s:Envelope/s:Header" <<<${r}

Auch xmlstarlet berücksichtigt Namespaces. Standardmäßig arbeitet es aber nur im ersten ausgewiesenen Namespace, im Beispiel des Envelope ist das s. Damit können Sie standardmäßig nur auf die Elemente <Envelope>, <Header> und <Body> zugreifen. Um an <Challenge> und die darunter liegenden Elemente <Status>, <Nonce> und <Realm> heranzukommen, müssen Sie zuvor über den Parameter -N den Namespace h definieren. Das erfordert folgende zusätzliche Parameter:

-N h="http://soap-authentication.org/digest/2001/10/"

Es gibt jedoch einen Trick: Da <Status>, <Nonce> und <Realm> kein expliziter Namespace zugewiesen wurde, können Sie die Elemente mittels Platzhaltern referenzieren, ohne den Namespace definieren zu müssen. So liefert

xmlstarlet sel -t -v //Realm <<<${r}

den Wert aller Elemente, die Realm heißen, unabhängig davon, wie ihr exakter XML-Pfad lautet. Weil in der Antwort der Fritzbox <Realm> nur einmal vorkommt, fällt automatisch der richtige Wert heraus.

Abgefragt

Für öffentlich abrufbare Daten genügt ein einzelner curl-Aufruf. Auch der Envelope schrumpft deutlich. Als Beispiel für eine solche Datenabfrage dient hier die Funktion GetSecurityPort, mit der die Fritzbox verrät, auf welchem Port Sie die XML-Daten verschlüsselt überträgt:

FBcontrol="/upnp/control/deviceinfo"
FBservice='urn:dslforum-org:service:DeviceInfo:1'
FBaction='GetSecurityPort'
r=(curl -s -k -m 5 \
"http://fritz.box:49000${FBcontrol}" \
-H 'Content-Type: text/xml; charset="utf-8"' \
-H "SoapAction:${FBservice}#${FBaction}" \
-d "<?xml version='1.0' encoding='utf-8'?>\
<s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>\
<s:Body>\
<u:${FBaction} xmlns:u='${FBservice}'></u:${FBaction}>\
</s:Body>\
</s:Envelope>")

Die gesuchte Information steckt in der Antwort gemäß http://fritz.box:49000/deviceinfoSCPD.xml im Tag <NewSecurityPort>, hier ein Auszug:

<?xml version="1.0"?>
<s:Envelope ...>
<s:Body>
<u:GetSecurityPortResponse ...>
<NewSecurityPort>49443</NewSecurityPort>
</u:GetSecurityPortResponse>
</s:Body>
</s:Envelope>

Um die Portnummer 49443 auszulesen und in der Variablen ${FBport} zu speichern, bemühen Sie abermals xmlstarlet:

FBport=$(xmlstarlet sel -t \
-v //NewSecurityPort <<<${r})

Indem Sie anschließend die URL https://fritz.box:49443 für Ihre Anfragen verwenden, können Sie verhindern, dass jemand in Ihrem Netzwerk die Kommunikation belauscht und so Daten mitliest, die eine Authentifizierung erfordern. Diese sind schließlich nicht für jedermanns Augen bestimmt – so wie die bereits in fbsec verwendete Funktion X_AVM-DE_GetHostListPath, die verschiedene Daten der Netzwerkgeräte liefert.

Auch hier ist für die Authentifizierung zunächst eine <InitChallenge> fällig. Der XML-Envelope ist der gleiche wie bei GetSecurityPort, nur dass es diesmal einen <Header> gibt und in den Feldern Funktionsname, Service-Typ und Control-URL andere Werte stehen. Deshalb ist es sinnvoll, den XML-Envelope ein für alle Mal als Variable ${FBenv} zu definieren und anschließend nur noch die für jede Anfrage spezifischen Angaben zu ändern:

FBenv="<?xml version='1.0' encoding='utf-8'?>\
<s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>\
\${FBeheader}\
<s:Body>\
<u:\${FBaction} xmlns:u='\${FBservice}'></u:\${FBaction}>\
</s:Body>\
</s:Envelope>"

Wenn Sie das gleiche für den Content Type und die SOAP-Anfrage tun, macht das den Abruf des verschlüsselten Ports sehr viel übersichtlicher:

FBct='Content-Type: text/xml; charset="utf-8"'
FBsoap="SoapAction:\${FBservice}#\${FBaction}"
FBcontrol="/upnp/control/deviceinfo"
FBservice='urn:dslforum-org:service:DeviceInfo:1'
FBaction='GetSecurityPort'
r=$(curl -s -k -m 5 \
"${FBhost}${FBcontrol}" -H "${FBct}" \
-H "${FBsoap@P}" -d "${FBenv@P}")

Der Clou steckt in der Parametertransformation ${parameter@operator} der Bash: Während ${FBsoap} lediglich die Zeichenkette ausgibt, den die Variable bei der Zuweisung gerade besaß, wendet ${FBsoap@P} unter anderem die Variable Expansion auf den String an. Sie befüllt die Variablen ${FBservice} und ${FBaction} aus ${FBsoap} mit ihren aktuellen Werten. Es genügt daher, ${FBenv} und ${FBsoap} am Anfang der Datei einmalig mit Variablen an den veränderlichen Stellen zu definieren und diese im Nachgang mittels ${FBenv@P} respektive ${FBsoap@P} zu ersetzen.

Von nun an ist es ein Leichtes, die <InitChallenge> für die Funktion X_AVM-DE_GetHostListPath zu formulieren:

FBcontrol="/upnp/control/hosts"
FBservice='urn:dslforum-org:service:Hosts:1'
FBaction='X_AVM-DE_GetHostListPath'
FBeheader="\
<s:Header>\
<h:InitChallenge xmlns:h='http://soap-authentication.org/digest/2001/10/' s:mustUnderstand='1'>\
<UserID>${FBuser}</UserID>\
</h:InitChallenge>\
</s:Header>"
r=$(curl -s -k -m 5 \
"${FBhost}${FBcontrol}" -H "${FBct}" \
-H "${FBsoap@P}" -d "${FBenv@P}")

Da in der Definition von $FBenv die Variable ${FBeheader} als Platzhalter für einen Header steckt, muss man den Envelope nicht neu definieren. Aus der Antwort der Fritzbox gewinnen Sie die Nonce sowie den Realm, berechnen unter Zuhilfenahme der Secret FBsec den Authentifizierungs-Hash und können dann die gewünschte Liste anfordern:

FBnonce=$(xmlstarlet sel -t \
-v //Nonce <<<${r})
FBrealm=$(xmlstarlet sel -t \
-v //Realm <<<${r})
FBauth=$(echo -n \
"${FBsec}:${FBnonce}" | md5sum)
FBeheader="\
<s:Header>\
<h:ClientAuth xmlns:h='http://soap-authentication.org/digest/2001/10/' s:mustUnderstand='1'>\
<Nonce>${FBnonce}</Nonce>\
<Auth>${FBauth:0:-3}</Auth>\
<UserID>${FBuser}</UserID>\
<Realm>${FBrealm}</Realm>\
</h:ClientAuth>\
</s:Header>"
r=$(curl -s -k -m 5 \
"${FBhost}${FBcontrol}" -H "${FBct}" \
-H "${FBsoap@P}" -d "${FBenv@P}")

Ob die Authentifizierung geklappt hat, verrät der Befehl

xmlstarlet sel -t -v //Status <<<${r}

mit der Antwort Authenticated. Daneben gibt es eine neue <Nonce>, die Sie bei Bedarf für eine weitere Abfrage nutzen können.

Bei umfangreicheren Antworten wie der Netzwerkliste liefert die Fritzbox einen Pfad zurück, über den Sie das Ergebnis abrufen können. Hier ein Auszug einer solchen Antwort:

<s:Envelope ...>
...
<s:Body>
<u:X_AVM-DE_GetHostListPathResponse ...>
<NewX_AVM-DE_HostListPath>/devicehostlist.lua?sid=f9f18ee78924684b</NewX_AVM-DE_HostListPath>
</u:X_AVM-DE_GetHostListPathResponse>
</s:Body>
</s:Envelope>

Wiederum mit xmlstarlet lösen Sie den Pfad heraus und laden anschließend die Antwort mittels curl herunter:

FBlua=$(xmlstarlet sel -t \
-v //NewX_AVM-DE_HostListPath <<<${r})
r=$(curl -s -k -m 5 "${FBhost}${FBlua}")

Eine Authentifizierung ist in diesem Fall nicht erforderlich, da der Abruf nur mit der korrekten Session-ID sid möglich ist. Ein weiterer Aufruf von xmlstarlet ermittelt aus der heruntergeladenen Liste zum Beispiel die MAC-Adresse eines Hosts:

xmlstarlet sel -t -m \
"List/Item[HostName='${FBsearch}']" \
-v MACAddress <<<${r}

Neu ist die Vorauswahl mit dem Parameter -m: Das Programm wählt alle <Item> mit dem XML-Pfad List/Item aus, die ein Element <Hostname> mit dem Wert aus ${FBsearch} enthalten. Aus dieser Vorauswahl liefert xmlstarlet den Wert des Elements <MACAddress> und damit die MAC-Adresse des gesuchten Hosts.

Fix und fertig

Das komplette Skript fbgetmacaddr haben wir auf ct.de/yju8 zum Download bereit gestellt, Sie müssen darin nur noch den Secret Hash eintragen. Es eignet sich gut, um für das Skript ewake aus [1] die MAC-Adresse des zu weckenden Rechners bei der Fritzbox zu erfragen. So können Sie auch Rechner starten, deren MAC-Adresse nicht mehr im ARP-Cache liegt: Fritzchen liefert auch nach Monaten noch die korrekte Antwort. Und mit den in diesem Artikel gezeigten Techniken können Sie die TR-064-Schnittstelle der Fritzbox leicht für weitere Zwecke nutzen. (mid@ct.de)

Fritzbox-Skripte zum Download: ct.de/yju8

Kommentare lesen (6 Beiträge)