[Gelöst] Freetz: Hilfe bei Shell-Script zur Extrahierung des aktuellen IPv6-Präfix

NanoBot

Mitglied
Mitglied seit
27 Jun 2005
Beiträge
412
Punkte für Reaktionen
19
Punkte
18
Hallo Leute,

ich nutze eine FB7490 mit Freetz. Dort möchte ich, mit Hilfe von "onlinechanged", die aktuellen IPv6-Adressen mehrerer Geräte in meinem Lan bei jedem Reconnect in "einem Rutsch" an FreeDNS melden.

Die Geräte haben einen fest eingestellten Suffix, so daß ich "nur" noch den aktuellen Präfix davor setzen muß, ehe die Updates an FreeDNS rausgehen können. Eine Datenquelle für den aktuellen Präfix war leicht zu finden:
Code:
root@fritz:/var/mod/root# showdsldstat | grep prefix
0: IPv6: prefix 2001:16b8:4051:1600::/56 valid 225172 prefered 138772

Jetzt benötige ich etwas Hilfe, um aus dieser Zeile den Präfix an sich zu extrahieren. Bei diesem Beispiel möchte ich also einer Shell-Variablen den Wert "2001:16b8:4051:1600:" zuweisen, um dann den Suffix hinzuzufügen zu können. Zu beachten ist hierbei, daß die Länge des Prefixes variabel sein kann, da führende Nullen ja nicht angezeigt werden. Es müßten also vermutlich die Leerzeichen und die Doppelpunkte als "Trenner" verwendet werden.

Mir ist bekannt, daß man dies unter Verwendung der IFS-Funktion und des set Kommandos ereichen kann, aber bin nicht so der Spezi für Shell-Scripte. Daher die Frage, ob mir jemand einen Vorschlag für ein solches Script machen könnte.

C.U. NanoBot
 
Moins


Sowas vielleicht....
Code:
$ AAAA_PRE=$(echo -ne '0: IPv6: prefix abcd:ef01:2345:6789:ffff:ffff' | grep -oE "([0-9a-f]{0,4}:){4}")
$ echo "${AAAA_PRE}"
abcd:ef01:2345:6789:
....?
 
Zuletzt bearbeitet:
  • Like
Reaktionen: NanoBot
Nimm "sed" mit "normalem regex" oder "expr" ... dann ist das sogar POSIX-kompatibel und funktioniert mit jeder Shell ("-E" ist optional für "grep" - hier aber auch nicht wirklich nötig):
Code:
prefix="$(showdsldstat | sed -n -e "s|^0: IPv6: prefix \([0-9a-fA-F:/]*\).*|\1|p")"
und wenn man das noch in Adresse und Maske teilen will, nimmt man einfach etwas in dieser Richtung:
Code:
printf "addr=%s\n" "${prefix%/*}"
printf "mask=%s\n" "${prefix#*/}"
, wobei man das "Auslesen" sogar noch weiter vereinfachen könnte, wenn man einfach "alles" im vierten "Wort" nimmt (AVM gibt außerdem A bis F immer in kleinen Buchstaben aus, die Range mit den Großbuichstaben könnte man also auch noch einzeln aus der ersten Zeile entfernen):
Code:
prefix="$(showdsldstat | sed -n -e "s|^0:.* prefix \([^ ]*\).*|\1|p")"
und unterstellt, daß sich das Format nicht ändert.

Auf den Beginn (mit dem "0:") sollte man nicht verzichten - das ist die Interface-Nummer und wenn man mehr als ein (logisches) Interface Richtung WAN hat (z.B. bei bestimmten VoIP-Konfigurationen), gibt es - wenn's schlecht läuft - zwei Zeilen in der Antwort. Daher sollte man (egal ob mit "grep" oder "sed" oder womit auch immer) den Beginn der Zeile sauber prüfen und nicht zwingend vom momentanen Inhalt der Ausgabe von "showdsldstat" ausgehen ... wer ganz sicher gehen will, ermittelt erst noch, welche Nummer das "internet"-Interface wirklich hat (der "name"-Eintrag ist ja auch in der Ausgabe enthalten).
 
  • Like
Reaktionen: NanoBot
Hallo,

beim Extrahieren sollte man sich besser nicht auf Anzahl der Doppelpunkte verlassen, denn rein rechnerisch müßte durchschnittlich bei jedem 256. Präfix die vierte Komponente 0 sein und somit in der Notation entfallen, z.B. "2001:16b8:4051::/56". Sehr unwahrscheinlich, aber theoretisch möglich wäre auch "2001:16b8::/56".

Aber der Schrägstrich steht ja wohl immer parat.

Grüße
 
  • Like
Reaktionen: NanoBot
Hi Leute,

Erstmal danke für die schnellen Antworten. Ich habe zunächst mal den ersten Vorschlag aufgegriffen und komme damit offenbar zum Ziel:
Code:
root@fritz:/var/mod/root# showdsldstat | grep prefix | grep -oE "([0-9a-f]{0,4}:){4}"
2001:16b8:4051:1600:
root@fritz:/var/mod/root#
Allerdings gäbe es theoretisch das von Zentronix angesprochene Problem, daß ein oder mehrere der Gruppen eine 0 sein könnten und somit dann zum Beispiel folgendes rauskommt:
Code:
root@fritz:/var/mod/root# echo 1111:2222:3333:: | grep -oE "([0-9a-f]{0,4}:){4}"
1111:2222:3333::
root@fritz:/var/mod/root#

Ein kurzer Test im Browser ergab aber erfreulicherweise, daß FreeDNS die verkürzte IPv6-Notation in der Update-URL akzeptiert und korrekt interpretiert.

Somit brauche ich jetzt nur aus der generellen Update-URL, den Security-Tokens, dem aktuellen Prefix und den Suffixen der einzelnen Geräte die korrekten Update-URLs für die einzelnen Geräte zusammen zu bauen. Damit komme ich aber ( hoffentlich ) dann alleine zurecht, da ich das vergleichbare Script schon für Windows habe und dann an Linux anpassen kann.

C.U NanoBot
 
Zuletzt bearbeitet:
Oder mit ctlmgr_ctl den Präfix auslesen:

PREFIX=$(ctlmgr_ctl r ipv6 settings/prefix)
 
Danke für den Tip, denn diese Methode ist insoweit einfacher, als daß ich nur ein grep benötige:

Code:
root@fritz:/var/mod/root# ctlmgr_ctl r ipv6 settings/prefix | grep -oE "([0-9a-f]{0,4}:){4}"
2001:16b8:407e:800:
root@fritz:/var/mod/root#

Denn ich benötige ja den Prefix ohne die Netzmaske.
 
Und warum nicht einfach mit

PREFIX=$(ctlmgr_ctl r ipv6 settings/prefix)
echo ${PREFIX%:/56}
 
Das funktioniert natürlich auch, setzt aber vorraus, daß man immer ein /56 Netz bekommt. Bei meinem Provider ist es immer bisher immer ein /56 Netz, aber es wäre ja denkbar, daß andere Provider andere Subnetze vergeben. Daher scheint mir die Version mit dem grep Befehl universeller zu sein.
 
Es geht ja auch problemlos mit einem Stern anstelle der 56 (s. #3) und in einer (konformen) IPv6-Adresse gibt es nur einen Schrägstrich. Fehlt der komplett, wird auch nichts abgeschnitten.

Das eine ist halt ein zusätzlicher Programmaufruf (auch wenn das "grep" in der Pipe läuft) und das andere mehr oder weniger eine ganz normale Variablenzuweisung - letztere ist um einiges schneller.

Selbst wenn das hier keine Rolle spielt, sollte man sich gleich einen passenden "Stil" angewöhnen - denn irgendwann steht das auch mal in der Schleife mit 1E6 Durchläufen und da macht sich das dann schon bemerkbar.

Außerdem liest sich (zumindest wenn man "Shell kann") so eine Zuweisung immer noch besser als ein "grep" - das ist "Globbing" vs. "regex" und es gibt genug Leute, die einen regulären Ausdruck nicht in allen Einzelheiten verstehen, geschweige denn selbst einen schreiben oder einen "angelesenen" ändern können.
 
Danke für den Hinweis mit dem Stern als Joker zum entfernen der Subnetzmaske. Somit dürfte diese Methode also am wenigsten Resourcen fressen und gleichzeitig, unabhängig von der Größe des zugewiesenen Netzes universell sein:

Code:
root@fritz:/var/mod/root# PREFIX=$(ctlmgr_ctl r ipv6 settings/prefix)
root@fritz:/var/mod/root# echo ${PREFIX%:/*}
2001:16b8:40ab:fc00:
root@fritz:/var/mod/root#

Und ja, ich gebe dir Recht dahingehend, daß diese Möglichkeit für Leute wie mich, welche mit RegEx nicht so gut klarkommen, am einfachsten nachvollziehbar ist.

Ich baue das jetzt mal in ein Script ein, und falls jemand Interesse daran haben sollte, nach dem Testen hier posten. Denn nach und nach wird ja IPv6 immer wichtiger, und wenn die Fritz!Box die IPv6-Adressen aller Geräte im Netz, welche von extern zugänglich sein sollen, auf einmal aktualisiert, ist dies aus meiner Sicht ja die beste Möglichkeit.

C.U NanoBot
 
So, das Updatescript ist seit gestern fertig und funktioniert bisher problemlos. Ich möchte mich noch einmal für alle Anregungen hier im Thread bedanken.

Somit bleibt jetzt nur noch die Frage:
Hat jemand Interesse an einem Shellscript auf der FB7490 mit Freetz ( es ist der Patch https://freetz.github.io/wiki/patches/replace_onlinechanged.html erforderlich ), welches es ermöglicht, mehrere Einträge für IPv4 und/oder IPv6 beim Anbieter https://freedns.afraid.org/ bei jedem Reconnect in einem Rutsch zu aktualisieren ?

Wenn ja, dann müßte ich das Script erst anonymisieren, was etwas Arbeit macht. Und der "Aufwand" lohnt ja nur, wenn überhaupt jemand Interesse daran hätte.

C.U. NanoBot
 
Super Arbeit

Ich hätte da Intresse dran

Danke
 
Da ich offenbar nicht der einzige bin, der IPv4 und IPv6 durch seine gefreezte Box updaten lassen möchte, hier das Script in anonymisierter Form. Vorab dazu die folgende Infos:

Bei dem von mir genutzten Anbieter freedns.afraid.org müssen die Einträge für IPv4 ( Typ A ) und IPv6 ( Typ AAAA ) seperat angelegt und seperat geupdatet werden. Dabei ist es sowohl möglich für die gleiche Subdomain sowohl einen Typ A als auch einen Typ AAAA Record anzulegen. Es ist aber auch möglich, für eine Subdomain entweder nur einen Typ A oder nur einen Typ AAAA Record anzulegen. Die Begrenzung für FreeUser besteht allerdings darin, daß maximal 5 Records pro Account angelegt werden können.

Ansonsten noch der Hinweis: FreeDNS bietet eine sehr große Anzahl von Subdomains, aus denen wählen kann. Allerdings "gehören" dem Betreiber dieses Dienstes nur sehr wenige dieser Domains, die meisten sind im nur zur Verwaltung anvertraut worden. Ich empfehle daher bevorzugt eine Subdomain unter "mooo.com", "strangled.net" etc., also einer Domain, welche dem Betreiber selbst gehört, zu wählen.

Zur Aktualisierung der jeweiligen IP-Adressen bietet freedns.afraid.org verschiedene Möglichkeiten, durch Aufruf einer bestimmten URL ein Update der IP-Adresse mitzuteilen. Das von mir mit Hilfe der User hier im Board entworfene Script nutzt die Methode "Randomized Update Token", da hierbei kein Login und kein Passwort erforderlich ist, was die Sache natürlich vereinfacht. Wie die URL mit diesem Token jeweils aussehen muß ( jeder Eintrag hat ein eigenes Token ), kann man, sobald bei bei FreeDNS eingeloggt ist, auf dieser Seite sehen:
https://freedns.afraid.org/dynamic/v2/

Wichtig ist hierbei, daß irgendeine eine Änderung an einem der Records, wie z.B. von Typ A auf Typ AAAA, oder das Löschen und Neuanlegen einer Subdomain ( sprich umbennen ), zu einem neuen Token führt. Also wenn irgendwas nicht klappt, dann schadet es nie zu prüfen, ob sich das Token zwischenzeitlich durch irgendeine Änderungen mitverändert hat.

Die generelle Update-URL für IPv4-Adressen ( also Typ A Records ) sieht so aus:
http://sync.afraid.org/u/RandomizedUpdateToken/
während die Update-URL für IPv6-Adressen ( also Typ AAAA ) so aussieht:
http://v6.sync.afraid.org/u/RandomizedUpdateToken/

Ruft man einfach nur diese URL auf, so ermittelt FreeDNS die IP-Adresse aus dem eingehenden Datenpaket. Ruft man also eine solche URL von der Fritz!Box aus auf, dann übermittelt man die IPv4 bzw. IPv6-Adresse der Box an sich. Ruft man die URL von einem der angeschlossenen Endgeräte aus auf, so funktioniert dies bei IPv4 dank NAT problemlos. Bei IPv6 wird dagegen dann nicht die Adresse der Fritz!Box, sondern die Adresse des Endgerätes hinterlegt. Dies macht in der Praxis aber selten Sinn, weil die abgehend genutzte IPv6-Adresse des Endgerätes bei aktivierten "privacy extensions" temporär ist und sich alle paar Stunden ändert.

Glücklicherweise kann man der Update-URL aber explizit eine IP-Adresse "mitgeben"; die URLs sehen hierzu dann so aus:
http://sync.afraid.org/u/RandomizedUpdateToken/?address=Neue_IPv4_Adresse
bzw.
http://v6.sync.afraid.org/u/RandomizedUpdateToken/?address=Neue_IPv6_Adresse
wobei uns nur die Version für IPv6 interessieren braucht, denn die ( externe ) IPv4 ist ja durch NAT für alle Geräte im eigenen LAN die gleiche.

Das Script dient also in Endeffekt dazu, die spezifischen Update-URLs für die einzelnen Subdomains mit dem jeweils korrekten Token, dem aktuellen Präfix und den Suffixen der einzelnen Geräte zusammen zu bauen, um diese anschliessend per wget aufzurufen.

Die Geräte heißen bei mir ALADIN, CREST_LAN und CREST_WLAN ( wobei dies der gleiche Laptop ist, aber eben zwei Netzwerkschnittstellen besitzt). Von diesen Geräten muß zuerst der jeweilige Suffix ermittelt werden. Dies geht unter Windows mit ipconfig oder unter Linux mit ifconfig auf der Kommandozeile. Ob der Suffix aus der MAC-ID oder bei der Installation des OS per Zufallsgenerator erzeugt wurde, spielt keine Rolle. Es muß aber der Suffix der "festen" IPv6-Adresse sein, und nicht etwa der Suffix eine temporären Adresse, welcher sich ja sehr oft ändert.

Unter Windows sähe dies dann zum Beispiel so aus:
Code:
C:\Users\Nanobot>ipconfig

Windows-IP-Konfiguration


Ethernet-Adapter Atheros:

Verbindungsspezifisches DNS-Suffix:
 IPv6-Adresse. . . . . . . . . . . : 2001:16b8:40f1:5e00:0011:2233:4455:6677
Temporäre IPv6-Adresse. . . . . . : 2001:16b8:40f1:5e00:8899:aabb:ccdd:eeff
....

Richtig wäre in diesem Fälle der Suffix 0011:2233:4455:6677, denn dies ist der Suffix der "festen" IPv6-Adresse. Natürlich kann man auch 11:2233:4455:6677 verwenden, da führende 0en ja weggelassen werden dürfen. FreeDNS akzeptiert sowohl die "volle", als auch die verkürzte Notation.

Und nun das Script für "onlinechanged":

Code:
#!/bin/sh

case "$1" in
   online )

#    Update der IP-Adressen der Fritz!Box selbst
#    Bei der ersten Methode erkennt FreeDNS anhand der Quell-IPs die richtigen Adressen allein

     wget http://sync.afraid.org/u/RandomizedUpdateToken1/ -q -O /dev/null
     wget http://v6.sync.afraid.org/u/RandomizedUpdateToken2/ -q -O /dev/null

#    Die zweite Methode dient nur als Fallback, falls v6.sync.afraid.org mal wieder streikt ;-)
#    Sie ist daher auskommentiert

#    ip4addr=$(ctlmgr_ctl r dslstatistic status/ifacestat0/ipaddr)
#    ip6addr=$(ctlmgr_ctl r ipv6 settings/ip)
#    url4=http://sync.afraid.org/u/RandomizedUpdateToken1/?address=$ip4addr
#    wget $url4 -q -O /dev/null
#    url6=http://sync.afraid.org/u/RandomizedUpdateToken2/?address=$ip6addr
#    wget $url6 -q -O /dev/null


# Update der IP-Adressen mehrerer Geräte im LAN

     SUFFIX_ALADIN=0011:2233:4455:6677
     SUFFIX_CREST_LAN=8899:aabb:ccdd:eeff
     SUFFIX_CREST_WLAN=7766:5544:3322:1100

     UPDATE_ALADIN=http://v6.sync.afraid.org/RandomizedUpdateToken3/?address=
     UPDATE_CREST_LAN=http://v6.sync.afraid.org/u/RandomizedUpdateToken4/?address=
     UPDATE_CREST_WLAN=http://v6.sync.afraid.org/u/RandomizedUpdateToken5/?address=

     PREFIX=$(ctlmgr_ctl r ipv6 settings/prefix)
     PREFIX=${PREFIX%:/*}

     URL_ALADIN=$UPDATE_ALADIN$PREFIX$SUFFIX_ALADIN
     URL_CREST_LAN=$UPDATE_CREST_LAN$PREFIX$SUFFIX_CREST_LAN
     URL_CREST_WLAN=$UPDATE_CREST_WLAN$PREFIX$SUFFIX_CREST_WLAN

     wget $URL_ALADIN -q -O /dev/null
     wget $URL_CREST_LAN -q -O /dev/null
     wget $URL_CREST_WLAN -q -O /dev/null

      ;;

esac

Der erste Teil updatet die IPs der Box an sich, wobei FreeDNS die IPv4- und IPv6-Adresse anhand der Quell-IP alleine ermittelt. Hierbei nicht wundern, daß die Box selbst, sofern sie als Router agiert, eine IPv6 hat, welche nicht zum zugeteilten Präfix "passt", das ist richtig so.

Der zweite Teil ermittelt mit Hilfe von ctlmgr_ctl den aktuellen Präfix, trennt die Subnetzmaske ab, und baut dann für die einzelnen Geräte die korrekten Update-URLs aus dem jeweiligen Token, dem aktuellen Präfix und dem Suffix zusammen, um sie per wget aufzurufen.

Vielleicht wundert sich jetzt jemand, wieso hier nirgends die Namen der Subdomains auftauchen, welche geupdatet werden sollen. Dies ist bei der Methode "RandomizedUpdateToken" schlicht und einfach überflüssig, weil FreeDNS anhand des Tokens erkennen kann, auf welchen Dyndns-Namen sich das Update beziehen soll. Ich hoffe, daß ich mich nicht vertippt habe und Ihr meinen Ausführungen folgen könnt.

C.U. NanoBot
 
Zuletzt bearbeitet:
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.