Selnic – Select Network-Interface und verbinde WLAN-Accesspoints
Selnic ist ein einfacher Non-Daemon-Netzwerkmanager, der als Bash-Script sowohl bei Systemstart zur Herstellung einer Verbindung laufen kann, als auch interaktiv zur Rechnerlaufzeit genutzt werden kann. Selnic ist ein reines Vordergrund-Programm.
Inhaltsübersicht über die Kapitel dieses Artikels:
> Einrichten für den System-Start mithilfe von Service-Units
> Überblick über die Abläufe bei Boot und Shutdown
> Anlegen einer neuen WLAN-Verbindung
> Commandline-Parameter und Return-Codes
> Galerie
|
Selnic ist als Bash-Script mit dem Ziel entstanden, eine grundlegende Unterstützung beim Öffnen und Schließen eines Netzwerk-Adapters sowie beim Herstellen einer Netzwerkverbindung zu erhalten. In gewisser Weise übernimmt Selnic damit einen Teil der Aufgaben eines traditionellen Netzwerk-Managers, ohne aber selber ein Netzwerk-Manager sein zu wollen. Selnic ist kein Daemon, sondern ein immer im Vordergrund laufendes Terminalprogramm. Es kann aber trotzdem auch via Service-Unit bei Systemstart vorübergehend im Hintergrund gestartet und unsichtbar seinen Job tun, und ebenso auch via Desktopstarter oder auch direkt im Terminal im Dialog-Modus gestartet werden. Insbesondere im Dialog-Modus ist das, was selnic tut, durch den aktivierbaren Trace-Mode hochtransparent. Weil selnic wegen dem Öffnen und Schließen von Netzwerkadaptern root-Rechte benötigt, ist hierfür eine Polkit-Berechtigungsregel notwendig, wenn ein unprivilegierter Anwender selnic bedienen soll.
Es sind die folgenden Ziele, die ich mit selnic erreichen wollte:
1. Zur Beseitigung altbekannter Fehler und Probleme:
- Verhindern, dass die herkömmlichen Networkmanager beim Shutdown WLAN-Verbindungen trennen, bevor die Netzwerk-Mounts 'umount'ed sind, was im Regelfall in diesen unschönen 90-Sekunden-Stobjobs endet, die den Shutdown blockieren.
- Die fehlende Abstimmung zwischen Netzwerk-Verbindung und Netzwerk-Mounts beseitigen, weil eine vorhandene Netzwerkverbindung auf meinem Laptop nicht bedeutet, dass auch meine Server-Platten erreichbar sind. Das bedeutet, wenn sich mein Laptop zuhause via WLAN verbindet, sollen die Server-Platten gemountet werden, unterwegs und bei Anmeldung an fremden WISP jedoch nicht. Wenn ich jedoch unterwegs via OpenVPN verbunden bin, will ich die Mounts übers Menü aber ggf. doch ermöglichen.
2. Um eine reine Vordergrundanwendung zu haben, die mir nicht im Hintergrund irgendwie ins Handwerk pfuscht und mit der ich notfalls auch gleichzeitig eth0 und wlan0 verbinden kann, was z.B. der Networkmanager gar nicht zulässt. Genau das brauche ich aber, wenn ich beispielsweise unterwegs via Kabel über meinen WLAN-Router den AccessPoint auf dem Dach einstellen will und gleichzeitig dabei die WLAN-Netze sehen muss.
3. Für eine optimale Unterstützung auf der bei Reisen täglich wechselnden WLAN-Anbieter. Das heißt, fremde WISP werden nur bei Bedarf ad hoc und manuell verbunden, aber beim nächsten Einschalten wird nicht dauerhaft versucht, den letzten WISP erneut zu verbinden. Eine automatische Verbindung, die im Hintergrund erfolgt, darf auf gar keinen Fall durchgeführt werden, nur weil der NWM meint "Ach, den kenn ich ja noch vom letzten Mal".
4. Um völlig flexibel den Laptop auf Reisen mit und ohne Netzwerk zu betreiben. Es wird nichts automatisch verbunden, aber eine Verbindung zum vorhanden WLAN-Netz kann jederzeit mit einem Klick hergestellt werden, sofern bereits eine SSID.conf besteht.
5. Wegen der Möglichkeit, völlig transparent in den von selnic erstellten SSID-eigenen /etc/wpa_supplicant/*.conf's manuell optimale Anpassungen durchführen zu können, falls selnic Probleme hat, einen WISP und dessen Einstellungen sauber zu identifizieren.
6. Wegen der Einbindung meiner Unit ‚mountctl@.service‘, mit der ich über selnic's Menü meine Netzwerk-Mounts verbinden kann. selnic sorgt beim Trennen vom WISP dafür, dass die Mounts vorher ordentlich geschlossen werden.
7. Um flexibel bei Verbindung in fremden Netzwerken mit Hilfe meiner Unit ‚openvpn.service‘ eine OpenVPN-Verbindung zum heimischen Router herstellen zu können, um entweder sicher zu surfen oder Zugang ins Heimnetz zu erhalten, z.B. für Mailserver, Festplatten
8. Zur Verhinderung von unnötig laufenden Diensten wie dhcpd und networkmanager, die ich generell für unsere Systeme für unerwünscht erachte und die mit selnic jetzt auch überflüssig sind.
|
selnic kann nicht konfliktfrei gleichzeitig mit dem dhcpd-Daemon und dem networkmanager-Daemon oder einem anderen das Netzwerk startenden Service betrieben werden. Konkurrierende Services verursachen zwangsläufig Konflikte, wenn sie sich möglicherweise um die gleiche Hardware "streiten". Ich persönlich halte dhcpd und NWM sowieso für überflüssig, insofern werden diese Services hier immer sofort außer Betrieb genommen, und das bei mir mit der Deinstallation der Pakete wirklich kompromisslos. Das Problem ist allerdings recht einfach zu lösen, und auch ganz ohne das System grundsätzlich zu verändern oder gar Pakete deinstallieren zu müssen…. indem betroffene Services einfach maskiert werden. Die größte Schwierigkeit besteht allerdings darin vorher herauszufinden, wie das Netzwerk überhaupt gestartet wird. Es kann z.B. durch udev und via ifup gestartet werden, oder durch den Network-Manager, oder durch systemd-networkd, durch ein init.d-Script wie networking oder durch einen beliebigen anderen Netzwerk-Service. |
Selnic ist außerdem völlig ungeeignet, um es für Static-IP-Setups zu verwenden. Für diese Zwecke ist systemd-networkd oder networking oder der ifup-Service in Verbindung mit /etc network/interfaces viel besser geeignet. Ich habe selnic primär für unsere mobilen Systeme entwickelt, die sich unkompliziert an unterschiedlichen Orten der Welt mit einem mobilen Gerät an fremden Netzen verbinden sollen, um dann komfortabel via einer hergestellten OpenVPN-Verbindung auf die heimischen Ressourcen zugreifen zu können. Der Einsatzzweck ist deutlich auf den Betrieb unserer mobilen Laptops ausgerichtet, wobei die bestmögliche Unterstützung für mobile Flexibilität das primäre Ziel war, z.B. wenn sich...
- unsere Laptops zuhause an einem von 2 heimischen Accesspoints automatisch anmelden (den mit den besseren Signalwerten)
- ein Laptop abwechselnd zuhause oder im Caravan (oder in einer Zweitwohnung) anmeldet
- ein Laptop an wechselnden völlig fremden Accesspoints anmelden können soll
- ein Laptop in Ausnahmefällen einfach via Tethering am Smartphone anmeldet
Mit den folgenden Befehlen verschaffen wir uns einen Überblick, welche Services laufen oder aktiviert sind und wie der Symlink des Netzwerk-Interfaces lautet, hier in diesem Beispiel ist das enp1s0.
# systemctl -l | egrep -i "netw|ifup|dhcp" networking.service loaded active exited Raise network interfaces NetworkManager.service loaded active running Network Manager dhcpcd.service loaded active running LSB: IPv4 DHCP client with IPv4LL support ifup@enp1s0.service loaded active exited ifup for enp1s0 # find /etc -iname "*networking" -print /etc/rc0.d/K01networking /etc/rc6.d/K01networking /etc/rcS.d/S01networking /etc/default/networking /etc/init.d/networking # ip a | grep BROADCAST 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 |
Ich versuche also zuerst festzustellen, wie das Netzwerk wirklich gestartet wird. In diesem obigen Beispiel ist es der NetworkManager und das init.d-Script networking, die beide dann mit dem folgenden Beispiel-Befehlen maskiert werden. Das hat zur Folge, dass diese Services bei Systemstart nun nicht mehr gestartet werden. Dieses scheinbar komplizierte Vorgehen hat eine einfache Ursache, welches als Problem an dieser Stelle auch relativ einfach zu benennen ist: Es gibt bei Linux keine festen Regeln oder Vorgaben, wie das Netzwerk gestartet und verbunden wird. Insofern gibt es auch keine eindeutige Voraussage für ein Desktop-Environment, mit welchen Methoden die Netzwerk- Verbindung hergestellt wird wird. Das bedeutet, man muss einfach von System zu System genau hinschauen, wie auf diesem System die individuelle Implementierung vorgenommen wurde, und darauf wird dann passend reagiert.
Ich kontrolliere also für jeden Service explizit dessen Status, und wenn einer dieser Services tatsächlich aktiv ist, wird die entsprechende Service-Unit für den nächsten Systemstart deaktiviert. Achtung: Inaktive Dienste packen wir nicht an, nur laufende oder aktivierte Dienste.
# systemctl status ifup@enp1s0.service ● ifup@enp2s0.service - ifup for enp2s0 Loaded: loaded (/lib/systemd/system/ifup@.service; static; vendor preset: enabled) Active: active (exited) since Sat 2019-06-08 # systemctl mask ifup@enp1s0.service Created symlink /etc/systemd/system/ifup@enp1s0.service → /dev/null. |
# systemctl status networking.service ● networking.service - Raise network interfaces Loaded: loaded (/lib/systemd/system/networking.service; enabled; vendor preset: enabled) Active: active (exited) since Thu 2020-03-05 14:37:31 CET; 21s ago # systemctl mask networking.service Created symlink /etc/systemd/system/networking.service → /dev/null. |
# systemctl status NetworkManager.service ● NetworkManager.service - Network Manager Loaded: loaded (/lib/systemd/system/NetworkManager.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-06-08 # systemctl mask NetworkManager.service Created symlink /etc/systemd/system/NetworkManager.service → /dev/null. |
# systemctl status systemd-networkd ● systemd-networkd.service - Network Service Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-06-08 # systemctl mask systemd-networkd Created symlink /etc/systemd/system/systemd-networkd.service → /dev/null. |
# systemctl status dhcpcd.service ● dhcpcd.service - LSB: IPv4 DHCP client with IPv4LL support Loaded: loaded (/etc/init.d/dhcpcd; generated) Active: active (running) since Thu 2020-03-05 15:01:35 CET; 9min ago # systemctl mask dhcpcd.service Created symlink /etc/systemd/system/dhcpcd.service → /dev/null. |
# systemctl status wpa_supplicant.service ● wpa_supplicant.service - WPA supplicant Loaded: loaded (/lib/systemd/system/wpa_supplicant.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2020-03-05 15:01:35 CET; 9min ago) # systemctl mask wpa_supplicant.service Created symlink /etc/systemd/system/wpa_supplicant.service → /dev/null. |
# systemctl reboot # systemctl status networking systemd-networkd NetworkManager dhcpcd ifup@enp1s0 # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: enp1s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 52:54:00:85:69:7c brd ff:ff:ff:ff:ff:ff |
Wie im letzten Befehl „ip a“ erkennbar ist, ist der Rechner nach dem Neustart jetzt nicht mehr mit einem Netzwerk verbunden. Der Vorteil der Maskierung ist, dass man nicht an irgendwelchen Einstellungen herumexperimentieren muss, alles bleibt im Grunde genommen, wie es war.
Um beispielsweise networking.service oder den NetworkManager irgendwann wieder in Betrieb zu nehmen reicht es aus, einfach die Maskierung wieder zu entfernen. Ab dem nächsten Systemstart wird der entsprechende Dienst wieder ordentlich gestartet und stellt wie zuvor erneut die Netzwerkverbindungen her. Das gleiche gilt für alle anderen Services, die zuvor über die Maskierung deaktiviert wurden.
# systemctl unmask networking.service oder # systemctl unmask NetworkManager.service |
|
Einrichten für den System-Start mithilfe von Service-Units
Obwohl der primäre Verwendungszweck des Programms eigentlich auf die optimale Unterstützung bei häufig wechselnden WLAN-Verbindungen durch einen auf dem Desktop stattfindenden manuellen Start gerichtet ist, kann selnic trotzdem auch durch eine Service-Unit direkt bei Systemstart gestartet werden, um zuerst die Netzwerkverbindung herzustellen und sofern erwünscht, auch den Mount von Netzwerk-Laufwerken im Zusammenwirken mit mountctl@service durchführen.
Auf unseren Laptops enthält die Service-Unit allerdings immer nur den Aufruf selnic -f, die Mounts erfolgen zuhause und in Reichweite des heimischen WLAN-Netzwerks ganz unabhängig von selnic erst nach der User-Anmeldung, initiiert durch Pam-Login… ein Vorgehen, was im Artikel mountctl umfassend beschrieben ist. Es handelt sich hierbei um aufeinander abgestimmte und somit konfliktfreie Prozesse: Ist der heimische LAN-Server erreichbar, wird mountctl@.service durch den PAM-Login gestartet und beendet. Auf Reisen wird es hingegen über die selnic-Dialog-Oberfläche/Menü manuell gestartet und auch wieder beendet. Es ist aber trotzdem sichergestellt, dass der umount immer erfolgreich vor dem Trennen einer WLAN-Verbindung (z.B. beim Shutdown) durch den Befehl „selnic -x“ durchgeführt wird.
Nachfolgend hier einige Aufruf-Beispiele des Programms, sowohl direkt im Terminal als auch für das ExecStart-Statement in der systemd-Service-Unit selnic.service:
selnic -f | Parameter zum automatischen Verbinden bei Systemstart: 1. Öffnet das WLAN-NIC 2. Scannt die am Ort vorhandene WLAN-Netze 3. Überprüft, ob für eines der vorhandenen Netze eine WPA-Conf besteht 4. Verbindet bei Übereinstimmung das Netzwerkj |
selnic -a | Parameter zum automatischen Verbinden bei Systemstart: Verwende die im Dialog-Modus gespeicherten Verbindungsdaten, ohne Mounts |
selnic -a -u thomas | dto., wenn Mount-Option gespeichert war, dann die Mounts mit den User-Credentials des angegebenen Users durchführen. Gemäß dem Beispiel startet selnic die systemd-Unit mountctl@thomas.service |
selnic -c enp2s0 | Verbinde die Schnittstelle enp2s0 mit dem Router/Default-Gateway |
selnic -c enp2s0 -u thomas -m | dto., und Mounts mit den User-Credentials des angegeb. Users durchführen |
selnic -c Toms_WLAN_AP | Verbinde das Default-WLAN-NIC wlan0 mit dem AccessPoint Toms_WLAN_AP. Eine passende wpa_supplicant-Conf für den AP ist vorhanden. |
selnic -c Toms_WLAN_AP -w wl01c086 | Verbinde das WLAN-NIC wl01c086 mit dem AccessPoint Toms_WLAN_AP. Eine passende wpa_supplicant-Conf für den AP ist vorhanden. |
selnic -c Toms_WLAN_AP -w wl01c086 -u thomas -m | dto. und Mounts mit den User-Credentials des angegeb. Users durchführen |
selnic -t | Diesen Parameter nur bei manuell ausgeführten Befehl im Terminal verwenden. Öffnet ein Trace-Fenster zur Beobachtung der Verarbeitungsschritte des Programms. -t kann in Kombination mit allen anderen Verbindungsparametern zur laufenden Sichtkontrolle verwendet werden. Ergänzungsparameter für Trace: -k = Bei Ende auf EnterKey warten -h = Bei Ende Trace-Info-Datei nicht löschen (TraceFileName="/tmp/selnic_trace.$$") |
selnic -f -t | Manuell ausgeführter Befehl im Terminal für automatisches Verbinden mit einem bekannten und erreichbaren WLAN-AP. Funktioniert wie zuvor, aber mit Ausgabe von Trace-Informationen |
selnic -f -t -k | Wie zuvor, aber das Trace-Fenster erst nach Enter-Taste schließen |
selnic -f -t -k -h | Wie zuvor, aber die Trace-Infodatei bei Ende nicht löschen |
selnic -x | Schließt in richtiger Reihenfolge aktive Verbindungen: 1. mountctl@.service (sofern aktiv) 2. openvpn@.service (sofern aktiv) 3. Disconnect Network |
Anmerkungen:
Grundsätzlich funktioniert selnic auch ohne die hier erwähnte Einbindung von Remote-Mounts durch mountctl@.service. Die Unit mountctl@service plus dem dazugehörenden Programm ist ein Tool im Rahmen der hier bei uns eingerichteten System-Integration, die im Sinne der Anwender und für die Anwender arbeitet. Ist die Service-Unit vorhanden, kann sie durch selnic verwendet werden, ist sie nicht vorhanden, wird sie auch nicht beachtet und das Fehlen wird ignoriert.
Speziell die hier in den Beispielen gezeigte persistente mountctl-Einbindung in den automatisierten selnic-Start ist eigentlich für einen normalen und stationären Anwender-PC sowieso unnötig. Eine bessere Alternative wäre es bei solchen Gegebenheiten und sofern mountctl@.service überhaupt verwendet werden soll, diese Unit direkt zu enablen und in die Service-Unit allenfalls ein Requires- und After-Statement auf selnic einzufügen. Aber egal welchen Weg man wählt, beide Methoden haben den gleichen Nachteil, dass Mounts nicht mit individuell userbezogenen Rechten erfolgen, was ich unter Einbindung von PAM-Login als primäres Ziel ja umfassend im Artikel <mountctl> beschrieben habe. Bei beiden Alternativen werden die Mounts konstant mit den Rechten des immer gleichen Users durchgeführt. Eine userbezogene Anwendung von Rechten und darüber individuell durchgeführte Mounts halte ich hingegen immer für die beste Alternative. Warum unterstützt selnic dann diese Funktionen überhaupt? Weil es auch Situationen gibt, wo genau das sinnvoll ist, z.B. an Rechnern, an denen keine lokalen User-Anmeldungen erfolgen.
Wenn selnic direkt bei Systemstart regelmäßig die Netzwerkverbindung herstellen soll, muss natürlich die entsprechende Service-Unit aktiviert werden. Aber auch hier weise ich darauf hin, dass diese Beispiel-Service-Units nicht das Ziel haben, das Netzwerk für andere abhängige Prozesse herzustellen, sondern einfach am Ende des Boot-Prozesses ein Netzwerk zu verbinden. Das Ziel ist nicht, eine Server- oder Wichtige-Desktop-Funktionalität für Folgeprozesse zu garantieren, sondern eine Netzwerkverbindung unter einer On-The-Fly-Prämisse herzustellen, wie man das typischerweise auf Reisen vorfindet – mal hat man ein offenes Netz, ein anderes Mal nicht, manchmal braucht/will mans, manchmal nicht. Vor diesem Hintergrund muss die Sinnhaftigkeit der Units im Einzelfall bewertet werden. Die rot geschriebenen Parameter müssen aber trotzdem auf die eigenen lokalen Gegebenheiten angepasst werden:
Drei Beispiele für den Systemstart über eine Service-Unit:
# cat /etc/systemd/system/selnic.service [Unit] Description=thlu:selnic.service: Connect to Network (Wired or WLAN-SSID) After=multi-user.target Before=shutdown.target Wants=network.target Conflicts=shutdown.target
[Service] Type=simple Environment="TERM=xterm" RemainAfterExit=yes ExecStart=/usr/local/bin/selnic -f ExecStop=/usr/local/bin/selnic -x
[Install] WantedBy=graphical.target | Selnic versucht eine Verbindung automatisch herzustellen, in dem am aktuellen Ort zuerst die vorhandenen WLAN-Netze ermittelt werden, um dann zu prüfen, ob für die erreichbaren Netze eine passende wpa-supplicant-Conf vorhanden ist. Das ist hier für unsere eigenen Laptops mit 2 WLAN-Zugangspunkten die favorisierte Methode ... selnic sucht sich selber den AP mit der besten Sende-Leistung. |
| |
[Unit] Description=thlu:selnic.service: Connect to Network (Wired or WLAN-SSID) After=multi-user.target Before=shutdown.target Wants=network.target Conflicts=shutdown.target
[Service] Type=simple Environment="TERM=xterm" RemainAfterExit=yes ExecStart=/usr/local/bin/selnic -c enp1s0 ExecStop=/usr/local/bin/selnic -x
[Install] WantedBy=graphical.target | Selnic versucht über das angegebene Ethernet-Interface mit dem Symlink enp1s0 beim Systemstart automatisch eine Netzwerkverbindung herzustellen. |
| |
[Unit] Description=thlu:selnic.service: Connect to Network (Wired or WLAN-SSID) After=multi-user.target Before=shutdown.target Wants=network.target Conflicts=shutdown.target
[Service] Type=simple Environment="TERM=xterm" RemainAfterExit=yes ExecStart=/usr/local/bin/selnic -c Toms_WLAN_AP -w wl01c086 ExecStop=/usr/local/bin/selnic -x
[Install] WantedBy=graphical.target | Selnic versucht sich konstant bei jedem Systemstart mit dem angegebenen WLAN-Netzwerk auf dem angegebenen WLAN-Interface zu verbinden. Die Angabe des Interfaces ist nicht notwendig, wenn der Rechner nur ein Interface besitzt. |
| |
# systemctl enable selnic.service | Aktivieren der Service-Unit für den nächten Systemstart |
Hier abschließend noch ein Beispiel, um selnic an einer regulären Position in der Startreihenfolge der Services durch den System-Manager einzureihen, so das auch die Netzwerkverbindung innerhalb basic.target und vor multi-user.target erfolgt. Das sollte in etwa dem entsprechen, wie z.B. auch networking.service eingereiht ist. Soweit es allerdings auf solchen Mobil-Geräten meine persönlichen Anforderungen betrifft, bin ich da eher anspruchslos und verbinde das Netzwerk aus Bequemlichkeit einfach After=basic.target…. das passt meistens… und wenn der Startzeitpunkt völlig unkritisch ist, dann erfolgt der Start sogar erst After=multi-user.target wie in den oberen 3 Beispielen, um eigentlich alle Probleme von vornherein auszuschließen.
[Unit] Description=thlu:selnic.service: Connect to Network (Wired or WLAN-SSID) After=local-fs.target apparmor.service systemd-sysctl.service systemd-modules-load.service Before=network.target shutdown.target network-online.target Wants=network.target Conflicts=shutdown.target
[Service] Type=simple Environment="TERM=xterm" RemainAfterExit=yes ExecStart=/usr/local/bin/selnic -f ExecStop=/usr/local/bin/selnic -x
[Install] WantedBy=multi-user.target |
|
Überblick über die Abläufe bei Boot und Shutdown
Der Ablauf in der Boot-Phase ist wie folgt:
|
Sofern selnic durch eine Service-Unit bereits bei Systemstart gestartet wurde, beendet der systemd-Service-Manager natürlich auch wieder über selnic alle offenen Verbindungen, wenn der Rechner heruntergefahren wird. Hierzu ist eigentlich nichts weiter zu erklären, weil die Reihenfolge der Schritte automatisch dafür sorgt, dass alles konfliktfrei passiert. Zuerst werden die offenen Mounts getrennt, dann eine evtl. bestehende OpenVPN-Verbindung und erst am Ende wird auch das Netzwerk-Interface geschlosssen.
Als einzige Besonderheit wäre noch erwähnenswert, dass selnic beim Beenden der Service-Unit auch die Remote-Mounts schließt, die nicht über mountctl geöffnet wurden. Hier gilt einfach die Prämisse, das es keine offenen Netzwerk-Mounts mehr geben darf, wenn das Netzwerk-Interface geschlossen wird. Jeder nach dem Schließen des NICs noch offene Remote-Mount führt unweigerlich zu Hängern im System und zu den bekannten 90-sec-Stop-Jobs beim Shutdown. Sind auf dem System jedoch gleichzeitig aktive Verbindungen von mehreren NICs vorhanden, würden natürlich auch die über andere NICs geöffneten Netzwerk-Mounts geschlossen werden. In einem solchen Spezialfall wäre selnic dann das falsche Programm.
|
Im Grunde genommen gibt es zwei primäre Einsatzzwecke für selnic, bei denen es seine Stärken ausspielen kann. Zum einen ist es die automatische Verbindung plus dem konfliktfreien Mount und Unmount von Netzwerklaufwerken auf unseren Laptops im heimischen Netzwerk. Und zum zweiten ist es die selektive Verbindung an fremden Accesspoints auf Reisen plus manuellem Hinzuschalten einer OpenVPN-Verbindung und plus manuell hinzugefügten Mounts der heimischen Laufwerke. |
Die von mir persönlich am häufigsten verwendete Methode zum Start des Programms ist allerdings der manuelle Start im Vordergrund, entweder über einen Desktop-Starter oder direkt im Terminal. Das beinhaltet nämlich genau die Unterstützung, die ich auf Reisen bei täglich wechselnden Access-Points ständig benötige und für die selnic eigentlich entwickelt wurde.
Zum einfachen Herstellen und Trennen von Netzwerkverbindungen, um schnell eine OpenVPN-Verbindung nach Hause für sicheres Surfen über den heimischen DSL-Router zu öffnen und für die temporären Mounts der heimischen Samba-Shares ... das sind die von mir am häufigsten genutzten Funktionen.
|
|
Der Aufwand beim Herstellen einer Netzwerkverbindung an einem neuen und bisher unbekannten Accesspoint soll so gering wie möglich sein, und das ohne die Gefahr, dass sich selnic, wenn man sich später zufällig erneut am gleichen Ort aufhält, unbemerkt im Hintergrund erneut verbindet. Die Verbindungsdaten sind zwar gespeichert und können einfach über das Menü verwendet werden, aber eine Verbindung erfolgt auf Reisen nur auf meine ausdrückliche Anforderung. Die Anmeldung an fremden Accesspoints erfordert meiner Meinung nach sehr viel Umsicht bezogen auf die Sicherheit des eigenen Laptops.
|
Drei Beispiele für das zusätzlich geöffnete Tracefenster nach einem manuellen (!) Aufruf des Programms im Terminal. Das Tracefenster kann eine wichtige Hilfe beim Debugging einer eigenen Verbindung sein, wenn die bisherigen Verbindungsversuche fehlschlagen sind. Anhand des jeweiligen Prefix „Exec:“ in den entsprechenden Zeilen kann genau festgestellt werden, welche System-Befehle selnic zu welchem Zeitpunkt ausgeführt hat. Diese Befehle können dann einfach für eine vollständig manuelle Prüfung mit Einzelbefehlen im Terminal übernommen werden, um die primären Rückmeldungen des Systemprogramms unmittelbar zu sehen.
# selnic -c enp1s0 -t -k | (Automatisch via Patch-Kabel-Verbundenen Interface mit dem Netzwerk verbinden) |
xterm | |
Tracemode is on TraceOn(1) BASHPID=1579 TracePID=1601 TraceOn(2) TerminalApp=/usr/bin/xterm TraceFileName=/tmp/selnic_trace.1579 Init(1) Cmdline-Parm: -c enp1s0 -t -k Init(1) TempFileName=/tmp/selnic_answer.1579 SavedSettings= Init(1) AutoConnect=false AutoClose=false ConnectTo=enp1s0 Favorites=false Init(1) WlanIF=false WlanSW=0 WlanOK=false Init(1) CurrUser= GetDefinedInterfaces(1) identify existing interfaces GetDefinedInterfaces(2) Add enp1s0 Type=eth Status=off Count=0 GetDefinedInterfaces(3) Set PrimaryEthDevice to enp1s0 GetDefinedInterfaces(4) Set PrimaryWlanDevice to GetDefinedInterfaces(6) menuopt_count=2 iface_count=1 Main(2) Try autoconnect to=enp1s0 GetInterfaceStatus(1) 0: iface=enp1s0 is off Main(4) Connect to=enp1s0: found type=eth name=enp1s0 CheckSetInterfaces( 1) ChkBoxItemsSelected=0 CheckSetInterfaces( 9) Try to set enp1s0 up CheckSetInterfaces(10) 16:42:36 Exec: ip link set dev enp1s0 up CheckSetInterfaces(11) 16:42:39 Exec: dhclient -v enp1s0 CheckSetInterfaces(13) 16:42:43 Connect successful! enp1s0 IP=172.1.1.65 CheckSetInterfaces(14) /etc/systemd/system/network-is-connect.service not found AppExit(1) Selnic terminated with RC: 0 |
# selnic -f -t -k | (Automatisch mit einem bekannten WLAN-AP verbinden) |
xterm | |
Tracemode is on TraceOn(1) BASHPID=8308 TracePID=8333 TraceOn(2) TerminalApp=/usr/bin/xterm TraceFileName=/tmp/selnic_trace.8308 Init(1) Cmdline-Parm: -f -t -k Init(1) TempFileName=/tmp/selnic_answer.8308 SavedSettings= Init(1) AutoConnect=false AutoClose=false ConnectTo= Favorites=true Init(1) WlanIF=true WlanSW=0 WlanOK=true Init(1) CurrUser=thomas GetDefinedInterfaces(1) identify existing interfaces GetDefinedInterfaces(2) Add enp1s0 Type=eth Status=off Count=0 GetDefinedInterfaces(2) Add wlan0 Type=wlan Status=off Count=1 GetDefinedInterfaces(3) Set PrimaryEthDevice to enp1s0 GetDefinedInterfaces(4) Set PrimaryWlanDevice to wlan0 GetDefinedInterfaces(5) Add SSID=Toms_RP_AP Type=ssid Status=off Count=2 GetDefinedInterfaces(5) Add SSID=Toms_AP2 Type=ssid Status=off Count=3 GetDefinedInterfaces(5) Add SSID=Toms_AP Type=ssid Status=off Count=4 GetDefinedInterfaces(6) menuopt_count=9 iface_count=5 Main(6) Connect to favorite network? GetInterfaceStatus(1) 0: iface=enp1s0 is off GetInterfaceStatus(1) 1: iface=wlan0 is off CheckFavorites(1) Scanning for WISP with wlan0 CheckFavorites(2) Exec: ip link set dev wlan0 up CheckFavorites(3) Exec: iw dev wlan0 scan | grep -i 'ssid:\|signal:\|associated' CheckFavorites(4) Exec: ip link set dev wlan0 down CheckFavorites(5) Found SSID Toms_AP Main(2) Try autoconnect to=Toms_AP GetInterfaceStatus(1) 0: iface=enp1s0 is off GetInterfaceStatus(1) 1: iface=wlan0 is off Main(4) Connect to=Toms_AP: found type=ssid name=Toms_AP CheckSetInterfaces( 1) ChkBoxItemsSelected=4 CheckSetInterfaces( 9) Try to set Toms_AP up CheckSetInterfaces(19) set wlan0 up CheckSetInterfaces(20) Exec: ip link set dev wlan0 up CheckSetInterfaces(21) link wlan0 to wisp=Toms_AP CheckSetInterfaces(22) Exec: iw dev wlan0 scan | grep ssid: Toms_AP -i CheckSetInterfaces(24) Exec: wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/Toms_AP.conf CheckSetInterfaces(25) Exec: dhclient -v wlan0 CheckSetInterfaces(27) dhclient successful! (RC=0) IP = 172.100.1.38. AppExit(1) Selnic terminated with RC: 0 |
# selnic -t -n | (Aufruf im Dialog/GUI-Mode, um manuell nach WLAN-Netzen zu suchen) |
xterm | |
Tracemode is on TraceOn(1) BASHPID=6418 TracePID=6443 TraceOn(2) TerminalApp=/usr/bin/xterm TraceFileName=/tmp/selnic_trace.6418 Init(1) Cmdline-Parm: -t -n Init(1) TempFileName=/tmp/selnic_answer.6418 SavedSettings= Init(1) AutoConnect=false AutoClose=false ConnectTo= Favorites=false Init(1) WlanIF=true WlanSW=0 WlanOK=true Init(1) CurrUser=thomas GetDefinedInterfaces(1) identify existing interfaces GetDefinedInterfaces(2) Add enp1s0 Type=eth Status=off Count=0 GetDefinedInterfaces(2) Add wlan0 Type=wlan Status=off Count=1 GetDefinedInterfaces(3) Set PrimaryEthDevice to enp1s0 GetDefinedInterfaces(4) Set PrimaryWlanDevice to wlan0 GetDefinedInterfaces(5) Add SSID=Toms_RP_AP Type=ssid Status=off Count=2 GetDefinedInterfaces(5) Add SSID=Toms_CAR_AP Type=ssid Status=off Count=3 GetDefinedInterfaces(5) Add SSID=Toms_WLAN_AP Type=ssid Status=off Count=4 GetDefinedInterfaces(6) menuopt_count=9 iface_count=5 GetInterfaceStatus(1) 0: iface=enp1s0 is off GetInterfaceStatus(1) 1: iface=wlan0 is off MainMenu(1) Running Dialog-MainMenu CheckSetInterfaces( 1) ChkBoxItemsSelected=1 CheckSetInterfaces( 9) Try to set wlan0 up CheckSetInterfaces(10) 11:17:39 Exec: ip link set dev wlan0 up GetInterfaceStatus(1) 0: iface=enp1s0 is off GetInterfaceStatus(1) 1: iface=wlan0 is on CheckDoMounts(1) Check for mount/umount CheckDoVPN(1) Check for Connect/Disconnect OpenVPN-Session MainMenu(1) Running Dialog-MainMenu CheckSetInterfaces( 1) ChkBoxItemsSelected=1 L GetInterfaceStatus(1) 0: iface=enp1s0 is off GetInterfaceStatus(1) 1: iface=wlan0 is on CheckDoMounts(1) Check for mount/umount CheckDoVPN(1) Check for Connect/Disconnect OpenVPN-Session ListWisp(1) Scanning for WISP ListWisp(3) Exec: iw dev wlan0 scan | grep -i 'ssid:\|signal:\|associated' ListWisp(4) n=0 scan=wlan0 ssid=Vodafone0815 connected=off ListWisp(4) n=1 scan=wlan0 ssid=Toms_WLAN_AP connected=off ListWisp(4) n=2 scan=wlan0 ssid=Unitymedia WifiSpot connected=off ListWisp(4) n=3 scan=wlan0 ssid=gigacube-2D33 connected=off ListWisp(4) n=4 scan=wlan0 ssid=FRITZ!Box 7412 connected=off ListWisp(4) n=5 scan=wlan0 ssid=vodafone1235 connected=off ListWisp(4) n=6 scan=wlan0 ssid=DIRECT-06-HP_DeskJet connected=off ListWisp(4) n=7 scan=wlan0 ssid=FRITZ!Box 7430 IS connected=off ListWisp(4) n=8 scan=wlan0 ssid=Unitymedia WifiSpot connected=off ListWisp(4) n=9 scan=wlan0 ssid=Fritzbox 6490 Cable connected=off |
|
Anlegen einer neuen WLAN-Verbindung
Damit die beschriebenen Aufrufe und Funktionen auch genau in dieser Form bei einem ansonsten unprivilegiertem User funktionieren, ist es erforderlich, dafür eine Polkit-Regel zu erstellen. Eine funktionierende Regel ist im Tar-Archiv enthalten. Für eine für mich komfortable Handhabung im Terminal und zur automatischen Einbindung der Polkit-Regel habe ich den tatsächlichen selnic-Aufruf mit einem Alias versehen:
$ which pkexec
/usr/bin/pkexec
$ cat /home/thomas/.bash_aliases | grep selnic
alias selnic="/usr/bin/pkexec /usr/local/bin/selnic"
Der Aufruf des Programms via Desktop-Starter enthält dann dazu passend im Starter eine entsprechende Variante:
/usr/bin/pkexec selnic -n
Die folgenden Screen-Shots zeigen, mit wie wenigen Schritten ein neuer WLAN-Accesspoint ausgewählt und verbunden werden kann.
Bei Bedarf kann nach einer hergestellten Verbindung auch einfach über das Menü und manuell ausgewählt ein sicherer Tunnel via OpenVPN gestartet werden, und sofort steht mir eine sichere Leitung über meinen heimischen DSL-Router zur Verfügung. Voraussetzung ist natürlich, dass zuhause ein OpenVPN-Server eingerichtet ist und eine solche Verbindung überhaupt annehmen kann und das hier lokal auf dem Rechner OpenVPN und eine openvpn@service-Unit eingerichtet sind.
Die Einrichtung eines solchen OpenVPN-Servers habe ich in meinem Artikel < OpenVPN > umfassend beschrieben. Und wenn es notwendig ist, werden durch den Tunnel ebenfalls über das Menü einfach die heimischen Samba-Shares gemountet. Ganz am Ende sorgt die Menü-Auswahl "X dafür, dass alles in korrekter Reihenfolge beendet wird, ohne dass sich das System über falsche Reihenfolgen quasi minutenlang aufhängt.
|
Commandline-Parameter und Return-Codes
Abschließend erfolgt hier ein kurzer Überblick über die möglichen Aufrufparameter des Programms und die Fehlercodes bei Problemen, die sowohl im Terminal angezeigt als auch im Journal abgerufen werden können.
$ selnic -?
Usage:
selnic { -c SSID | -e ethnicname | -w wlannicname | -a | -f | -h | -m | -n | -k | -t | -u | -x | -? }
-c NIC/SSID = Connect to NIC/SSID Mit LAN oder AP verbinden ({AP}.conf ist vorhanden)
-e NIC = Set ETH-NIC Setze primäres Default-Interface für eth
-w NIC = Set WLAN-NIC Setze primäres Default-Interface für wlan
-u Username = Set current user User-credentials für mountctl@.service verwenden
-a = Automode start, no GUI Connect Network + Mounts und beenden
-f = Favorites Favorisiertes WLAN-Netzwerk erreichbar?
-h = Hold Trace-File bei Programmende nicht löschen
-m = Mount Mount Samba-Shares via mountctl@.service
-n = No Request Keine Frage Einstellungen speichern?
-k = Wait for Key Warte auf Tastendruck bei Exit im Trace-Mode
-t = Trace-Mode Trace-Fenster
-x = Automode stop, no GUI Umount + disconnect Network und beenden
-? = Help Zeigt diese Hilfe
Return-Codes:
0 = Keine Fehler
1 = Programm ip nicht gefunden
2 = Programm iw nicht gefunden
3 = Programm dhclient nicht gefunden
4 = Programm dialog nicht gefunden
5 = Programm wpa_supplicant nicht gefunden
6 = Netzwerk ist bereits verbunden
7 = SSID-wpa-conf nicht gefunden
8 = Netzwerk-Interface nicht gefunden
9 = AutoConnect durch selnic.conf fehlgeschlagen
|
Und schließlich noch ein paar Screen-Shots, die das Aussehen von selnic zeigen. Es ist kein grafisches Dialog-Interface, sondern ein rein textbezogenes. Die Prämisse war, dass das Programm natürlich auch auf Systemen ohne ein grafisches Deskop-Environment laufen können muss.
Selnic-Menü ohne die Service-Units:
- /etc/systemd/system/mountctl@.service
- /etc/systemd/system/openvpn@.service
und ohne WLAN-Adapter:
Selnic-Menü mit Service-Unit
- /etc/systemd/system/mountctl@.service
und ohne WLAN-Adapter:
Selnic-Menü mit Service-Units:
- /etc/systemd/system/mountctl@.service
- /etc/systemd/system/openvpn@.service
und ohne WLAN-Adapter:
Selnic-Menü mit Service-Units:
- /etc/systemd/system/mountctl@.service
- /etc/systemd/system/openvpn@.service
und mit WLAN-Adapter und 'bekannten' Accesspoints:
|
Abhängigkeiten, die für ein fehlerfreies Funktionieren von selnic erfüllt sein müssen:
dialog, iw, wpasupplicant, isc-dhcp-client, xterm
Optional integrierbare Lösungen:
Prüfen, ob die notwendigen Pakete bereits installiert sind:
# dpkg -l dialog iw wpasupplicant isc-dhcp-client xterm
||/ Name Version Architektur Beschreibung
+++-===============-==================-============-======================================================
ii dialog 1.3-20190211-1 amd64 Displays user-friendly dialog boxes from shell scripts
ii isc-dhcp-client 4.4.1-2 amd64 DHCP client for automatically obtaining an IP address
ii iw 5.0.1-1 amd64 tool for configuring Linux wireless devices
ii wpasupplicant 2:2.7+git20190128 amd64 client support for WPA and WPA2 (IEEE 802.11i)
ii xterm 344-1 amd64 X terminal emulator
Die fehlenden Pakete installieren (bereits vorhandene Pakete aus dem Befehl entfernen):
# apt update
# apt install iw wpasupplicant isc-dhcp-client xterm
Download des Tarfile-Archivs:
http://www.thlu.de/Public/selnic.tar
|
Die beiden folgenden Service-Units sind für die Nutzung von selnic nicht zwingend notwendig: - /etc/systemd/system/mountctl@.service - /etc/systemd/system/openvpn@.service Aber wenn sie installiert sind, ist Voraussetzung, dass auch die (bzw. eine alternative) mountctl-Infrastruktur installiert ist, wie sie im Artikel <mountctl> umfassend beschrieben ist. Ebenso ist Voraussetzung, dass OpenVPN installiert ist. Mit der Existenz dieser beiden Units würden diese auch in der selnic-Verarbeitung berücksichtigt und im Menü angezeigt werden. Zur interaktiven Anzeige der OpenVPN-Verbindung beim Start aus dem selnic-Menü ist es darüber hinaus noch notwendig, in den OpenVPN-Client-Conf-Files das Log in der Datei /var/run/openvpn/client.log zu aktivieren. Die OpenVPN-Client-Conf-Files werden im Verzeichnis /etc/openvpn erwartet und nur dort gesucht. | |
Wenn Selnic bereits im Boot-Prozess über eine Service-Unit gestartet werden und sofort auch Netzwerk-Mounts über die mountctl-Infrastruktur durchführen soll, so ist zwingend die Angabe des Usernamens erforderlich, unter dem die Mounts durchgeführt werden sollen. Das reguläre Verfahren ist, dass mountctl erst nach dem Login eines Users aktiv wird und zum Mount den Namen und die Credentials dieses Users verwendet. In der Boot-Phase ist jedoch kein Sambaberechtigter User bekannt. In dem Fall muss der User in der Service-Unit explizit angegeben werden, z.B.: mountctl@thomas.service Wenn mountctl@.service jedoch planmäßig von sessionctl und dann in der Folge von selnic im Vordergrund-Dialog gestartet wird, ist das nicht notwendig, weil in beiden Fällen durch sessionctl der angemeldete User bereits bekannt ist und von sessionctl automatisch eingefügt wird. Wenn die Funktionen mountctl und openvpn nicht verwendet werden und die entsprechenden Service-Units nicht vorhanden sind, findet im Programm auch keine weitere Berücksichtigung statt. Und ganz zum Schluß noch mal eine Wiederholung, damit es nicht übersehen wird: selnic kann nicht konfliktfrei gleichzeitig mit dem dhcpd-Daemon und dem networkmanager-Daemon oder anderen konkurrierenden Netzwerkprogrammen betrieben werden! |
|
Haftungsausschluss:
Das von mir geschriebene Programme selnic ist als Bash-Script nur ein Wrapper für verschiedene Linux-Programme. Das Programm selber verändert nicht das installierte Betriebssystem und schreibt/erstellt außer journald-Einträgen, Conf-Files in /etc/wpa_supplicant und Einstellungen in einer eigenen Conf in /usr/local/bin keine weiteren Daten.
Ich erhebe keinen Anspruch darauf, dass selnic vollständig fehlerfrei programmiert ist und ich behaupte das auch nicht. Sowohl durch Programmierfehler in meinen Code, wie auch durch vorhandene Fehler in den vom Programm verwendeten Linux-Programmen, sowie durch ggf. zeitgleich auftretende äußere mechanische Einflüsse, wie auch durch den Anwender selber verursacht durch Änderungen am Programm oder durch unsachgemäße oder fehlerhafte Bedienung des Programms oder falsche Parameterübergaben beim Aufruf des Programms ist Datenverlust möglich, wenn das laufende Programm wegen solcherart unsachgemäßer Manipulation nicht mehr Bestimmungsgemäß arbeitet.
Deshalb schließe ich jede Haftung für Schäden an Software oder Hardware oder Vermögensschäden oder für Datenverlust aus, die durch die Benutzung des Programms selnic enstehen. Die Benutzung des Programms erfolgt auf eigenes Risiko.
Datum Änderung
05.06.2019 | Version 2.2 |
| Grundlage der aktuellen Änderung ist der mit Debian-Buster neu etablierte /usr Merge-Support. Zitat: /{bin,sbin,lib}/ directories becoming symbolic links to /usr/{bin,sbin,lib}
- absolute Pfade entfernt, stattdessen PATH-Anweisung bei Programmstart: PATH=/usr/sbin:/usr/bin:$PATH - die primäre Unterstützung ist in der aktuellen Version auf Debian Buster ausgerichtet |
| Die Unterstützung von xfce-terminal und lxterminal für Trace-Fenster und OpenVPN-Trace ist eingestellt. Nur noch die grafischen Terminals {xterm | urxvt} werden unterstützt |
| Fehlerbehebung bei Systemstart: Auf einigen Systemen wurde das Kabel-NIC systemseitig kurz gestartet, ohne jedoch eine Netzwerkverbindung aufzubauen. selnic hat bei zufälligen Treffen auf diesen kurzen Zehntelsekunden-'Up-State' des NICs das Netzwerk als verbunden interpretiert, obwohl das NIC kurz danach wieder "down" war. Lösung: 5*1 Prüfsekunde zum Prüfen des Interface-Status 'Up-State' in der Bootphase eingefügt, zur Feststellung, ob es sich hier nur um ein temporäres Ereignis handelt. Auf die Dauer des Boot-Prozesses hat das keinen Einfluss. |
| Return-Codes für bestimmte Fehlersituationen gesetzt |
25.10.2019 | Version 2.3 |
| Bei über das Menü ad hoc geöffneten OpenVPN-Verbindungen wird für eine sichtbare Kontrolle über den Verbindungsaufbau ein Trace-Fenster geöffnet. Dieses Fenster wird nun beim Trennen der VPN-Verbindung vom Programm auch wieder geschlossen, was zuvor manuell durchgeführt werden musste. |
| Die Plausibilitätsprüfung auf Vorhandensein von wpa_supplicant wurde an das Vorhandensein einer WLAN-Schnittstelle gebunden. |
07.03.2020 | Version 3.0 |
| Erkennung der Network-Interfaces von einer Interpretation des Symlink-Namens auf Auswertung von /sys/class/net/ umgestellt. |
| Wirkungslose Code-Elemente entfernt, fehlendes String-Quoting ergänzt, semantische Korrekturen durchgeführt |
| Probleme bei der Erkennung von ‚unsauberen‘ SSIDs behoben, wie z.B. „Fritz!Box 6490 Cable“. Sonderzeichen und Blanks, sowie die Funktionen der History-Expansion könnten bei solch 4-teiligen (Fritz+Box+6490+Cable) Bezeichnungen unvorhersehbares Verhalten nach sich ziehen. |
| Funktion CheckFavorites() eingefügt. Die Funktion versucht mit einem bekannten WLAN-AP zu verbinden |
| Bugfixes |