Ein VPN mit einem SSH Tunnel aufbauen

Bild der Darstellung eines SSH Tunnels

Zuletzt geändert oder ergänzt am !

Es soll ein VPN (Virtual Private Network) mit einem SSH-Tunnel zu einem entfernten Rechner aufgebaut werden. Ein VPN ist eine verschlüsselte Datenverbindung zwischen zwei Rechnern. Der SSH-Tunnel stellt eine einfache und hocheffiziente Methode dar, um eine verschlüsselte Verbindung mittels Secure Shell (SSH) zu etablieren.

Dieses Verfahren wird auch als Portweiterleitung bezeichnet und garantiert die Integrität als auch die Vertraulichkeit der Datenübertragung.

Die Verbindung kann beliebige Datenströme transportieren und ist besonders sicher, da sie zwei Verfahren kombiniert. Während der Authentifizierung wird die asymmetrische Verschlüsselung genutzt, um die Identität der Partner zu prüfen. Anschließend übernimmt die schnellere symmetrische Verschlüsselung den Schutz der eigentlichen Datenübertragung.

Dazu wird der Kommandozeilenbefehl ssh (Secure Shell) verwendet.

Unter Linux bzw. Ubuntu kann der SSH-Client mit dem folgenden Befehl installiert werden:

$ sudo apt install openssh-client

In diesem Beitrag wird als Beispiel auf dem lokalen Rechner der Port 40.000 geöffnet, über den, der Port 110 des entfernten Rechners (pop.example.org) erreichbar ist (siehe Titelbild oben).

Damit der Port 40.000 von außerhalb nicht erreichbar ist, wird er an localhost gebunden. Damit lautet die lokale URL des entfernten Rechners http://localhost:40000 und der entfernte Rechner wird über den Port 110 aufgerufen.

SSH-Tunnel per lokale Portweiterleitung

Voraussetzung: Der lokale Benutzer muss sich mit SSH am entfernten Rechner anmelden können.

$ ssh user@pop.example.org

Es soll eine verschlüsselte Verbindung zwischen dem lokalen Rechner localhost und dem entfernten Rechner pop.example.org aufgebaut werden.

Zusätzlich soll eine Netzwerk-Route (SSH-Tunnel) beginnend auf dem lokalen Rechner localhost mit Port 40.000 und endend auf dem entfernten Rechner pop.example.org mit Port 110, über die verschlüsselte Verbindung, etabliert werden.

$ ssh -L 40000:pop.example.org:110 user@pop.example.org
ssh -L [local-server:]local-port:destination-server:destination-port [login-name@]login-server

So wird eine Verbindung am lokalen Port 40.000 zum Port 110 (POP3) auf dem entfernten Rechner ermöglicht. Ein lokaler Client, wie Microsoft Outlook, kann damit auf ein Postfach auf dem entfernten Rechner pop.example.org zugreifen, der normalerweise vom lokalen Rechner nicht erreichbar und außerdem noch verschlüsselt ist.

Der Zielport 110 entspricht dem Standard-Port des Post Office Protocol – Version 3 (POP3, RFC 1939). Da POP3 in seiner Basisform Passwörter und E-Mails im Klartext überträgt, bietet der SSH-Tunnel hier den entscheidenden Vorteil der nachträglichen Verschlüsselung eines eigentlich unsicheren Protokolls.

Hier noch ein Test der Verbindung:

$ telnet localhost 40000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK POP3 (version 2.2) at 192.168.178.222 starting.

SSH-Tunnel per entfernte Portweiterleitung

Voraussetzung: Der lokale Benutzer muss sich mit SSH am entfernten Rechner anmelden können.

$ ssh user@pop.example.org

Bei der entfernten Portweiterleitung möchte ich die Kommunikation entgegen der lokalen Portweiterleitung umdrehen.

Beispiel: Ich bin Softwareentwickler und möchte den aktuellen Entwicklungsstand meiner lokal laufenden Webanwendung meinem entfernten Kunden oder Kollegen präsentieren. Typischerweise hört die lokale Webanwendung auf dem Port 8080.

Mit dem folgenden Befehl wird die verschlüsselte Verbindung vom entfernten Rechner pop.example.org mit Port 80 zum lokalen Rechner localhost zum Port 8080 aufgebaut.

$ ssh -R 80:localhost:8080 user@pop.example.org
ssh -R [destination-server:]destination-port:local-server:local-port [login-name@]login-server

SSH-Tunnel per dynamische Portweiterleitung

Voraussetzung: Der lokale Benutzer muss sich mit SSH am entfernten Rechner anmelden können.

$ ssh user@pop.example.org

Bei der dynamischen Portweiterleitung möchte ich, den gesamten Netzwerkverkehr vom lokalen Rechner localhost über einen SSH-Tunnel zum entfernten Rechner pop.example.org leiten. Dazu wird ein Proxy verwendet, der das SOCKS-Protokoll benutzt – ideal für anonymes und verschlüsseltes Surfen.

$ ssh -D 1080 user@pop.example.org
ssh -D [local-server:]local-port [login-name@]destination-server

Die lokalen Anwendungen (z. B. Browser) nutzen den Port 1080, um ihre komplette Kommunikation an den entfernten Rechner pop.example.org weiterzuleiten. Diese Art der Portweiterleitung wird verwendet, wenn die Ports auf dem entfernten Rechner pop.example.org im Voraus unbekannt sind oder die Daten vom entfernten Rechner pop.example.org an andere entfernte Servers weitergeleitet werden sollen.

Tipps für die Praxis

Die Wahl des Quell- und Zielports

Das System der Port-Nummerierung unterliegt den Standards der Internet Assigned Numbers Authority (IANA), die eine klare Segmentierung vorschreibt.

Port-KategoriePort-BereicheCharakteristika
Well-Known Ports0-1023Reserviert für Systemdienste (Root/Administrator-Rechte erforderlich)
Registered Ports1024-49151Für spezifische Anwendungen registriert
Dynamic/Private Ports49152-65535Zur freien Verfügung für temporäre Verbindungen

Indem ein Port im Bereich über 1024 gewählt wird, wird sichergestellt, dass für das Binden des Ports keine administrativen Vorrechte auf dem lokalen Rechner vonnöten sind. Gleichzeitig wird das Risiko von Port-Kollisionen mit Standarddiensten wie HTTP (80) oder HTTPS (443) minimiert.

$ ssh -L 400:pop.example.org:110 user@pop.example.org 
bind [127.0.0.1]:400: Permission denied
channel_setup_fwd_listener_tcpip: cannot listen to port: 400
Could not request local forwarding.

Achtung bei virtuellen HTTP-Servern

Ein virtueller HTTP-Server wird durch den Hostnamen im HTTP-Request identifiziert. Dadurch kann auf einem Rechner unter einer einzigen IP-Adresse mehrere virtuelle HTTP-Server existieren. Dazu werden alle Hostnamen im DNS mit der gleichen IP-Adresse registriert.

Bei einer lokalen Portweiterleitung mit SSH wird im HTTP-Request der Hostname localhost übertragen. Um zu verhindern, dass dadurch möglicherweise der falsche virtuelle HTTP-Server auf dem entfernten Rechner ausgewählt wird, kann der ursprüngliche Hostname www.example.org eingetragen werden. Dazu muss in der lokalen Datei /etc/hosts der Hostname www.example.org mit der IP-Adresse 127.0.0.1 konfiguriert werden.

$ ssh -L 80:www.example.org:80 user@pop.example.org
127.0.0.1      localhost www.example.org

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

SSH-Schlüssel-Verwaltung

In diesem Abschnitt wird die Erzeugung und Austausch von SSH-Schlüsseln beschrieben.

SSH-Schlüssel erzeugen

Ein SSH-Schlüssel muss auf dem lokalen Rechner als ein asymmetrisches Schlüsselpaar erzeugt werden. Dieser Schlüssel besteht aus zwei Teilen, dem privaten Schlüssel (id_ed25519) und dem öffentlichen Schlüssel (id_ed25519.pub). Diese werden im Verzeichnis ~/.ssh/ an- und abgelegt. Der private Schlüssel darf den Rechner niemals verlassen. Entsprechend restriktiv sind die Benutzerrechte (-rw-------) zu setzen.

Als Schlüsselverfahren stehen Ed25519 und RSA zur Verfügung. Ed25519 basiert auf den Algorithmus für elliptische Kurven Curve25519. Das RSA-Verfahren verwendet gegenüber dem Ed25519 einen wesentlich größern Schlüssel und ist dadurch deutlich langsamer.

Ein SSH-Schlüssel wird mit dem folgenden Befehl erzeugt.

$ ssh-keygen -t ed25519 -C user@local.example.org
ssh-keygen -t ed25519 -C [login-name@]local-server
ssh-keygen -t rsa -b 4096 -C [login-name@]local-server
ssh-keygen -t ecdsa -b 521 -C [login-name@]local-server

Mit der Option -f ~/Pfad/zum/Verzeichnis/mein-key werden die SSH-Schlüssel im existierenden Verzeichnis ~/Pfad/zum/Verzeichnis/ erstellt. Die Schlüssel werden in die beiden Dateien mein-key und mein-key.pub geschrieben.

SSH-Schlüssel übertragen

Der öffentliche SSH-Schlüssel (id_ed25519.pub) muss in die Datei ~/.ssh/authorized_keys auf dem entfernten Rechner pop.example.org eintragen werden. Die Datei liegt im Home bzw. Benutzerverzeichnis des angegebenen Benutzers (user) auf dem entfernten Rechner pop.example.org.

$ ssh-copy-id -i ~/.ssh/id_ed25519.pub user@pop.example.org

Dieser Befehl fügt den öffentlichen SSH-Schlüssel zur Datei ~/.ssh/authorized_keys auf dem entfernten Rechner hinzu. Falls die Datei nicht vorhanden ist, wird sie und der Pfad angelegt. Zusätzlich werden die korrekten Dateiberechtigungen eingerichtet. Ist der Benutzername nicht angegeben, wird der aktuelle lokale Benutzername verwendet.

SSH-Hostschlüssel abfragen

Mit dem Befehl ssh-keyscan können die öffentlichen SSH-Hostschlüssel von einem entfernten Rechner abfragt werden. Es hilft beim Erstellen und Überprüfen der Dateien ~/.ssh/known_hosts oder /etc/ssh/ssh_known_hosts. In diesen Dateien werden die bekannten entfernten Rechner auf den lokalen Rechner gespeichert. Mit der Option -t ed25519,ras kann das gewünschte Schlüsselverfahren ausgewählt werden.

$ ssh-keyscan pop.example.org 
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
pop.example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE...
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
pop.example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQA...
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
pop.example.org ecdsa-sha2-nistp256 AAAAE2VjZHN...

Die SSH-Hostschlüssel dürfen ohne manuelle Überprüfung nicht automatisch akzeptiert werden. Nur so kann das Risiko eines Man-in-the-Middle Angriffes verhindert werden.

$ ssh-keyscan pop.example.org >> ~/.ssh/known_hosts

Mit der Option -H werden die Hostnamen und IP-Adressen der entfernten Rechner gehasht. Dadurch das Hashen der Hostnamen wird die Preisgabe von identifizierenden Informationen verhindert, falls der Inhalt der Dateien ~/.ssh/known_hosts oder /etc/ssh/ssh_known_hosts gelesen werden können. Insbesondere können die Hostnamen der verbundenen Rechner nicht ermittelt werden.

$ ssh-keyscan -H pop.example.org 
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
|1|dtUPDLOL...|DF83lhfj7B+20... ssh-ed25519 AAAAC3NzaC1lZDI1NTE...
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
|1|7SNqUiLH...|iKYwflflLsQtA... ssh-rsa AAAAB3NzaC1yc2EAAAADAQA...
# pop.example.org:22 SSH-2.0-OpenSSH_8.2
|1|bVnM4QL1...|beAIaiuMlJXWu... ecdsa-sha2-nistp256 AAAAE2VjZHN...

SSH-Server

Überprüfen der bestehenden Installation mit folgendem Befehl:

$ sudo systemctl status ssh
Unit ssh.service could not be found.

Installation unter Linux bzw. Ubuntu

Der SSH-Server wird mit dem folgenden Befehl unter Linux bzw. Ubuntu installieren:

$ sudo apt install openssh-server 
...

Der SSH-Server wird, mit den folgenden Befehlen, dauerhaft startet:

$ sudo systemctl status ssh
○ ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled)
     Active: inactive (dead)
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable ssh
Created symlink /etc/systemd/system/sshd.service → /usr/lib/systemd/system/ssh.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /usr/lib/systemd/system/ssh.service.
$ sudo systemctl start ssh
$ sudo systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Wed 2008-12-21 15:03:16 CEST; 4s ago
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 26346 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 26348 (sshd)
      Tasks: 1 (limit: 76828)
     Memory: 1.4M (peak: 2.6M)
        CPU: 16ms
     CGroup: /system.slice/ssh.service
             └─26348 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
 
Dec 21 15:03:16 CLL009 systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
Dec 21 15:03:16 CLL009 sshd[26348]: Server listening on 0.0.0.0 port 22.
Dec 21 15:03:16 CLL009 sshd[26348]: Server listening on :: port 22.
Dec 21 15:03:16 CLL009 systemd[1]: Started ssh.service - OpenBSD Secure Shell server.

Wichtige Konfigurationen des SSH-Servers

Der SSH-Server wird in der Konfigurationsdatei /etc/ssh/sshd_config eingerichtet.

Das Anmelden per Passwort über SSH deaktivieren durch PasswordAuthentication no. Damit wird die Nutzung von SSH-Schlüsseln zu erzwingen.

Aus Sicherheitsgründen sollte der direkte Login als Root-Benutzer immer unterbunden werden (PermitRootLogin no).

Standardmäßig erlaubt SSH nur Verbindungen vom lokalen Rechner zum getunnelten Port. Wenn auch andere Rechner im Netzwerk auf den SSH-Tunnel zugreifen sollen, muss dieser Wert auf GatewayPorts yes gesetzt werden.

SSHFS

Mit SSHFS (Secure Shell Filesystem) lässt sich ein entferntes Dateisystem verschlüsselt per SSH mounten. Dabei wird das SFTP-Protokoll (Secure File Transfer Protocol) eingesetzt, welches die meisten SSH-Server unterstützen und standardmäßig aktivieren.

$ sshfs user@pop.example.org:/pfad/auf/dem/server/ ~/srv

Hierbei wird das Verzeichnis /pfad/auf/dem/server/ vom Server lokal unter ~/srv gemountet.

Unter Linux bzw. Ubuntu kann SSHFS mit dem folgenden Befehl installiert werden:

$ sudo apt-get install sshfs

Anwendungsfälle

In diesem Abschnitt werden einige Beispiele für die Nutzung von SSH-Tunnel aufgeführt.

Wenn Ihr noch weitere interessante Anwendungsfälle kennt, schreibt mir, damit wir diese Liste erweitern können!

Sichere Systemverwaltung für Administrator

Zur Absicherung des Fernzugriffs auf die digitale Infrastruktur ermöglicht es SSH, einem Administrator das sichere Ausführen von Befehlen auf einem entfernten Server, um z. B. die Systemkonfiguration zu verändern.

$ ssh admin@srv1.example.org

E-Mail-System

Das POP3-Protokoll überträgt in seiner Basisform Passwörter und E-Mails im Klartext. Ein SSH-Tunnel mit einer lokalen Portweiterleitung bietet sich hier an, um den entscheidenden Vorteil der nachträglichen Verschlüsselung eines eigentlich unsicheren Protokolls auszuspielen.

$ ssh -N -L 1110:mail.example.org:110 user@mail.example.org
$ ssh -N -L 1025:mail.example.org:25 user@mail.example.org
$ ssh -N -L 1143:mail.example.org:143 user@mail.example.org

Die Ports unter 1024 (die bekannten Service-Ports) sind für normale Benutzer nicht zugänglich, sondern nur für Systemadministratoren (mit Root-Rechten). Daher wird auf die Original-Portnummer 1.000 addiert.

Die Option -N verhindert, das auf dem entfernten Rechner Befehle ausgeführt werden.

Absicherung von Datenbankverbindungen

Datenbanken-Administratoren nutzen SSH-Tunnel häufig, um auf Datenbanken wie MySQL (Port 3306) oder PostgreSQL (Port 5432) zuzugreifen, ohne diese direkt dem Internet auszusetzen. Eine lokale Portweiterleitung erlaubt es, eine lokale SQL-GUI mit der Datenbank zu verbinden, während die Daten sicher verschlüsselt zum Datenbankserver fließen.

$ ssh -N -L 5433:psql.example.org:5432 user@psql.example.org
$ psql -h localhost -p 5433 -U user -d <db-name>
$ ssh -N -L 3307:mysql.example.org:3306 user@mysql.example.org
$ mysql -h 127.0.0.1 -P 3307 -u user -p

Der lokale Port 3307 bzw. 5433 wird verwendet, um Konflikte mit einem eventuell lokal laufenden Datenbankserver an Port 3306 bzw. 5432 zu vermeiden.

Die Option -N verhindert, das auf dem entfernten Rechner Befehle ausgeführt werden.

Entfernte Portweiterleitung für Web-Entwicklung

Software-Entwickler nutzen oft die entfernte Portweiterleitung (-R), um eine lokal auf ihrem Rechner laufende Webanwendung einem entfernten Kunden oder Kollegen zu präsentieren. Über die entfernte Portweiterleitung kann die lokale Webanwendung an Port 8080 unter www.example.org mit Port 80 weltweit freigeben werden, ohne dass Router-Konfigurationen oder Port-Freigaben am lokalen Rechner nötig sind.

$ ssh -R 80:localhost:8080 user@www.example.org

Umgehung von restriktiven Web-Filtern

Durch die Nutzung der dynamischen Portweiterleitung (-D) kann SSH als SOCKS-Proxy fungieren. Dies ist besonders nützlich in Umgebungen mit strengen Inhaltsfiltern. Der Browser leitet sämtliche Anfragen durch den SSH-Tunnel, wodurch der Traffic für den lokalen Netzwerkbetreiber unkenntlich wird und am Standort des SSH-Servers austritt.

Spezifikationen für SSH:

RFC 4250 – The Secure Shell (SSH) Protocol Assigned Numbers

RFC 4251 – The Secure Shell (SSH) Protocol Architecture

RFC 4252 – The Secure Shell (SSH) Authentication Protocol

RFC 4253 – The Secure Shell (SSH) Transport Layer Protocol

RFC 4254 – The Secure Shell (SSH) Connection Protocol

RFC 4256 – Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)

RFC 4335 – The Secure Shell (SSH) Session Channel Break Extension

RFC 4344 – The Secure Shell (SSH) Transport Layer Encryption Modes

Erweiterungs-RFCs:

RFC 4255 – Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints

RFC 4419 – Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol

RFC 4432 – RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol

RFC 4462 – Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol

RFC 4716 – The Secure Shell (SSH) Public Key File Format

RFC 4819 – Secure Shell Public Key Subsystem

RFC 5647 – AES Galois Counter Mode for the Secure Shell Transport Layer Protocol

RFC 5656 – Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer

RFC 6187 – X.509v3 Certificates for Secure Shell Authentication

RFC 6239 – Suite B Cryptographic Suites for Secure Shell (SSH)

RFC 6594 – Use of the SHA-256 Algorithm with RSA, Digital Signature Algorithm (DSA), and Elliptic Curve DSA (ECDSA) in SSHFP Resource Records

RFC 6668 – SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol

RFC 8268 -More Modular Exponentiation (MODP) Diffie-Hellman (DH) Key Exchange (KEX) Groups for Secure Shell (SSH)

RFC 8270 – Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits

RFC 9142 – Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH)

Frank Rahn
Letzte Artikel von Frank Rahn (Alle anzeigen)
0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Ihre E-Mail-Adresse wird nicht veröffentlicht. Ihr Kommentar wird verschlüsselt an meinen Server gesendet. Erforderliche Felder sind mit * markiert.

Weitere Informationen und Widerrufshinweise finden Sie in meiner Datenschutzerklärung.