Get-FritzMACTable

Bei meinen IoT-Experimenten war es mir auf Dauer zu nervig, die Fritz!Box immer auf MAC-Adressen per Browser zu durchsuchen. Das hier vorgestellte PowerShell-Script nutzt die TR064-Schnittstelle, um eine Liste der MAC-Adressen zu ermitteln. Vielleicht wird irgendwann ja auch mal eine Tray-App draus.

Die Seite findet sich aber unter dem Bereich "PRTG - Monitoring für den KMU", weil über einen Schalter damit auch die Aktiven/Passiven Hosts oder sogar jede MAC-Adresse als Kanal in PRTG abgebildet werden kann.

Quellen-Studium

Leider unterstützt die Fritz!Box kein SNMP. Aber per TR-064 kommt man auch recht weit, zumal AVM die Schnittstellen auf https://avm.de/service/schnittstellen/ sehr ausführlich dokumentiert.

Einige andere Vorarbeiten zu meiner Fritz!Box habe ich ja schon veröffentlicht:

Damit war eigentlich klar, dass ich eigentlich nur den Service "urn:LanDeviceHosts-com:serviceId:Hosts1" unter der URL "/upnp/control/hosts" abfragen muss

Interessant sind hier die URLs und die weitere Definition der "Service Controlled Protocol Descriptions" (SCPD)

API-Beschreibung

Aus der ersten XML ergibt sich eine Url für die Servicebeschreibung. Sie übernehmen einfach den Wert aus "SCPDUTL" und hängen ihn an den Hostnamen und TR-064-Port an

http://fritz.box:49000/hostsSCPD.xml

Wenn Sie die Daten nicht per Brower parsen wollen, dann hilft ihnen die PowerShell auch hier:

$hostsSCPD = Invoke-WebRequest http://fritz.box:49000/hostsSCPD.xml
([xml]$hostsSCPD.Content).scpd.actionList.action

name argumentList
---- ------------
GetHostNumberOfEntries argumentList
GetSpecificHostEntry argumentList
GetGenericHostEntry argumentList
X_AVM-DE_GetChangeCounter argumentList
X_AVM-DE_SetHostNameByMACAddress argumentList
X_AVM-DE_GetAutoWakeOnLANByMACAddress argumentList
X_AVM-DE_SetAutoWakeOnLANByMACAddress argumentList
X_AVM-DE_WakeOnLANByMACAddress argumentList
X_AVM-DE_GetSpecificHostEntryByIP argumentList
X_AVM-DE_HostsCheckUpdate
X_AVM-DE_HostDoUpdate argumentList
X_AVM-DE_GetHostListPath argumentList
X_AVM-DE_GetMeshListPath argumentList

Jetzt kennen Sie alle "Funktionsaufrufe", die diese Schnittstelle anbietet. Sie sind hier auch beschrieben:

TR-064 Support – Hosts
https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/hostsSCPD.pdf

Der Anfang ist dabei die Funktion "X_AVM-DE_GetHostListPath" zu dem die Dokumentation schreibt:

Gets a path to a lua script file, which generates an XML structured list of hosts. A generated xml example is shown in 4.1 Host List Contents
Required rights : PhoneRight, AppRight

Ich muss also den Service "urn:dslforum-org:service:Hosts:1" anfordern und die Funktion "X_AVM-DE_GetHostListPath" aufrufen. Allerdings sind diese Abfragen nicht mehr "anonym" möglich. Ich muss also das Kennwort der Fritz!Box zusammen mit dem Benutzernamen "admin" übermitteln.

Wireshark

Es war dann nicht sonderlich schwer, daraus ein PowerShell-Script zu bauen ,welches die Daten bezieht. Allerdings gibt es schon zwei Besonderheiten zu beachten, die mit Wireshark bei Nutzung einer unverschlüsselten Verbindung über Port 49000 einfach zu sehen sind:

  • Authentifizierung
    Man kann nicht schon mit dem ersten Request die Benutzername/Kennwort-Information mit senden. Der erste Request erfolgt anonym und die Fritz!Box bietet dann Digest an
  • Zweiter Request liefert nur Download-URL
    Nach einer gültigen Anmeldung per "Digest" liefert die Box eine URL zum Download der eigentlichen Information
  • Anonymer Download
    Die gewünschte Information selbst gibt es dann wieder anonym. Die "sid" ist eine Sitzungskennung, die nur kurz gültig ist. Das ist dann eine XML-Struktur

Ergebnis

Die XML-Datei lässt sich natürlich recht einfach ausgeben. Das Skript gibt dazu direkt die Liste mit folgender Zeile an die Pipeline aus

$devicehostlist.List.Item.GetEnumerator()

Ohne weitere Formatierung bekommt Sie die Daten als Liste. Jeder Datensatz hat dabei folgende Felder:

Index                     : 55
IPAddress                 : 192.168.178.2
MACAddress                : 70:4F:57:23:1A:19
Active                    : 1
HostName                  : TPLink-T2600-28
InterfaceType             : Ethernet
X_AVM-DE_Port             : 3
X_AVM-DE_Speed            : 1000
X_AVM-DE_UpdateAvailable  : 0
X_AVM-DE_UpdateSuccessful : unknown
X_AVM-DE_InfoURL          :
X_AVM-DE_Model            :
X_AVM-DE_URL              : http://192.168.178.2
X_AVM-DE_Guest            : 0
X_AVM-DE_WANAccess        : granted
X_AVM-DE_Disallow         : 0

Leider ist nicht zu sehen, wann ein Gerät das letzte mal aktiv war oder wie alt der Eintrag in der MAC-Tabelle ist. Allerdings gibt es ein Feld "Active", welche bei inaktiven Geräten auf "0" steht. Anscheinend löscht die Fritz!Box aber keine einmal gelernte Geräte.

Sie können die Liste damit einfach auf die Console als Liste oder als Tabelle ausgeben lassen

.\get-fritzmactable.ps1 | ft MACAddress,IPAddress,Active,HostName,X_AVM-DE_Port

Dann sehen Sie sehr schnell alle Geräte.

Die aktiven Geräte können Sie auch schnell filtern.

.\get-fritzmactable.ps1 | ?{$_.active -eq 1}| ft MACAddress,IPAddress,Active,HostName,X_AVM-DE_Port

Die Ports 1-4 entsprechen den Ethernet-Ports. Geräte, die per WLAN (2,4 oder 5 GHz) angebunden sind, erscheinen aber als Port 0. Eine Unterscheidung nach der Frequenz gibt es nicht. Wie sich die Geräte hinter einem Mesh-Netzwerk ausgeben, kann ich mangels Repeater nicht testen.

Das Skript

Sie können das folgende PowerShell-Skript einfach in ein Verzeichnis herunterladen und aufrufen. Denken Sie daran, dass Sie als Parameter mindestens das Kennwort für ihre Fritz!Box angeben müssen. Getestet habe ich das mit meiner FB7950 und Firmware 7.x aber die verwendete API ist schon viel älter und sollte daher auch mit früheren Versionen nutzbar sein.

get-fritzmactable.20201122.ps1

Das Skript nutzt die PowerShell-Commandlets "Invoke-RestMethod" und da die Fritzbox kein öffentlich vertrauenswürdiges Zertifikat hat, muss ich den Parameter "SkipCertificateCheck" addieren, der aber erst ab PowerShell 7.0 verfügbar ist. Leider gibt es in PRTG aktuell keine Option eine bestimmte Shell aufzurufen. Ich nutze daher immer eine CMD-Datei, die dann die gewünschte Powershell mit dem Skript als Parameter startet.

REM Startet das PS1-Skript mit der richtigen Powershell und Parametern

"C:\Program Files\PowerShell\7\pwsh.exe" ^
   -nologo ^
   -NonInteractive ^
   -command "& ""C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\get-fritzmactable.ps1"" -FBKennwort:""geheimeskennwort"" -prtg"

Alternativ können Sie den Abruf von HTTPS über Port 49443 auf http und Port 49000 umstellen und den Parameter SkipCertificateCheck entfernen.

PRTG

Natürlich gibt es in dem Code auch zwei Schalter, die eine PRTG-kompatible Ausgabe liefern:

  • -prtg
    Liefert eine kleine XML mit der Anzahl der aktiven und passiven Hosts
  • -prtgdetail
    Liefert neben der Anzahl auch jede MAC-Adresse als eigener Kanal mit dem individuellen Status. Beachten Sie, das PRTG maximal 50 Kanäle offiziell unterstützt. Durch IoT-Geräte und Gäste kann dies sehr schnell erreicht sein.

Das Skript funktioniert auf jeder PRTG-Probe und liefert die Ergebnisse per STDOUT an die aufrufende Instanz aus. Denken Sie an die Angabe des Parameters und des Kennworts in der Konfiguration.

Weiterentwicklung

Aktuell habe ich keine Weiterentwicklung geplant. Interessant könnte es aber schon sein, eine Tray-App zu nutzen, die regelmäßig den Status abfrage und Sie über neue Geräte informiert. Die gleiche Schnittstelle kann übrigens auch genutzt werden, um z.B. die Präsenz eines Geräts zu überwachen. Dazu wäre es natürlich besser, eine "Push-Funktion" zu haben anstatt die Daten immer wieder abzurufen.

Weitere Links