[[Vorlage(getestet, , bionic, focal)]] {{{#!vorlage Wissen [:Editor: Einen Editor öffnen] [:Rechte: Rechte von Ordnern und Dateien ändern] }}} [[Inhaltsverzeichnis(3)]] Der [:NetworkManager:] kann mehr als nur einfach eine Verbindung auf- und wieder abbauen. Er ist in der Lage, zusätzliche Skripte beim Verbindungsauf- und -abbau ausführen. Dies erfolgt über Dispatcher-Skripte, die ausgeführt werden, wenn der NetworkManager eine Aktion durchführt, z.B. wenn er sich zu einem WLAN verbindet oder davon trennt. Diese Funktionen sind jedoch nicht von der grafischen Oberfläche aus konfigurierbar. {{{#!vorlage Warnung Das Skript '''/etc/NetworkManager/dispatcher.d/01-ifupdown''' sollte man niemals löschen oder modifizieren. Es ist ein grundlegender Bestandteil der Funktionalität des NetworkManagers und wird in unveränderter Form für die Funktion des NetworkManagers benötigt. }}} = Was ist ein Dispatcher-Skript = Grundsätzlich ist ein Dispatcher-Skript ein ganz normales Shellskript, das im Ordner '''/etc/NetworkManager/dispatcher.d/''' liegt. Diese Skripte werden dann vom NetworkManager bei einer Änderung an den Netzwerken mit zwei Parametern aufgerufen: Netzwerkschnittstelle und Aktion. Wichtig dabei ist, dass [:root:] der Besitzer der Skripte ist, da sie sonst nicht ausgeführt werden können. In dem Ordner können mehrere Skripte liegen, diese werden in alphabetischer Reihenfolge abgearbeitet. Ein Skript liegt bereits in dem Ordner, '''01-ifupdown''', dieses sorgt dafür, dass Skripte für das Konfigurationssystem '''ifupdown''' in den Verzeichnissen unter '''/etc/network/''' mit den richtigen Informationen in ihrer Programmumgebung aufgerufen werden. Auch bei inaktivem '''ifupdown''' legen viele Programme hier ihre Startskripte ab. Die Skripte sollten den Statuswert 0 (= Erfolg) an den Dispatcher zurück geben. Bei einigen Versionen des NetworkManager bricht der Dispatcher den Aufruf weiterer Skripte ab, sobald eines einen Fehler meldet. == Aktionen == Als zweiter Parameter wird dem Script vom NetworkManager der Name der Aktion übergeben, welche die Ausführung des Dispatchers ausgelöst hat. ||<-3 tableclass="zebra_start3" rowclass="titel" :>Dispatcher Aktionen|| ||Aktion||Bedeutung||Anwendungsbeispiel|| || `pre-up` || Die Aktivierung einer Netzwerk-Schnittstelle steht bevor. || || || `up` || Eine reelle Netzwerk-Schnittstelle wurde aktiviert. || Mountet man Netzwerkfreigaben über ein Netzwerk, so kann man dieses an dieser Stelle ausführen lassen. || || `pre-down` || Die De-Aktivierung einer Netzwerk-Schnittstelle steht bevor. || Hat man Netzwerkfreigaben eingebunden, so sollte man diese vor dem Verbindungsabbau aushängen. Erst dann kann man sicher gehen, dass alle Daten korrekt geschrieben wurden. Beachte: Dieses Ereignis wird nicht immer ausgelöst! (S.u.) || || `down` || Eine reelle Netzwerk-Schnittstelle wurde deaktiviert. || Für eine Synchronisation über das Netzwerk ist es jetzt zu spät. Man kann aber den Müll wegräumen. || || `pre-vpn-up` || Die Aktivierung einer VPN-Schnittstelle steht bevor. || || || `vpn-up` || Eine virtuelle (VPN) Netzwerk-Schnittstelle wurde aktiviert. || Dies ist der richtige Zeitpunkt zur Anpassung der DNS-Namensserver, sofern NetworkManager es nicht richtig macht. || || `vpn-pre-down` || Die De-Aktivierung einer VPN-Schnittstelle steht bevor. || || || `vpn-down` || Eine virtuelle (VPN) Netzwerk-Schnittstelle wurde deaktiviert. || || || `hostname` || Der Hostname wurde geändert || || || `dhcp4-change` || Der DHCP lease hat sich geändert (IPv4 Verbidungen) || || || `dhcp6-change` || Der DHCP lease hat sich geändert (IPv6 Verbidungen) || || || `connectivity-change` || Die Verbindungsqualität des Netzwerks hat sich geändert.|| Es gibt die Zustände `UNKNOWN`, `NONE`, `PORTAL`, `LIMITED` und `FULL`. || Die Aktionen `pre-…` funktionieren unter 16.04 gar nicht oder nur unzuverlässig. Ab Ubuntu 18.04 kann man diese benutzen, jedoch werden diese Aktionen nur an Skripte in den entsprechenden Unterverzeichnissen '''/etc/NetworkManager/dispatcher.d/pre-up.d/''' bzw. '''/etc/NetworkManager/dispatcher.d/pre-down.d/''' weitergegeben. Es reicht aus, in diesen Verzeichnissen einen Symlink zum Skript in '''/etc/NetworkManager/dispatcher.d/''' anzulegen. {{{#!vorlage Hinweis Die Aktion `pre-down` wird nur aufgerufen, wenn NetworkManager selbst die Deaktivierung der Schnittstelle verursacht. Eine von anderer Seite verursachte Abschaltung, wie beispielsweise über '''rfkill''', betätigen eines Hardware-Schalters oder gar Störungen im Netzwerk kann NetworkManager nicht vorher erkennen. Bei den Aktionen `hostname`, `dhcp*` und `connectivity-change` ist der erste übergebene Parameter entweder `none` oder möglicherweise leer, aber immer vorhanden. Programmieren ohne ausreichendes Quoting kann zu falschem Verhalten führen. }}} == Environment == Die Skripte werden mit einer spezifischen Programmumgebung gestartet, deren Variablen Informationen zur momentanen Situation der Netzwerk-Konfiguration enthalten, beispielsweise `CONNECTION_ID` (= Name der Verbindung) oder `IP4_ADDRESS_0` (= erste IPv4-Adresse). Die tatsächlich verfügbaren Variablen variieren mit der Aktion (zweiter Parameter); man kann sie in der Praxis ermitteln, indem man sie von einem Skript mit diesem Befehl ins Systemlog schreiben lässt: {{{#!code bash printenv >&2 }}} = Was kann man damit machen? = Eigentlich alles was ein Skript so kann... man sollte aber nur sinnvolle Dinge wie z.B. automatischer Uhrzeitabgleich, Starten eines VPN-Clients oder Umschalten der [:iptables: iptables-Konfiguration] machen. Grundsätzlich kann man die Skripte in jeder Programmiersprache erstellen. Es ist jedoch üblich, für solche Systemskripte die System-Shell zu verwenden, also bei Ubuntu die [:Dash:]. == Beispiele == === NM-Ereignisse im Systemlog === Bei Netzwerkproblemen möchte man oft durch Analyse des Systemlogs Fehler finden, weiß aber nicht, nach welchen Begriffen man suchen soll. In dieser Situation hilft das Skript '''00-logger''', indem es einfach Meldungen mit bekannten Texten ins Systemlog schreibt. {{{#!code bash #! /bin/dash -e # Script to dispatch NetworkManager events # # /etc/NetworkManager/dispatcher.d/00-logger # logs calls to syslog. # See NetworkManager(8) for further documentation of the dispatcher events. # SPDX-License-Identifier: GPL-2.0-or-later # (c) 2020 kB @ ubuntuusers.de myName=${0##*/} : ${PATH:=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} #LOG() logger --tag="nm-dispatcher-script" --id=$PPID "$@" #LOG() logger --tag="nm-dispatcher-script [$PPID]" --id=$$ "$@" LOG() logger --tag="$myName [$$]" --id=$PPID "$@" ERROR() LOG -p user.err -- "$@" # 3 WARN() LOG -p user.warning -- "$@" # 4 NOTE() LOG -p user.notice -- "$@" # 5* INFO() LOG -p user.info -- "$@" # 6 DEBUG() LOG -p user.debug -- "$@" # 7 DIE() { ERROR $0 $* ; false ;} put_symlink_in() \ for dir do dir=/etc/NetworkManager/dispatcher.d/${dir}.d test -e $dir/$myName || ln -s $0 $dir/ done test $myName = 00-logger && { DEBUG $0 $* start. case $2 in (vpn*) NOTE "$2 $DEVICE_IP_IFACE/$DEVICE_IFACE/$1/$CONNECTION_ID " ip -4 route | NOTE esac case $2 in ('') DIE no action found. # Should never happen. ;; (hostname) NOTE Hostname: $(hostname) ;; (connectivity*) NOTE Netzanbindung: $CONNECTIVITY_STATE { ip -6 route ; ip -4 route ;} | INFO ;; (dhcp4*) NOTE DHCP4 $1 #printenv | grep DHCP4 | DEBUG ;; (dhcp6*) NOTE DHCP6 $1 #printenv | grep DHCP6 | DEBUG ;; (*up|*down) { echo -n "$1/$CONNECTION_ID " nmcli --get-values general.state device show $1 | sed 's/^[^(]*(//; s/)$//' } | NOTE ;; (*) WARN 1=$1, 2=$2. esac put_symlink_in pre-up pre-down DEBUG $0 $* endet. } || DEBUG 00-logger sourced. }}} Die Meldungen erfolgen mit unterschiedlicher Priorität und Ausführlichkeit, nach denen man filtern kann. Beispielsweise sieht man mit dem Befehl {{{journalctl -f -p 0..5 | grep nm-dispatcher }}} alle Meldungen von '''nm-dispatcher''' mit den Prioritäten `0..5` (= notice) nach Absenden dieses Befehls fortlaufend aktualisiert, darunter auch die Meldungen dieses Skripts. Alle Meldungen bekommt man, indem man `0..7` (= debug) verwendet oder die Option `-p` ganz weg lässt. Alternativ kann man bei neueren Versionen des NetworkManagers auch diesen Befehl verwenden: {{{journalctl -b 0 -p 5 -u NetworkManager-dispatcher.service }}} Damit werden alle dem Dispatcher zugeordneten Meldungen ab dem aktuellen Rechnerstart bis Priorität 5 seitenweise angezeigt. Den Stil der Meldungen kann man durch Wahl zweckmäßiger Optionen für den Systemlogger anpassen, siehe auskommentierte Vorschläge im Skript. === Netzwerk Freigaben einbinden === Die automatische Einbindung von im Netzwerk freigegebenen Dateisystemen soll normalerweise über das Init-System (z.B. [:systemd:]) erfolgen, jedoch funktioniert das nicht immer. In diesen Fällen kann man alternativ die Einbindung über ein Dispatcher-Skript versuchen. Das hier vorgestellte Skript bindet aus der Datei '''/etc/fstab''' alle Dateisysteme ein, welche mit den beiden Optionen `_netdev` und `noauto` markiert sind, wenn eine dem Skript bekannte Verbindung aktiviert wird. Beim Deaktivieren dieser Verbindung werden alle eingebundenen Netzwerk-Dateisysteme entfernt. {{{#!code bash #! /bin/dash -e # Script to dispatch NetworkManager events # /etc/NetworkManager/dispatcher.d/50-net-shares # mounts network shares # See NetworkManager(8) for further documentation of the dispatcher events. # SPDX-License-Identifier: GPL-2.0-or-later # (c) 2020 kB @ ubuntuusers.de # Use "nmcli connection" to find your UUID. myUUID=b1317c20-4258-4e32-b947-2614c69fee41 # Change this! #----------------------------------------------------------------------- case $2 in (vpn-up|up|*pre-down) test $CONNECTION_UUID = ${myUUID:=none} ;; (*) false esac || exit 0 . /etc/NetworkManager/dispatcher.d/00-logger put_symlink_in pre-down case $2 in (*up) awk '/_netdev/ && /noauto/ && ! /^#/' /etc/fstab | while read source target more do NOTE mounting $source on $target mount -v $target 2>&1 | INFO done esac { findmnt --output FSTYPE,SOURCE --types nfs,nfs4,cifs | grep '' || WARN Keine Netzlaufwerke eingebunden. } | NOTE case $2 in (*pre-down) umount --verbose --lazy --all --types nfs,nfs4,cifs | grep success | NOTE esac DEBUG "$0 $* ends." }}} Dieses Skript benötigt das Skript '''00-logger''' für Meldungen und zur Realisierung der pre-down-Funktionalität. Da diese pre-down-Funktionalität prinzipbedingt jedoch nicht immer funktioniert, ist dieses Skript nicht geeignet zur Verbesserung der Datensicherheit, sondern lediglich eine Komfort-Funktion. === VPN: Datenlecks verhindern === Der Auf- und Abbau von VPN-Verbindungen gehört zur Grundfunktionalität von NetworkManager und bedarf selbst keiner Unterstützung durch Skripte. Jedoch möchte man in der Regel bei VPN-Nutzung verhindern, dass über die immer noch bestehenden Basis-IP-Verbindungen für IPv6 und IPv4 am Tunnel vorbei Informationen für Außenstehende sichtbar bleiben. Ein weiteres Problem stellt der DNS-Namensdienst dar, wenn Abfragen am Tunnel vorbei zu den DNS-Servern gelangen. Bei einem korrekt konfigurierten VPN stellt NetworkManager bereits eine ziemlich sichere Mitgliedschaft im VPN her. Das hier vorgestellte Skript '''30-VPN-only''' baut darauf auf und realisiert zusätzlich diese Sicherheitsaspekte: * Beschränkung der (entweder IPv4- oder IPv6-) Basis-Verbindung auf die Erreichbarkeit des eigenen Routers und das VPN-Gateway. Alle anderen, vor dem Aufbau des VPN möglichen IPv4- und IPv6-Verbindungen werden entweder blockiert oder in den Tunnel geleitet. Dies wird realisiert durch eine zusätzliche, der üblichen Routing-Tabelle `main` vorgeschaltete Routing-Tabelle. In dieser zusätzlichen Routing-Tabelle werden IP-Ziele entweder direkt verboten (prohibit-Route) oder zur Bearbeitung in weiteren Routing-Tabellen zugelassen (throw-Route). * Deaktivierung der für die Basis-Verbindung definierten DNS-Server. Es werden nur noch die durch die VPN-Verbindung vorgegebenen DNS-Server kontaktiert. Diese Funktionalität setzt eine Zusammenarbeit des NetworkManager mit systemd-resolve voraus und funktioniert daher nur ab Ubuntu 18.04. Dieses Skript beschränkt die Konnektivität des Rechnersystems und ist daher nur für jene geeignet, die Wert auf die durch diese Einschränkung verbesserte Vermeidung von Datenlecks legen! Man kann nicht beides gleichzeitig haben. Mit diesem Skript kann der Rechner Ziele im LAN außer dem Router nicht mehr erreichen und kann auch von Rechnern im LAN nicht mehr erreicht werden. Man kann im Skript über die Variable `myUUID` festlegen, für welche VPN-Verbindung das Skript arbeiten soll. Wenn es für jede VPN-Verbindung wirksam sein soll, lässt man die Variable einfach undefiniert. Es liegt in der Verantwortung jedes VPN-Betreibers, ob sein VPN einen Zugang zum freien Internet ermöglicht oder nicht. In VPN ohne freien Zugang zum Internet muss bei Benutzung dieses Skripts der Konnektivitäts-Check des NetworkManagers ausgeschaltet oder speziel für das VPN umkonfiguriert werden. Anderenfalls wird NetworkManager nach wenigen Minuten die VPN-Verbindung beenden, weil der Konnektivitäts-Status `FULL` nicht erreicht wurde. Bei VPN mit Zugang zum freien Internet sollte der Konnektivitäts-Check ohne Änderung funktionieren. {{{#!code bash #! /bin/dash -e # Script to dispatch NetworkManager events # /etc/NetworkManager/dispatcher.d/30-VPN-only # disconnects non-VPN networks # See NetworkManager(8) for further documentation of the dispatcher events. # SPDX-License-Identifier: GPL-2.0-or-later # (c) 2020 kB @ ubuntuusers.de # Use "nmcli connection" to find your UUID. #myUUID=df719bbe-5a2f-4fa0-aa14-035bb577f040 # Change this! #----------------------------------------------------------------------- case $2 in (vpn-*) test $CONNECTION_UUID = ${myUUID:-$CONNECTION_UUID} ;; (*) false esac || exit 0 . ${0%/*}/00-logger put_symlink_in pre-up IP() { ip -${IPv:-4} "$@" || true ;} ROUTE() case $* in (*table*) IP route "$@" ;; (*) ROUTE "$@" table 666 ; esac RULE() { IP rule "$@" pref 1 ;} filter() { while RULE show | grep -q '' ; do RULE del ; done ROUTE flush case $* in (OFF|'') return ; esac ROUTE add throw default ROUTE show table main | grep -v "dev $1" | while read prefix more do case $prefix in (default) continue ;; (*/128) test $IPv = 6 ;; (*/32) test $IPv = 4 ;; (*/*) false ;; (*) true esac && destiny=throw || destiny=prohibit DEBUG $destiny $prefix ROUTE add $destiny $prefix done RULE add lookup 666 } X="Erlaube $1, beschränke $DEVICE_IP_IFACE, blockiere andere" #X="Allow $1, restrict $DEVICE_IP_IFACE, block other" for IPv in 4 6 do case $2 in (vpn-pre-up) filter $1 ; NOTE "IPv$IPv-Filter: $X" ;; (vpn-up) resolvectl -$IPv revert $DEVICE_IP_IFACE ;; (vpn-down) filter OFF ; NOTE IPv$IPv-Filter entfernt. esac done { echo "DNS-Servers ($2)" ; resolvectl dns ;} | INFO DEBUG $* ends. }}} Dieses Skript benötigt das Skript '''00-logger''' für Meldungen und zur Realisierung der pre-up-Funktionalität. === Wifi deaktivieren wenn Ethernet (LAN) verfügbar ist, und umgekehrt === Dieses Skript ist ab Ubuntu 18.04 nicht erforderlich, da deren NetworkManager die Funktionalität selbst beherrscht. Am einfachsten legt man das Skript im Terminal an: {{{#!vorlage Befehl sudo nano /etc/NetworkManager/dispatcher.d/10-wifi-off }}} Das eigentliche Skript mit Logger nach /var/log/syslog: {{{#!code bash #!/bin/bash logger "Running $0" case "$1" in eth*) # Name der Ethernet-Schnittstelle. Bitte mit oder ermitteln # und hier ggf. ändern! if [ "$2" == up ]; then logger "$1 $2 wifi off" nmcli radio wifi off elif [ "$2" == down ]; then logger "$1 $2 wifi on" nmcli radio wifi on fi esac }}} Danach die Rechte richtig setzten: {{{#!vorlage Befehl sudo chmod 755 /etc/NetworkManager/dispatcher.d/10-wifi-off }}} Wenn die der Name der Ethernet-Schnittstelle richtig eingetragen wurde, funktioniert das Skript sofort: LAN-Kabel rein -> WLAN wird deaktiviert LAN-Kabel raus -> WLAN wird aktiviert und verbindet sich neu = Links = * [:NetworkManager:] {Übersicht} Übersichtsartikel * https://developer.gnome.org/NetworkManager/stable/NetworkManager.html Dokumentation für Entwickler. Beachte: Hier soll jeweils die aktuellste Version beschrieben werden. Die im eigenen System verfügbare Version von NetworkManager und Dispatcher verfügt möglicherweise nicht über alle hier beschriebenen Eigenschaften oder macht Details anders. #tag:Internet, Netzwerk, VPN