Netzwerkkonfigurationen über Dispatcher-Skripte automatisieren

Aus LinuxUser 07/2020

Netzwerkkonfigurationen über Dispatcher-Skripte automatisieren

© iakovenko, 123RF

Supervisor

Mit Dispatcher-Skripten hängen Sie je nach Standort unterschiedliche Netzwerklaufwerke ein oder starten automatisch eine VPN-Verbindung, ohne dass Sie einen Finger krumm machen müssten.

Gestern auf einer Tagung, heute im Büro in der Innenstadt, morgen im Homeoffice, übermorgen in einem Café: Der Arbeitsalltag vieler Menschen beschränkt sich heute nicht mehr auf einen Schreibtisch, sondern verteilt sich auf unterschiedliche Orte. Für viele Arbeitnehmer und Selbstständige gilt daher: Wo es einen verlässlichen und schnellen Zugang zum Internet gibt, kann man seiner Arbeit nachgehen – einfach den Laptop aufklappen und loslegen.

Was sich in der Theorie erst einmal einfach anhört, steckt in der Praxis oft voller Tücken. Im Homeoffice müsste man sich gerade konzentrieren, doch die lieben Kleinen fordern Bespaßung ein; der Tisch im hippen Café im Szeneviertel wackelt zu stark. Aber auch die Technik möchte vorbereitet sein. Hier erfordern besonders die unterschiedlichen Netzwerke Aufmerksamkeit. Im LAN zu Hause möchte man die Dateifreigaben eines NAS mounten, im offenen WLAN eines Cafés sollte die Firewall alle Zugriffe blocken. Im sicheren Büro hingegen dürfen die lokal laufenden Dienste ruhig funken.

Der Dispatcher regelt’s

Die unterschiedlichen Netzwerkzugänge erfordern allerdings ständig Anpassungen am System. Geht ein Rechner nur über einen einzigen kabelgebundenen Ethernet-Anschluss ins Netz, mountet man Netzwerklaufwerke idealerweise über die /etc/fstab oder verwendet AutoFS, falls der gewünschte Server nicht immer am Netz hängt. Um aber Dienste abhängig von der Situation automatisch zu starten und zu stoppen oder um bestimmte Konfigurationen automatisiert vornehmen zu lassen, braucht es einen intelligenten Netzwerkmanager.

Nach einer solchen smarten Netzwerkverwaltung müssen Sie nicht lange suchen: Die meisten Distributionen haben in Form von NetworkManager das nötige Werkzeug von Haus aus an Bord (Abbildung 1). Als Nutzer müssen Sie nur sogenannte Dispatcher-Skripte für den Dienst konfigurieren. Die Automatik erledigt dann abhängig vom gerade aktiven Netzwerkzugang den Rest und führt beim Verbindungsauf- und -abbau beliebige Skripte automatisiert aus. Das Einrichten dieser Funktionen erfordert allerdings ein wenig Know-how, eine grafische Oberfläche dafür fehlt.

Abbildung 1: Der NetworkManager l&auml;sst sich auch &uuml;ber das Terminal bedienen. Als zentrales Steuerungswerkzeug dient das Konsolenprogramm <code>nmcli</code>.

Abbildung 1: Der NetworkManager lässt sich auch über das Terminal bedienen. Als zentrales Steuerungswerkzeug dient das Konsolenprogramm nmcli.

Achtung

Je nach eingesetzter Distribution befinden sich im Ordner /etc/NetworkManager/dispatcher.d/ bereits Dispatcher-Skripte. Ubuntu etwa bringt von Haus aus das Skript 01-ifupdown mit. Diese Dateien sollten Sie auf keinen Fall löschen oder verändern, um die Funktionen von NetworkManager nicht zu stören.

Dispatcher-Skripte schreiben

Die Dispatcher-Funktion von NetworkManager sucht im Ordner /etc/NetworkManager/dispatcher.d/ nach Skripten, die sie abarbeiten soll. Sie führt die Skripte dann beim Verbindungsaufbau in alphabetische Reihenfolge aus, beim Abbau einer Netzverbindung in umgekehrter Abfolge. Zur besseren Organisation stellen Sie den Dateinamen für eigene Skripte daher idealerweise eine Nummer voran, in der Art 30-mount-diskstation. Zudem müssen Sie darauf achten, dass die Skripte dem Root-User sowie zur Root-Gruppe gehören und ausführbar sind. Das angesprochene Skript würden Sie beispielsweise wie in Listing 1 gezeigt anlegen.

Listing 1

$ cd /etc/NetworkManager/dispatcher.d
$ sudo touch 30-mount-diskstation
$ sudo chown root:root 30-mount-diskstation
$ sudo chmod 755 30-mount-diskstation

Ein simples Skript wie in Listing 2 bindet dann zum Beispiel beim Anschluss des Rechners an einen kabelgebundenen Ethernet-Anschluss die in der /etc/fstab konfigurierten Netzwerkfreigaben ein. Die dafür nötige CONNECTION_UUID ermitteln Sie beispielsweise über das Konsolen-Frontend von NetworkManager mittels nmcli connection show (Listing 3). Beachten Sie dabei, dass sich die UUID von zuvor konfigurierten WLAN-Netzwerken jeweils unterscheidet. Die Ethernet-Schnittstelle bekommt jedoch immer dieselbe UUID, egal, ob Sie den Rechner im Büro, an der Uni oder zu Hause per Kabel ans Netzwerk hängen.

Listing 2

#!/bin/bash
if [ "$2" = "up" ]; then
  if [ "$CONNECTION_UUID" = "2911db45-3eff-3b74-9c87-4c36e0290693" ]; then
    mount /mnt/diskstation/music &
    mount /mnt/diskstation/daten &
    mount /mnt/diskstation/photo &
  fi
fi

Listing 3

$ nmcli connection show
NAME                      UUID                                  TYPE       DEVICE
LAN1                      2911db45-3eff-3b74-9c87-4c36e0290693  ethernet   enp0s31f6
Santa                     5e1eb419-9f6a-40e2-ada5-ca6a909bee87  wifi       wlp2s0
G6_SMARTPHONE             d9d63454-329e-4177-a6ef-c92b39fe26af  wifi       --
LAN2                      f38a99ea-48ea-362b-90d3-62a265930f87  ethernet   --
VPN-Netherlands           7b87cee0-3131-4b0c-a659-bb33f4a64dd8  vpn        --
PirateBox - Share Freely  46b124c1-0604-4645-99d6-5c73d200a1e6  wifi       --

Wichtig ist hier die gewünschte Aktion: In Zeile 2 von Listing 2 definieren Sie, dass der Netzwerkmanager die Aktion nach dem erfolgreichen Verbindungsaufbau ausführen soll. Es gibt zahlreiche weitere Aktionen, wie etwa down, pre-up oder pre-down; die Tabelle “Dispatcher-Aktionen” bietet einen Überblick.

Aktion

Beschreibung

pre-up

Netzwerkgerät mit dem Netz verbunden, aber noch nicht vollständig aktiviert. Skripte müssen entweder nach /etc/NetworkManager/dispatcher.d/pre-up.d kopiert oder dort per Symlink verlinkt werden.

up

Aktion wird nach dem vollständigen Verbindungsaufbau ausgeführt.

pre-down

Das Netzwerkgerät soll deaktiviert werden, ist aber noch mit dem Netz verbunden. Skripte müssen entweder nach /etc/NetworkManager/dispatcher.d/pre-down.d kopiert oder dort verlinkt werden.

down

Aktion wird nach dem Abbau einer Netzverbindung ausgeführt.

vpn-pre-up

Identisch zu pre-up, gilt aber nur für VPN-Verbindungen.

vpn-up

Aktion wird nach dem Aufbau einer VPN-Verbindung ausgeführt.

vpn-pre-down

Identisch zu pre-down, gilt aber nur für VPN-Verbindungen.

vpn-down

Aktion wird nach dem Abbau einer VPN-Verbindung ausgeführt.

hostname

Registriert die Änderung des Hostnamens.

dhcp4-change

System hat via DHCP eine neue IPv4-Konfiguration erhalten.

dhcp6-change

System hat via DHCP eine neue IPv6-Konfiguration erhalten.

connectivity-change

Netzwerkstatus hat sich verändert (siehe Tabelle “Netzwerkstatus”).

Alle pre-Aktionen (besonders pre-down und vpn-pre-down) führt NetworkManager nur aus, wenn die Netzwerkschnittstelle sauber heruntergefahren wird. Beim Absturz einer VPN-Verbindung kann das unter Umständen zur ungewollten Preisgabe von Daten führen.

Status

Beschreibung

none

Netzwerkgerät ist nicht verbunden.

portal

Netzwerkgerät ist mit einem “Captive Portal” verbunden (etwa einer Seite zur Authentifizierung in einem Hotel-WLAN) und hat noch keine Verbindung zum Internet.

limited

Das Netzwerkgerät ist mit dem LAN verbunden, hat aber keine Verbindung zum Internet.

full

Netzwerkverbindung inklusive Internet-Zugang vollständig eingerichtet.

unknown

Netzwerkstatus des Geräts kann nicht ermittelt werden.

Für Verwirrung sorgen dabei allerdings die pre-Aktionen. Für sie gibt es seit einiger Zeit unterhalb von /etc/NetworkManager/dispatcher.d/ die Unterverzeichnisse pre-up.d/ und pre-down.d/. Dort hinterlegte oder verlinkte Skripte führt der Netzwerkmanager ohne Fallunterscheidung im Skript selbst bei der entsprechenden Aktion aus. Listing 4 würde, als [...]/pre-down.d/10-umount-cifs abgespeichert, beispielsweise die zuvor über Listing 2 gemounteten Freigaben vor dem Abbauen der Netzwerkverbindung sicher aushängen.

Listing 4

#!/bin/bash
umount -a -l -t cifs

Ungeduldig

Für Dispatcher-Skripte, die NetworkManager unabhängig von der Reihenfolge abarbeiten soll, gibt es unter /etc/NetworkManager/dispatcher.d/ den Ordner no-wait.d/. Die dort abgelegten Skripte führt NetworkManager umgehend nach dem Ändern des Netzwerkstatus aus, egal, welche anderen Skripte gerade noch aktiv sind.

Um nun je nach Arbeitsort unterschiedliche Freigaben zu realisieren, lässt sich das Prinzip von Listing 2 noch etwas erweitern. Bestücken Sie das Skript mit dem Inhalt aus Listing 5, überprüft NetworkManager mithilfe des Netcat-Kommandos nc -z Server 139. ob der in der Variablen SERVERNAME eingetragene Rechner im Netz zu finden ist und ob auf ihm der Samba-Dienst auf Port 139 läuft. Falls ja, mountet das Skript die im Array SHARES aufgeführten Freigaben.

Listing 5

#!/bin/bash
SERVERNAME="diskstation"
FOLDER="/mnt/diskstation"
SHARES=(homes music daten photo ebooks images video web)
if [ "$2" = "up" ]; then
  if [ "$CONNECTION_UUID" = "2911db45-3eff-3b74-9c87-4c36e0290693" ]; then
    ### Prüfen ob $SERVERNAME online ist und Samba-Shares anbietet
    if nc -z $SERVERNAME 139 2>/dev/null; then
      ### Wenn ja, dannn mounte Freigaben aus Array $SHARES
      for SHARE in "${SHARES[@]}"
      do
        ### Nur einbinden, wenn Freigabe noch nicht gemountet
        if ! $(mountpoint -q "$FOLDER/$SHARE") ; then
          mount $FOLDER/$SHARE
        fi
      done
    fi
  fi
fi

Damit haben Sie bereits ein Ziel erreicht: Für jeden üblicherweise genutzten Samba-Server erstellen Sie unter /etc/NetworkManager/dispatcher.d ein Skript in der Art 30-mount-Server, das in Zukunft das situative Mounten von Netzwerkfreigaben übernimmt. Sie müssen lediglich die Variablen im Kopf des Skripts anpassen sowie die UUID ändern. Sollte einmal ein Server nicht zu erreichen sein, hält sich das System nicht mit erfolglosen Versuchen auf, den Server im Netz zu finden.

Umgebungsvariablen

NetworkManager befüllt in den Dispatcher-Skripten eine Reihe von Umgebungsvariablen, die sich zum Steuern der gewünschten Aktionen nutzen lassen. So finden Sie in $IP4_DOMAINS den vom DHCP-Server zugewiesenen Domain-Namen, in $IP4_ADDRESS_0 die IP- sowie Gateway-Adresse im Format IP-Adresse/Prefix Gateway. Sämtliche Variablen erklärt die Developer-Seite der Gnome-Foundation zu NetworkManager [1]. Bei Bedarf schreiben Sie den Inhalt dieser Variablen mit dem Kommando printenv >&2 in das Journal des Systems. Dementsprechend lässt sich dann mithilfe von journalctl -f -u NetworkManager der Inhalt der Variablen während der Laufzeit des Dispatcher-Skripts einsehen (Listing 6).

Listing 6

$ journalctl -f -u NetworkManager
[...]
Mai 22 23:44:01 ontario NetworkManager[485]: <info>  [1590183841.6878] dhcp4 (enp0s31f6): option domain_name          => 'fritz.box'
Mai 22 23:44:01 ontario NetworkManager[485]: <info>  [1590183841.6878] dhcp4 (enp0s31f6): option domain_name_servers  => '192.168.188.11'
Mai 22 23:44:01 ontario NetworkManager[485]: <info>  [1590183841.6878] dhcp4 (enp0s31f6): option ntp_servers          => '192.168.188.1'
[...]

Automatisch ins VPN

Ein anderer populärer Anwendungsfall besteht darin, beim Verbindungsaufbau zu einem bestimmten WLAN automatisch eine VPN-Verbindung zu starten. Sichern Sie zum Beispiel Listing 7 als 20-protonvpn in /etc/NetworkManager/dispatcher.d, so ruft der NetworkManager beim Verbindungsaufbau zum WLAN mit der angegebenen UUID über das textbasierte Frontend des Netzwerkmanagers nmcli eine Verbindung zum VPN mit der ID ProtonUS auf. Diesmal sorgt eine Fallunterscheidung mithilfe des case-Kommandos für die unterschiedlichen Kommandos beim Auf- und Abbau der Verbindung (Abbildung 2).

Abbildung 2: Mit dem entsprechenden Dispatcher-Skript startet NetworkManager bei der Einwahl in ein bestimmtes WLAN automatisch eine VPN-Verbindung.

Abbildung 2: Mit dem entsprechenden Dispatcher-Skript startet NetworkManager bei der Einwahl in ein bestimmtes WLAN automatisch eine VPN-Verbindung.

Listing 7

#!/bin/sh
if [ "$CONNECTION_UUID" = "5e1eb419-9f6a-40e2-ada5-ca6a909bee87" ]; then
  case "$2" in
    up)
      nmcli connection up id "ProtonUS" passwd-file /root/protonvpn-passwd-file
    ;;
    pre-down)
      nmcli connection down id "ProtonUS"
    ;;
  esac
fi

Dabei müssen Sie beachten, dass Sie beim Konfigurieren der VPN-Verbindung über das grafische Frontend von NetworkManager das Passwort des VPN-Zugangs benutzerspezifisch im Schlüsselbund der Desktop-Umgebung ablegen. Der als Root gestartete NetworkManager-Dienst hat auf diese Inhalte allerdings keinen Zugriff, Sie müssen das Passwort daher noch einmal gesondert im System abspeichern. Das Beispiel aus Listing 7 verwendet die Datei /root/protonvpn-passwd-file. Das Format der Passwortdatei zeigt Ihnen die Ausgabe des zweiten Kommandos in Listing 8.

Listing 8

# nmcli connection show
NAME        UUID                                   TYPE   DEVICE
ProtonUS    4610ff84-57d8-4509-a56d-c33a5c7f21c9   vpn    --
SantaFAST   5e1eb419-9f6a-40e2-ada5-ca6a909bee87   wifi   --
# cat /root/protonvpn-passwd-file
vpn.secrets.password:geheimes+passwort

Optional könnten Sie auch unter /etc/NetworkManager/system-connections/ direkt die für das gewünschte Netz verantwortliche Konfigurationsdatei bearbeiten. Im fraglichen File müssten Sie dann im Abschnitt [vpn] in der Option password-flags= eine 0 statt einer 1 setzen und dann unter [vpn-secrets] über die neu hinzuzufügende Zeile password=Passwort das Passwort hinterlegen. So kann der NetworkManager auch ohne Interaktion des Benutzers die gewünschte VPN-Verbindung starten.

Hinweis

Der Aufbau einer VPN-Verbindung genügt alleine noch nicht für sicheres und anonymisiertes Surfen im Netz. Sollte zum Beispiel das VPN aufgrund von Übertragungsfehlern ungewollt zusammenbrechen, würde der NetworkManager das nicht bemerken und die Daten dann unverschlüsselt übertragen. Sie sollten daher zusätzlich mit geeigneten Firewall-Skripten dafür sorgen, dass das System ausschließlich den verschlüsselten Tunnel für Datenübertragungen verwendet.

Debuggen

Da NetworkManager bis auf die Konfiguration im Hintergrund arbeitet, lassen sich eigene Dispatcher-Skripte nicht so ohne Weiteres auf Fehler hin untersuchen. Stimmt etwas nicht, springt nicht einfach ein Fenster mit hilfreichen Fehlermeldungen auf: Bei einem Fehler im Skript passiert schlichtweg gar nichts. Um dennoch Programmierfehlern auf die Schliche zu kommen, muss man in die Logs des Systems schauen.

Zum einen können Sie mit nmcli monitor in Echtzeit verfolgen, was NetworkManager gerade macht. Sie sehen, wie die Netzwerkgeräte heißen und welche Aktionen gerade ablaufen. Um die Logs von NetworkManager einzusehen, müssen Sie mit journalctl das Journal des Systemd-Protokolls auswerten. Mit dem Kommando journalctl -f -u NetworkManager werfen Sie zum anderen in Echtzeit einen Blick auf das Log und filtern dabei gleich die Ausgaben von NetworkManager heraus (Listing 9).

Listing 9

$ journalctl -f -u NetworkManager
[...]
Mai 22 23:21:45 ontario NetworkManager[485]: <warn>  [1590182505.2987] dispatcher: (44) /etc/NetworkManager/dispatcher.d/30-mount-diskstation failed (failed): Script '/etc/NetworkManager/dispatcher.d/30-mount-diskstation' exited with error status 2.
$ nmcli monitor
enp0s31f6: Verbindung »LAN1« wird verwendet
enp0s31f6: wird verbunden (wird vorbereitet)
NetworkManager ist jetzt im Zustand »wird verbunden«
[...]
NetworkManager ist jetzt im Zustand »verbunden«
Verbindungszustand ist jetzt »vollständig«

Diese Kommandos liefert Ihnen einen allgemeinen Überblick über die Aktionen des Netzwerkmanagers. Um nun aber gezielt nach einem Fehler zu forschen, empfiehlt es sich, an kritischen Stellen per logger selbst in das Systemd-Log zu schreiben. Ein Beispiel dafür finden Sie in Listing 10. Dabei können Sie auf die von NetworkManager für das Dispatching verwendeten Variablen $0 (Skript-Name), $1 (Netzwerkgerät) und $2 (Aktion) zurückgreifen, aber auch die von der Dispatcher-Funktion bereitgestellten Umgebungsvariablen wie $CONNECTION_UUID oder $IP4_DOMAINS verwenden (Listing 11).

Listing 10

#!/bin/bash
logger "LOGGER: Führe Skript $0 aus."
if [ "$2" = "up" ]; then
  logger "LOGGER: Netzwerkgerät: $1, Aktion: $2"
  logger "LOGGER: Umgebung: CONNECTION_UUID=$CONNECTION_UUID, IP4_DOMAINS=$IP4_DOMAINS"
fi

Listing 11

$ journalctl -f | grep LOGGER
[...]
Mai 22 23:36:47 ontario root[16135]: LOGGER: Führe Skript /etc/NetworkManager/dispatcher.d/30-mount-diskstation aus.
Mai 22 23:36:47 ontario root[16136]: LOGGER: Netzwerkgerät: enp0s31f6, Aktion: up
Mai 22 23:50:31 ontario root[18811]: LOGGER: Umgebung: CONNECTION_UUID=2911db45-3eff-3b74-9c87-4c36e0290693, IP4_DOMAINS=fritz.box

Fazit

Die vom Dispatcher zur Verfügung gestellte Bandbreite an Möglichkeiten ist schier unbegrenzt: Alles, was Sie im System auf Dateiebene ändern können, lässt sich mithilfe von Dispatcher-Skripten umsetzen und situationsabhängig automatisieren. Die größte Schwierigkeit besteht darin, an Log-Ausgaben zu kommen oder die beim Dispatching befüllten Umgebungsvariablen einzusehen. Mit den entsprechenden Tricks lassen sich diese Hürden jedoch schnell nehmen.

Ein passendes Dispatcher-Skript schreibt sich allerdings nicht von alleine. Bis alles wie gewünscht funktioniert, braucht es etwas Zeit – besonders, wenn Sie noch nicht viel mit Shell-Skripten gearbeitet haben. Ein Dispatcher-Skript ist jedoch ein ideales Fallbeispiel für die individuelle Gestaltung des eigenen Systems: Schließlich lassen sich mit dem Dispatcher Probleme lösen, für die es keine vorgefertigten Pakete zur Installation gibt.

Wie aber schon der Autor der Xkcd-Webcomics zum Thema Automatisierung festgestellt hat [2], unterscheidet sich die in der Theorie erhoffte Zeitersparnis vom Zeitgewinn in der Realität oft ganz erheblich. 

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 07/2020 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben