Ein VPN mit einem SSH Tunnel aufbauen
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-Kategorie | Port-Bereiche | Charakteristika |
|---|---|---|
| Well-Known Ports | 0-1023 | Reserviert für Systemdienste (Root/Administrator-Rechte erforderlich) |
| Registered Ports | 1024-49151 | Für spezifische Anwendungen registriert |
| Dynamic/Private Ports | 49152-65535 | Zur 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.
Weiterführende Links
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 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 6668 – SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol
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)
- Wer ist der optimale Java Bean Mapper? - Freitag, 22. September 2023
- Spring Boot Webanwendung: Die ersten Schritte (Tutorial) - Montag, 28. März 2016
- Mainframe-Zugriff via Java - Sonntag, 04. Mai 2014










Hinterlasse einen Kommentar
An der Diskussion beteiligen?Hinterlasse uns deinen Kommentar!