Um Applikationen und Netzwerke über das Internet zu koppeln, bedarf es gesicherter Verbindungen. VPN-Setups sind häufig aufwendig und kompliziert. Dabei liefert ein simples Standardtool eigentlich schon alle Funktionen: SSH. Wir zeigen, wie Sie die Secure Shell unter Linux und Windows konfigurieren.
Die Secure Shell "SSH" ist für viele Admins ein alltägliches Werkzeug, um sich in entfernte Systeme einzuloggen. Doch SSH ist weit mehr als nur ein schlichtes Remote-Terminal. Über eine einzige verschlüsselte Verbindung lassen sich unsichere Protokolle tunneln, mehrere Zielsysteme ansprechen und ganze Netzwerke als VPN koppeln. Im diesem Workshop zeigen wir, wie Sie die vielen Features der Secure Shell im Alltag besser nutzen. Der OpenSSH-Server gehört dabei zu jedem Linux-Rollout und ist bei jeder Server-Distribution von Haus aus aktiv.
Sicherheit geht vor
Wenn Sie heute auf einer der bekannten Public-Cloud-Plattformen oder bei einem Co-Location-Service-Provider einen physischen oder virtuellen Server in Betrieb nehmen, dauert es in der Regel nur wenige Minuten, bevor Hacker versuchen, in dieses System einzudringen. Die externen IP-Adressen der Provider sind bekannt und automatisierte Bots scannen sie regelmäßig. Reagiert eine IP-Adresse auf einen Ping, versucht ein ebenfalls automatisierter Bot, sich sofort per SSH anzumelden. Dazu verwendet er ein Sammelsurium an geleakten und weit verbreiteten Kombinationen aus Benutzernamen und Passwörtern.
Die ersten zwei SSH-Server-Regeln lauten daher: Keine "root"-Logins und keine Passwörter. Nutzen Sie ausschließlich Schlüsselpaare, die Sie zuvor mit "ssh-keygen" erstellt haben, um Nutzer zu authentisieren. Der private Key verbleibt auf Ihrer Arbeitsstation, der öffentliche landet im Zielsystem in der Datei "/home/ <username>/.ssh/authenticated_keys". Die passenden Konfigurationszeilen in der Datei /etc/ssh/sshd_config lauten:
Die Secure Shell "SSH" ist für viele Admins ein alltägliches Werkzeug, um sich in entfernte Systeme einzuloggen. Doch SSH ist weit mehr als nur ein schlichtes Remote-Terminal. Über eine einzige verschlüsselte Verbindung lassen sich unsichere Protokolle tunneln, mehrere Zielsysteme ansprechen und ganze Netzwerke als VPN koppeln. Im diesem Workshop zeigen wir, wie Sie die vielen Features der Secure Shell im Alltag besser nutzen. Der OpenSSH-Server gehört dabei zu jedem Linux-Rollout und ist bei jeder Server-Distribution von Haus aus aktiv.
Sicherheit geht vor
Wenn Sie heute auf einer der bekannten Public-Cloud-Plattformen oder bei einem Co-Location-Service-Provider einen physischen oder virtuellen Server in Betrieb nehmen, dauert es in der Regel nur wenige Minuten, bevor Hacker versuchen, in dieses System einzudringen. Die externen IP-Adressen der Provider sind bekannt und automatisierte Bots scannen sie regelmäßig. Reagiert eine IP-Adresse auf einen Ping, versucht ein ebenfalls automatisierter Bot, sich sofort per SSH anzumelden. Dazu verwendet er ein Sammelsurium an geleakten und weit verbreiteten Kombinationen aus Benutzernamen und Passwörtern.
Die ersten zwei SSH-Server-Regeln lauten daher: Keine "root"-Logins und keine Passwörter. Nutzen Sie ausschließlich Schlüsselpaare, die Sie zuvor mit "ssh-keygen" erstellt haben, um Nutzer zu authentisieren. Der private Key verbleibt auf Ihrer Arbeitsstation, der öffentliche landet im Zielsystem in der Datei "/home/ <username>/.ssh/authenticated_keys". Die passenden Konfigurationszeilen in der Datei /etc/ssh/sshd_config lauten:
PermitRootLogin no
PasswordAuthentication no
Noch besser ist es natürlich, wenn Ihre Zielsysteme Teil eines Benutzerverzeichnisses wie FreeIPA sind und die Schlüssel über den Verzeichnisserver erhalten. Bei abgeschalteter Passwortauthentisierung können Sie die vielen Log-Einträge Ihres SSH-Servers über gescheiterte Anmeldeversuche ignorieren. Alternativ setzen Sie Fail2Ban ein, um die störenden Quell-IP-Adressen zu blockieren.
Sie halten die Hacker ebenfalls vom System fern, wenn Sie eine andere Portnummer als 22 für die SSH-Verbindung verwenden. Suchen Sie sich einen Port zwischen 1024 und 65.535 aus, der nach Möglichkeit nicht von einem Standarddienst verwendet wird [1]. Die Botnetze haben schlicht und ergreifend keine Zeit, um bei allen möglichen Zielsystemen einen umfassenden Portscan durchzuführen und den SSH-Zugang so aufzuspüren. Zudem erkennen und blockieren viele Provider Portscanner auf ihren Netzwerken.
Oftmals trauen sich Administratoren nicht, den SSH-Daemon auf einem Zielsystem umzukonfigurieren, während sie aktiv damit verbunden sind. OpenSSH hat dafür aber einen Trick auf Lager: Wenn Sie sshd neu laden, um eine Konfigurationsänderung umzusetzen, bleiben bestehende Verbindungen unverändert erhalten, bis Sie diese trennen. SSH-Ports ändern sie in zwei Schritten: Zuerst geben Sie beide Ports in der Konfiguration an:
Port 22
Port 41424
und konfigurieren die Firewall des Zielsystems entsprechend, sodass Port 41424 offen steht. Dann starten Sie den sshd-Dienst neu und verbinden ihren Client in einer zweiten Sitzung über den neuen Port. Wenn das klappt, entfernen Sie Port 22 aus der "sshd_config" und der Firewallkonfiguration. Natürlich möchten Sie nicht jedes Mal eine lange Portadresse auf der SSH-Kommandozeile eingeben. An dieser Stelle kommen nun Client-Konfigurationsdateien zum Einsatz.
Eine Konfiguration für alle Fälle
Der SSH-Client unterstützt neben der Portangabe natürlich eine Vielzahl von Parametern, die Sie aber nicht immer mit eintippen möchten. Hier helfen eine oder mehrere Config-Dateien. Prinzipiell genügt eine Datei "config" im Verzeichnis "/home/<username>/.ssh/". Dort tragen Sie die Parameter für Ihre Verbindungen ein, beispielsweise:
Host srv1
User srv1admin
HostName server01.viel.zu.lange.url.org
Port 41424
Das Schlüsselwort "Host" gibt hier den "Alias" der Verbindung an, gefolgt von den Parametern. Ohne die Config-Datei müssten Sie für die SSH-Verbindung die folgende Zeile eintippen:
Mit dem Config-Eintrag genügt dann ein simples ssh srv1. Dem Servereintrag können weitere Parameter folgen wie beispielsweise ServerAliveInterval 180. Fließen über einen längeren Zeitraum keine Daten über die SSH-Verbindung, terminieren aktive Netzwerkkomponenten im Verbindungspfad eventuell die Sitzung. In solchen Fällen erhalten Sie häufig die Fehlermeldung "Broken Pipe". Das ServerAliveInterval 180 sorgt dafür, dass der Client alle drei Minuten ein Nullbyte übermittelt. Das genügt in der Regel, um die Verbindung offen zu halten.
Auf diese Art können Sie mehrere Server in der Config eintragen. Das wird mit der Zeit aber unübersichtlich und funktioniert auch nur auf einem Client. Ein praktischer Tipp dafür: Legen Sie für jede Verbindung eine eigene Konfigurationsdatei unterhalb des ".ssh-"Verzeichnisses an, beispielsweise in "~/.ssh/config.d". Schreiben Sie dann in die Datei "~/.ssh/config" folgende Zeile:
Include config.d/*.config
Der SSH-Client wird dann alle config-Dateien des Verzeichnisses berücksichtigen. Das komplette "config.d"-Verzeichnis packen Sie nun in ein privates Git-Repository. So halten Sie Ihre SSH-Einstellungen bequem auf mehreren Client-PCs synchron.
SSH huckepack
SSH funktioniert nicht nur als Standalone-Tool. Andere Werkzeuge, beispielsweise für den Filetransfer, integrieren SSH, um deren eigenen unsicheren Protokolle zu verschlüsseln. Ein simples Beispiel hierfür ist SCP, das Binärdateien mit dem SSH-Protokoll überträgt. Ebenso können etablierte, aber unsichere File-Transfer-Protokolle wie FTP die Verschlüsselung von SSH nutzen und damit sichere Varianten wie SFTP anbieten. Für größere Dateitransfers und Remote-Backups ist vor allem das Tool "rsync" von den Machern des "samba"-Fileservers interessant. Es gleicht zwei Verzeichnisse differenziell ab und kopiert nur Änderungen. Windows-Admins erhalten etwa mit dem Tool "robocopy" eine ähnliche Funktionalität. Rsync tunnelt seine Filetransfers mithilfe einer simplen Kommandozeilenoption via SSH. Der Befehl
rsync -avx -e ssh /eins user@server:/zwei
kopiert die Differenzen des lokalen Verzeichnisses "/eins" zum Verzeichnis "/zwei" auf dem Remote-Server und tunnelt dabei das eigene Rsync-Protokoll über eine SSH-Verbindung. Natürlich kann als Zielangabe auch ein Alias aus der ".ss/config" stehen:
rsync -avx -e ssh /eins srv1:/zwei
Bild 1: Schematische Darstellung eines Layer-2-VPN mit SSH. Der Tunnel verbindet die Tap-Interfaces, somit erscheinen die Bridges auf beiden Seiten der Verbindung wie ein einzelner Switch.
Tunnelbauer
Wie erwähnt, kann SSH über eine bestehende Verbindung weitere Protokolle tunneln. Anwender müssen sich damit nicht mehr um die individuelle Absicherung einzelner Dienste kümmern. Ein praktisches Beispiel: Sie betreiben einen Re-
mote-Host bei einem Provider. Auf diesem arbeiten verschiedene Internetdienste in virtuellen Maschinen. Um die Umgebung zu überwachen, sammeln Sie Telemetriedaten via Telegraf und Influx und stellen sie in einem Grafana-Dashboard dar. Dieses ist nur für die Admins von Interesse, also gibt es keinen offenen Internetzugang dazu. Fügen Sie in die SSH-Konfiguration des Servers einfach folgende Zeile ein:
LocalForward 3030 127.0.0.1:3000
Der SSH-Client wird dann Zugriffe auf den Port 3030 am Client-PC durch den SSH-Tunnel senden und auf der Seite des SSH-Servers an die Adresse 127.0.0.1: 3000 übermitteln – also an das Grafana-Dashboard. Um dieses nutzen zu können, geben Sie auf Ihrem PC lediglich "ssh srv1" ein und öffnen dann das Dashboard in Ihrem Browser über die URL "http://localhost:3030". Das Praktische daran: SSH beschränkt diese Weiterleitung nicht auf den Host mit dem SSH-Serverdienst. Läuft der Grafana-Dienst beispielsweise nicht auf dem physischen Remote-Host, sondern in einer virtuellen Maschine auf dem Host mit der internen IP-Adresse 192.168.122.23, kann der Config-Eintrag wie folgt aussehen, wobei die Funktion auch mehrere Tunnel erlaubt:
LocalForward 3030 192.168.122.23:3000
LocalForward 10091 192.168.122.23:9090
LocalForward 10092 192.168.122.24:9090
LocalForward 10093 192.168.122.25:9090
In diesem Beispiel arbeiten auf dem Zielhost drei Linux-VMs mit dem Admin-Interface auf Port 9090. Auf dem SSH-Client können Sie diese dann via "https://localhost:10091" bis 10093 einzeln steuern. Sehr praktisch ist diese Funktion im Übrigen im Zusammenspiel mit VNC. Verschiedene VNC-Clients integrieren dabei gleich die Funktion eines SSH-Tunnels, sodass Sie gar nicht erst separat eine SSH-Sitzung öffnen müssen. Oft kommt die Tunnelfunktion auf sogenannten "Bastion Hosts" zum Einsatz. Hier gibt es keine direkte Verbindung zwischen dem Client- und dem Zielnetzwerk. Lediglich ein "Jump"- oder "Bastion"-Host kann mit beiden kommunizieren. Dieser könnte dann auch als Proxy fungieren und SSH-Verbindungen ins isolierte Netzwerk weiterleiten.
Host bastion
Hostname <extern ansprechbare IP-Adresse>
Host isolated
Hostname <IP-Adresse im internen Netz, zu der der Bastion-Host Zugriff hat>
ProxyJump bastion
Geben Sie bei einer solchen Konfiguration dann "ssh isolated" ein, wird SSH die Verbindung mit dem Umweg über den "bastion" aufbauen.
Bild 2: Die zweite Bridge benötigt eine andere IP-Adresse als den Default ".1", sonst kommt es zu IP-Adresskonflikten, wenn das SSH-VPN die Bridges verbindet.
Layer-2-VPN via SSH
Via SSH lassen sich nicht nur einzelne Port-und IP-Zugriffe weiterleiten, sondern auch komplette Netzwerke. Das braucht dann weder eine komplexe VPN-Konfiguration noch root-Zugriffsrechte – von den Vorereitungen abgesehen. Dafür erstellen Sie als root zunächst auf dem Quell- und dem Zielsystem ein sogenanntes Tap-Interface und schließen dieses jeweils an einer Netzwerk-Bridge an. Der SSH-Tunnel verbindet beide Tap-Interfaces später, sodass die an beiden Bridges angebundenen VMs oder Container miteinander kommunizieren können, als wären sie in einem lokalen LAN verbunden. Das Tap-Interface leitet dabei alle Ethernet-Frames weiter (Layer 2), nicht nur IP-Pakete (Layer 3).
Ein praktisches Beispiel dazu: Auf einem gemieteten Server eines Internet-Providers laufen mehrere VMs und Podman-Container. Alle sind an dessen Bridge "virbr0" angebunden und setzen IP-Adressen aus dem LAN-Segment 172.27.55.0/24 ein. Zugang zum Internet erhalten diese via NAT und das externe Interface "eth0" des Servers. Auf diesem Server konfigurieren Sie den SSH-Daemon zunächst so, dass dieser Netzwerktunnel zulässt. Dazu muss in der Datei "/etc/ssh/sshd_config" folgende Zeile stehen: "PermitTunnel yesBeispiel laufen auf dem Zielserver virtuelle Maschinen mit KVM. Dessen Management-Daemon "libvirtd" hat für diese VMs ein passendes virtuelles Netzwerk mit Bridge erstellt. Die Netwerkdefinition liegt in der Datei "one.xml" unter "/etc/libvirt/ qemu/ networks" und sieht in etwa so aus:
Der Abschnitt "forward" gibt dabei an, dass die VMs via NAT Zugang zum Internet erhalten.
Auf dem Quellsystem, einem Server im lokalen Datacenter, erstellen Sie via virsh net-create oder über den grafischen Virt-Manager nun ein ähnliches Netzwerk, mit dem Unterschied, dass Sie dieses als "Host-Only" – also ohne die NAT-Route und ohne DHCP-Dienst – definieren. In unserem Beispiel gibt es auf dem Quellsystem bereits das übliche Standard-KVM-Netzwerk 192.268.122.0/24 auf "virbr0". Das neue Host-Only-Netzwerk nutzt daher die Bridge "virbr1".
Erstellen Sie das Netzwerk in der UI des Virt-Managers, müssen Sie dazu in die XML-Ansicht wechseln und die IP-Adresse korrigieren. Der reguläre Dialog fragt nämlich nur die Netzwerkadresse ab und weist der Bridge dann automatisch die ".1"-IP-Adresse zu. Diese nutzt aber schon der Remote-Node, weswegen wir eine andere Adresse wie hier ".199" verwenden. Auf beiden Systemen erstellen Sie dann das tap-Interface "tap5" und binden es an die jeweilige Bridge an:
ip tuntap add mode tap tap5
brctl addif virbr0 tap5
ifconfig tap5 up
Geben Sie dabei auf dem Client in der "brctl"-Zeile als Bridge "virbr1" anstatt "virbr0" an. Im Anschluss genügt es, wenn Sie vom Server im Datacenter aus eine SSH-Verbindung mit folgenden Parametern starten:
ssh -o Tunnel=ethernet -w 5:5 -t <user@remote>
Der Parameter "-o Tunnel=ethernet" legt fest, dass Sie einen Layer-2-Tunnel aufbauen, während "-w" die Nummern der Tap-Interfaces (tap5 auf der Quelle und tap5 auf dem Ziel) angibt. Weder Quell- noch Zielbenutzer brauchen dafür root-Rechte. Die Konfiguration lässt sich natürlich mit einer wie zuvor beschriebenen Konfigurationsdatei "/home/<user>/.ssh/ config.d/tunnel.conf" vereinfachen:
Host tunnel
User user
Hostname remote.server.name
Port 54312
ServerAliveInterval 180
Tunnel ethernet
TunnelDevice 5:5
Dann genügt ein schlichtes ssh tunnel. Sobald der Tunnel steht, können Sie von der Bridge-IP-Adresse des lokalen Servers (172.27.55.199) auf alle VMs und Container des Provider-Servers und natürlich auf den Host (172.27.55.1) selbst zugreifen. Erstellen Sie nun auf dem lokalen System eine VM mit Anbindung an die "virbr1"-Bridge, erhält sie vom entfernten libvirt-Dienst eine IP-Adresse aus dem Segment 172.27.55.x und leitet auch all ihren Internet-Traffic via Tunnel zum Server beim Provider.
Praktische Einsatzgebiete
Das SSH-Tunnel-VPN leistet im Alltag gute Dienste, gerade weil es den angebundenen VMs und Containern ein "flaches" Netzwerk vorgaukelt. Da der Tunnel vom Datacenter aus zum Provider-Server aufgebaut wird, bedarf es keiner Firewall und Forwarding-Regeln in das lokale Datacenter. Die Quelle benötigt zudem keine statische IPv4-Adresse. Ändert der Provider die Verbindung, bauen Sie das VPN einfach neu auf. Da der Tunnel via IPv6 genauso funktioniert, kommt das Quellnetzwerk sogar ohne IPv4-Adresse aus.
Mit der Methode betreiben Sie beispielsweise einen Webauftritt bei einem Provider. Die dabei häufig genutzte MySQL-Datenbank spiegeln Sie einfach mittels MySQL-Replikation auf einen zweiten Server, der auf der anderen Seite des VPN im Datacenter als VM oder Container läuft. Genauso lassen Sie Remote-Systeme einfach Backups auf NFS-Freigaben schreiben, die im lokalen Datacenter liegen.
Je nach Konfiguration halten Sie dabei den Tunnel permanent geöffnet oder bauen ihn nur für Wartungsarbeiten auf. Der einzige Nachteil dieser Methode liegt darin, dass das Terminal mit dem SSH-Kommando geöffnet bleiben muss. Die Verbindung schließt sich natürlich, wenn es zu Aussetzern kommt. Daher starten Sie sie mit einem simplen "loop-forever"-Bash-Skript:
While true: do
ssh tunnel
echo "Verbindung unterbrochen. Wiederaufbau in 60 Sekunden"
sleep 60
done
sshd für Windows
Natürlich können Sie auch Windows-Server via SSH ansprechen. Dazu installieren Sie einfach das OpenSSH-Paket für Windows via "Settings / Apps / Optional features", per Chocolatey-Paketmanager oder von der Github-Seite "https://github.com/PowerShell/Win32-OpenSSH/releases". Alle drei Installationsvarianten bringen ein PowerShell-Skript mit, das sshd als Systemdienst registriert. Aktivieren Sie den Dienst und legen Sie eine passende Firewallregel für die Applikation "<Pfad>\sshd.exe" an. Die Konfigurationsdatei liest "sshd.exe" standardmäßig aus der Datei "%programdata%\ssh\sshd_config".
Legen Sie im Verzeichnis des Nutzers, der sich via SSH anmelden darf, dessen Public Key ab, beispielsweise in "C:\ users\<Nutzername>\.ssh\authorized_eys". Jetzt kann sich der Nutzer per SSH ohne Passwort am Windows-System anmelden, landet dort aber auf der regulären Kommandozeile "cmd.exe". In der Regel bevorzugen Windows-Admins jedoch die PowerShell. Das können Sie in der Regsitry unter dem folgenden Schlüssel anpassen:
HKEY_LOCAL_MACHINE\SOFTWARE\OpenSSH
Generieren Sie nun einen Key "DefaultShell" mit der vollen Pfadangabe zur PowerShell, beispielsweise: "C:\Program Files\PowerShell\7\pwsh.exe". Der Schlüssel sollte lediglich die EXE-Datei enthalten. Kommandozeilenparameter, falls benötigt, legen Sie in einem separaten Key fest:
Die Automatisierungsplattform Ansible führt Playbooks auf Windows-Zielsystemen via SSH (mit der angegebenen Konfiguration) übrigens deutlich schneller aus, als wenn Sie WinRM oder WinPSRP verwenden.
Fazit
Die Secure Shell ist so etwas wie das Schweizer Taschenmesser für gesicherte Internetverbindungen und damit weit mehr als eine simple Remote-Kommandozeile. Dank der Tunnelfunktionen müssen sich Admins nicht abmühen und alle in einem hybriden Netzwerkverbund verwendeten Applikationsprotokolle einzeln absichern. Oftmals genügt eine SSH-Verbindung, die alle darüber laufenden Protokolle schützt. Der Umgang mit SSH gestaltet sich dabei sogar deutlich einfacher als mit den meisten offenen oder proprietären VPN-Produkten.