Dispatcher
Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:
Ubuntu 20.04 Focal Fossa
Du möchtest den Artikel für eine weitere Ubuntu-Version testen? Mitarbeit im Wiki ist immer willkommen! Dazu sind die Hinweise zum Testen von Artikeln zu beachten.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
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.
Achtung!
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.
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.
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:
1 | 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-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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #! /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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #! /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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #! /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:
sudo nano /etc/NetworkManager/dispatcher.d/10-wifi-off
Das eigentliche Skript mit Logger nach /var/log/syslog:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/bash logger "Running $0" case "$1" in eth*) # Name der Ethernet-Schnittstelle. Bitte mit <ip link> oder <ifconfig -a> 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:
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 Ü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.