Remote Management über SSH-Tunnel

Management von IT-Komponenten über einen SSH-Tunnel von beliebigen Lokationen aus

Motivation

Über das Internet können Management, Support und Wartung von IT-Systemen jederzeit und unabhängig vom Standort durchgeführt werden. Das spart Zeit und Kosten. Aus diesem Grund wurden spezielle Fernwartungstools wie z.B. TeamViewer oder ISL Online entwickelt. Gegen deren Einsatz sprechen aber evtl. Sicherheitsbedenken, Funktionalität auf weniger verbreiteten Betriebssystemen oder auch die Kosten. Eine Alternative wird im Folgenden vorgestellt.

Funktionsprinzip

Um auf ein internes IT-System (im Firmennetz oder zuhause) von außerhalb zuzugreifen, gibt es verschiedene Möglichkeiten. Dazu gehören die o.g. Fernwartungstools oder auch ein VPN. Alle erstellen einen abgesicherten Tunnel, über welchen die Daten übertragen werden. Auch die hier beschriebene Lösung nutzt einen Tunnel, und zwar einen über das SSH-Protokoll. Ein von außen (über das Internet) initiierter Zugriff würde ein Öffnen der Firewall erfordern und ist daher meist nicht gewünscht. Deswegen baut, so wie das andere Fernwartungstools auch machen, das zu managende Zielsystem selbst aktiv eine Verbindung zu einem Gateway im Internet auf. Auf diesem Gateway muß lediglich ein SSH-Server laufen, was bei den meisten üblichen Linux-Distributionen der Standard ist.

Der Supporter baut mit seinem Support-Client selbst auch einen SSH-Tunnel zum Gateway auf und hat darüber dann Zugriff auf das zu managende Zielsystem.

Sicherheitsbetrachtungen

Es wird ein Tunnel durch die Firewall gebohrt, welche das Netzwerk mit dem Zielsystem schützt. Das schafft definitiv neue Angriffsmöglichkeiten auf das Netzwerk. Hier muß man, wie bei allen Fernwartungszugängen, zwischen dem Komfortgewinn und dem Sicherheitsverlust abwägen.

Ein potentieller Angreifer müßte Zugriff auf das Gateway erlangen und könnte von dort alle zu managenden Zielsysteme erreichen. Das Zielsystem und das dahinter liegende Netzwerk ist dann nur noch durch die Sicherheitsmechanismen geschützt, welche die über den Tunnel errreichbare Anwendung auf dem Zielsystem bietet (z.B. SSH- oder Webserver).

Es ist also zum einen wichtig, das Gateway gut abzusichern. Das ist gar nicht so anspruchsvoll, weil es sich beim Gateway um ein Minimalsystem handelt, welches vergleichsweise einfach upgedatet und sicher konfiguriert werden kann. Zum anderen sollten auch auf dem Zielsystem die üblichen Sicherheitsmaßnahmen durchgeführt werden (laufende Updates, sichere Paßwörter usw.). Insgesamt ist bei Einhaltung dieser Maßnahmen die Sicherheit im Vergleich zu anderen Varianten (proprietäre Fernwartungstools, Port-Forwarding durch Firewalls) als höher einzuschätzen.

Parameter

Als Beispiel für diese Anleitung werden folgende Parameter angenommen:

  • Allgemein:

    • Linux-Systeme: getestet mit Gentoo Linux und OpenSSH, sollte aber sinngemäß mit jeder Distribution oder auch mit *BSD funktionieren
  • Gateway:

    • Hostname: gateway.example.de
    • Benutzer, unter welchem die Tunnel erstellt werden: sshtunnel
  • zu managendes Gerät:

    • Hostname: mgmtdest.example.de
    • Benutzer, unter welchem die Tunnel erstellt werden: support

Konfiguration

Gateway

Als Gateway kann ein beliebiger Linux-Server im Internet dienen. Ein SSH-Server wird dort bereits aktiv sein. Für den Tunnel-Aufbau wird ein separater User angelegt:

root@gateway# useradd -m -G users -s /bin/bash sshtunnel

Die Supporter sollten nun unter diesem User ihren SSH-Key hinterlegen, um sich nicht jedesmal mit Paßwort authentifizieren zu müssen. Außerdem sollte die paßwortbasierte Authentifizierung am SSH-Server abgeschaltet werden.

Zielsystem Linux

Für den Tunnelaufbau zum Gateway wird ein separater User verwendet:

root@mgmtdest# useradd -m -G users -s /bin/bash support

Nach Login als dieser neue User wird ein SSH-Key für den Tunnel erzeugt (als Name wird im Beispiel der FQDN des Gateways genutzt, das ist aber nicht zwingend):

root@mgmtdest# sudo -u support -i
support@mgmtdest$ ssh-keygen -f ~/.ssh/gateway.example.de -t ecdsa

Eine Passphrase wird nicht verwendet (nur Enter drücken).

Der öffentliche Schlüssel muß nun auf dem Gateway der Datei ~/.ssh/authorized_keys des Tunnel-Users hinzugefügt werden. Angezeigt werden kann der Schlüssel mittels:

support@mgmtdest$ cat ~/.ssh/gateway.example.de.pub
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGFrouMZKE6ozpWLj+xH3mONc6LWL3ZbnFbpL7sMKAjMSiTlBzek0doEHrh9VvTmKce4pmHK9ilkI4ILFw7t+sk= support@mgmtdest

Auf dem Gateway wird als der dortige Tunnel-User der Schlüssel wie folgt eingefügt:

sshtunnel@gateway$ echo command=\"\",no-pty ecdsa-sha2-nistp256 \
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBB\
GFrouMZKE6ozpWLj+xH3mONc6LWL3ZbnFbpL7sMKAjMSiTlBzek0doE\
Hrh9VvTmKce4pmHK9ilkI4ILFw7t+sk= \
support@mgmtdest \
>>~/.ssh/authorized_keys

Durch das Voranstellen von command="",no-pty kann ein User mit diesem Key auf dem Gateway kein Kommando ausführen und kein Terminal öffnen.

Zurück auf dem Zielsystem wird nun zum Test und zur Aufnahme als "known host" eine SSH-Verbindung zum Gateway aufgebaut:

support@mgmtdest$ ssh -i ~/.ssh/gateway.example.de sshtunnel@gateway.example.de

Nach Vergleich des angezeigten Fingerprints und Bestätigung durch Eingabe von "yes" erscheint eine Fehlermeldung "PTY allocation request failed on channel 0" und die Verbindung wird wieder abgebrochen. Das ist so gewollt.

Der Tunnel kann nun mit folgendem Kommando aufgebaut werden:

ssh -NTC\
 -o ServerAliveInterval=60
 -o ExitOnForwardFailure=yes
 -o StrictHostKeyChecking=no\
 -i ${SSHKEY}
 -R ${GWPORT}:localhost:${LOCALPORT}\
 ${GWUSER}@${GWHOST}

Durch den Parameter "-R" wird ein reverse Tunnel erstellt, denn es soll ja aus Richtung Gateway auf das Zielsystem zugegriffen werden können. Die verwendeten Variablen haben folgende Bedeutung:

  • ${SSHKEY}: der komplette Pfad zum SSH-Key, z.B. ~/.ssh/gateway.example.de
  • ${GWPORT}: Der Port, welcher auf dem Gateway für den Tunnel verwendet wird. Diesen muß man dort ansprechen, um sich mit dem Zielsystem zu verbinden. Werden mehrere Tunnel zum Gateway aufgebaut (was recht wahrscheinlich ist), muß natürlich für jeden ein anderer Port verwendet werden. Da zum Tunnelaufbau normale User (nicht root) genutzt werden, können nur Ports über 1024 verwendet werden.
  • ${LOCALPORT}: Das ist der Port, mit welchem der Tunnel auf dem Zielsystem verbunden wird. Soll über den Tunnel eine SSH-Sitzung aufgebaut werden, nimmt man den Port 22. Läuft auf dem Zielsystem ein Webserver und dieser soll über den Tunnel erreichbar sein, wird Port 443 genommen (für verschlüsselte Seiten).
  • ${GWUSER}: Der User auf dem Gateway. In unserem Beispiel also "sshtunnel".
  • ${GWHOST}: Der Hostname des Gateways, also z.B. "gateway.example.de".

Soll der Tunnel automatisch beim Booten gestartet werden, erstellen wir für Systemd-Systeme eine passende Service-Unit:

/etc/systemd/system/ssh-reverse@.service

[Unit]
Description=Reverse SSH Tunnel Service
ConditionPathExists=|/usr/bin
After=network.target

[Service]
User=support
Environment="GWPORT=40%I"
Environment="GWUSER=sshtunnel"
Environment="GWHOST=gateway.example.de"
Environment="SSHKEY=/home/support/.ssh/gateway.example.de"
ExecStart=/usr/bin/ssh -NTC -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -i ${SSHKEY} -R ${GWPORT}:localhost:%I ${GWUSER}@${GWHOST}

# Restart every >2 seconds to avoid StartLimitInterval failure
RestartSec=3
Restart=always

[Install]
WantedBy=multi-user.target

Durch das @ im Namen der Unit können verschiedene Instanzen, also mehrere Tunnel erstellt werden. Z.B. einer für SSH und einer für HTTPS:

root@mgmtdest# systemctl daemon-reload
root@mgmtdest# systemctl start ssh-reverse@22.service
root@mgmtdest# systemctl start ssh-reverse@443.service

Der Port des Tunnels auf dem Gateway wird auf "40%I" gesetzt wobei %I dem Instanznamen (im Beispiel 22 und 443) entspricht. Im Beispiel ergibt das auf dem Gateway die Ports 4022 und 40443.

Die Parameter für die einzelnen Instanzen können und sollten über Drop-In-Files angepaßt werden, z.B.:

/etc/systemd/system/ssh-reverse@22.service.d/tunnel.conf:

[Service]
# Port of the tunnel at the remote gateway
Environment="GWPORT=10001"
# User at gateway to create the tunnel
##Environment="GWUSER=sshtunnel"
# remote gateway
##Environment="GWHOST=gateway.example.de"
# Location of the SSH key
##Environment="SSHKEY=/home/support/.ssh/gateway.example.de"

/etc/systemd/system/ssh-reverse@443.service.d/tunnel.conf:

[Service]
# Port of the tunnel at the remote gateway
Environment="GWPORT=10002"
# User at gateway to create the tunnel
##Environment="GWUSER=sshtunnel"
# remote gateway
##Environment="GWHOST=gateway.example.de"
# Location of the SSH key
##Environment="SSHKEY=/home/support/.ssh/gateway.example.de"

In diesen Beispielen werden die auf dem Gateway verwendeten Ports angepaßt.

Zielsystem Windows

Wird noch getestet...

Supportclient Linux

Als normaler User, dessen SSH-Key beim Tunnel-User auf dem Gateway ("sshtunnel") hinterlegt ist, wird der Tunnel zum Gateway wie folgt aufgebaut:

user@supportclient$ ssh -nNT -L 10022:localhost:10001 sshtunnel@gateway.example.de

Damit wird ein Tunnel vom lokalen Port 10022 zum Port 10001 auf dem Gateway erstellt. Hat das Zielsystem, wie im Beispiel, einen reverse Tunnel zum Gateway von seinem lokalen Port 22 auf den Port 10001 auf dem Gateway gestartet, kann man nun vom Supportclient auf das Zielsystem mit SSH zugreifen:

user@supportclient$ ssh -p 10022 admin@localhost

"admin" ist ein Nutzer auf dem Zielsystem, über welchen der Support abgewickelt wird.

Ist ein Zugriff mittels Browser auf das Zielsystem notwendig, wird ein zweiter Tunnel zum Gateway erstellt:

user@supportclient$ ssh -nNT -L 10443:localhost:10002 sshtunnel@gateway.example.de

Wird nun im Browser https://localhost:10443 eingegeben, ist man direkt mit dem Webserver auf dem Zielsystem verbunden.

Supportclient Windows

Wird noch getestet...