SSH Verbindungsaufbau: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(9 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
= SSH-Verbindungsaufbau =
 
= SSH-Verbindungsaufbau =
  
SSH baut eine Verbindung in drei aufeinanderfolgenden Phasen auf. Dieser Artikel erklärt, was dabei Schritt für Schritt im Hintergrund passiert – verständlich auch ohne tiefes Vorwissen.
+
SSH baut eine Verbindung in drei Phasen auf:
 +
* Verschlüsselter Kanal wird aufgebaut
 +
* Nutzer wird authentifiziert
 +
* Eigentliche Sitzung beginnt
  
'''Hinweis für Einsteiger:''' Du musst den Verbindungsaufbau nicht auswendig kennen, um SSH zu benutzen. Dieses Wissen hilft dir aber, Fehlermeldungen zu verstehen und zu begreifen, warum SSH so sicher ist.
+
'''Hinweis:''' Dieses Wissen hilft dir, Fehlermeldungen zu verstehen – du brauchst es nicht, um SSH zu benutzen.
  
 
== Die drei Phasen im Überblick ==
 
== Die drei Phasen im Überblick ==
Zeile 11: Zeile 14:
 
* '''Phase 3 – Session Phase:''' Die eigentliche Arbeit beginnt – Befehle, Dateiübertragungen, Tunnel usw.
 
* '''Phase 3 – Session Phase:''' Die eigentliche Arbeit beginnt – Befehle, Dateiübertragungen, Tunnel usw.
  
== Phase 1: Transport Layer & Key Exchange ==
 
  
In dieser Phase wird der verschlüsselte Kanal aufgebaut. Am Ende kennen beide Seiten einen gemeinsamen geheimen Schlüssel – ohne dass dieser jemals über das Netzwerk gesendet wurde.
+
[[Datei:Ssh-verbindung-1.png|800px]]
  
=== Begrüßung (Hello) ===
+
<!-- ===================================================== -->
 +
<!-- GRAFIK HIER: Einstiegs-Diagramm (Password-Variante)  -->
 +
<!-- Datei: Ssh-verbindungsaufbau-password.svg o.ä.        -->
 +
<!-- [[Datei:Ssh-verbindungsaufbau-password.svg|zentriert|Abb. 1: SSH-Verbindungsaufbau – Überblick (Password-Authentifizierung)]] -->
 +
<!-- ===================================================== -->
  
Der Client nimmt Kontakt auf und schickt ein '''ClientHello'''. Darin teilt er dem Server mit, welche kryptographischen Verfahren er unterstützt:
+
== Phase 1: Transport Layer & Key Exchange ==
  
* '''KEX-Algorithmen:''' Verfahren für den Schlüsselaustausch (z. B. <code>curve25519-sha256</code>)
+
=== Begrüßung (Hello) ===
* '''Host-Key-Algorithmen:''' Wie der Server sich ausweisen kann (z. B. <code>ssh-ed25519</code>)
 
* '''Cipher-Algorithmen:''' Verschlüsselungsverfahren (z. B. <code>aes256-gcm</code>)
 
* '''MAC-Algorithmen:''' Methoden zur Integritätsprüfung (z. B. <code>hmac-sha2-256</code>)
 
  
Der Server antwortet mit einem '''ServerHello''': Er wählt aus der Liste die Algorithmen aus, die er ebenfalls unterstützt, und schickt außerdem seinen '''öffentlichen Host Key''' mit.
+
* Client schickt dem Server, welche Verfahren er unterstützt (KEX, Host-Key, Cipher, Hash, MAC)
 +
* Server wählt passende Verfahren aus
 +
* Server schickt seinen öffentlichen Host Key mit
  
 
=== Host-Key-Prüfung ===
 
=== Host-Key-Prüfung ===
Der Client hat jetzt den öffentlichen Host Key des Servers. Jetzt stellt sich die Frage: ''Ist das wirklich der richtige Server – oder wurde die Verbindung abgefangen?''
 
SSH überprüft das mithilfe der Datei <code>~/.ssh/known_hosts</code>. Dort werden beim ersten Verbindungsaufbau die öffentlichen Host Keys bekannter Server gespeichert. Beim allerersten Verbindungsaufbau zu einem neuen Server zeigt SSH einen Fingerprint des Host Keys an – eine kompakte Hash-Darstellung – und fragt, ob du dem Server vertraust. Erst nach deiner Bestätigung wird der vollständige Public Key in <code>known_hosts</code> gespeichert. Bei allen weiteren Verbindungen vergleicht SSH den gespeicherten Key automatisch mit dem vom Server.
 
'''Warnung:''' Wenn SSH die Meldung <code>WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!</code> anzeigt, präsentiert der Server einen anderen Key als beim letzten Mal. Das kann ein Hinweis auf einen Angriff sein – oder einfach darauf, dass der Server neu aufgesetzt wurde. Im Zweifel beim Administrator nachfragen, bevor du fortfährst.
 
  
=== Diffie-Hellman Key Exchange ===
+
* Client empfängt den öffentlichen Host Key des Servers
 +
* SSH prüft: ''Ist das wirklich der richtige Server?''
 +
* Prüfung erfolgt anhand <code>~/.ssh/known_hosts</code>
 +
* Beim ersten Verbindungsaufbau: SSH zeigt den Fingerprint an und fragt nach Bestätigung
 +
* Nach Bestätigung: Public Key wird in <code>known_hosts</code> gespeichert
 +
* Bei weiteren Verbindungen: SSH vergleicht automatisch
  
Jetzt passiert etwas scheinbar Magisches: Client und Server einigen sich auf einen gemeinsamen geheimen Schlüssel – '''ohne ihn jemals zu übertragen'''.
+
'''Warnung:''' <code>WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!</code>
 +
* Der Server präsentiert einen anderen Key als beim letzten Mal
 +
* Mögliche Ursachen: Angriff oder Server neu aufgesetzt
 +
* Im Zweifel beim Administrator nachfragen
  
Das Verfahren heißt '''Diffie-Hellman''' (oder in moderner Form ECDH). Die klassische Analogie ist das Farbmischen: Stell dir vor, beide Seiten haben eine gemeinsame Ausgangsfarbe (öffentlich bekannt). Jeder mischt seine eigene Geheimfarbe dazu – und tauscht das Ergebnis aus. Aus diesem Ergebnis kann jeder seine eigene Geheimfarbe wieder herausrechnen und erhält dadurch dieselbe Endfarbe. Ein Lauscher sieht nur die gemischten Farben, nie die Geheimfarben.
+
=== Diffie-Hellman Key Exchange ===
  
Ablauf im Detail:
+
* Client sendet seinen öffentlichen DH-Wert
 +
* Server berechnet daraus den KEX-Hash (H) und signiert ihn mit seinem '''privaten Host Key'''
 +
* Server sendet seinen eigenen DH-Wert zusammen mit dieser Signatur zurück
 +
* Client prüft die Signatur anhand des öffentlichen Host Keys – damit ist bewiesen, dass der Server wirklich der Besitzer des Host Keys ist
 +
* Beide Seiten berechnen daraus '''unabhängig''' denselben Session Key
 +
* Der Session Key wird nie übertragen
 +
* Ein Lauscher kann den Session Key nicht ableiten
  
# Client erzeugt ein zufälliges privates Geheimnis und berechnet daraus einen '''Public Value'''
+
=== Ab jetzt alles verschlüsselt ===
# Server macht dasselbe und schickt seinen Public Value sowie eine '''Signatur''' (erstellt mit dem privaten Host Key)
 
# Client prüft die Signatur mit dem öffentlichen Host Key des Servers → bestätigt die Serveridentität
 
# Beide berechnen unabhängig voneinander denselben '''Session Key'''
 
  
=== Session Key – ab jetzt alles verschlüsselt ===
+
* Beide Seiten besitzen nun denselben Session Key
 +
* Ab jetzt ist die gesamte Kommunikation symmetrisch verschlüsselt
  
Aus den ausgetauschten Werten berechnen beide Seiten unabhängig voneinander denselben '''symmetrischen Session Key'''. Ab diesem Moment ist die gesamte Kommunikation verschlüsselt – auch die noch folgende Authentifizierung des Nutzers.
+
== Phase 2: User Authentication ==
  
== Phase 2: User Authentication (Public Key) ==
+
* Server prüft: ''Wer will sich einloggen – und hat diese Person Berechtigung?''
 +
* Sicherste Methode: '''Public-Key-Authentifizierung'''
 +
[[Datei:Ssh-verbindung-2.png|600px]]
 +
<!-- ===================================================== -->
 +
<!-- GRAFIK HIER: Vollständiges Diagramm (Public-Key)      -->
 +
<!-- Datei: Ssh-verbindungsaufbau-publickey.svg o.ä.      -->
 +
<!-- [[Datei:Ssh-verbindungsaufbau-publickey.svg|zentriert|Abb. 2: SSH-Verbindungsaufbau – Public-Key-Authentifizierung (vollständig)]] -->
 +
<!-- ===================================================== -->
  
Der Kanal ist jetzt verschlüsselt. Jetzt muss der Server wissen: ''Wer will sich hier einloggen – und hat diese Person die Berechtigung?''
+
=== Ablauf Public-Key-Authentifizierung ===
  
Die sicherste Methode ist die '''Public-Key-Authentifizierung'''. Dabei beweist der Client, dass er im Besitz eines privaten Schlüssels ist – ohne diesen jemals zu senden.
+
# Client schickt: Username, Methode <code>publickey</code> und welchen öffentlichen Schlüssel er verwenden will
 +
# Server prüft, ob dieser Schlüssel in <code>~/.ssh/authorized_keys</code> steht
 +
# Wenn nein → Auth fail
 +
# Wenn ja → Server schickt eine Challenge (Zufallsdaten)
 +
# Client signiert die Challenge mit seinem '''privaten''' Schlüssel und schickt die Signatur zurück
 +
# Server prüft die Signatur mit dem öffentlichen Schlüssel → Erfolg
  
Vorbedingung: Der öffentliche Schlüssel des Clients muss vorher auf dem Server hinterlegt werden:
+
* Der private Schlüssel verlässt nie den eigenen Rechner
ssh-copy-id user@server
+
* Sicherer als ein Passwort, weil die Signatur ohne privaten Schlüssel nicht reproduzierbar ist
  
Ablauf der Authentifizierung:
+
=== Ablauf Password-Authentifizierung ===
  
# Client schickt einen '''Auth Request''' mit Benutzername, Methode „publickey" und dem verwendeten öffentlichen Schlüssel
+
# Client schickt: Username, Methode <code>password</code>
# Server prüft: Ist dieser Public Key in <code>~/.ssh/authorized_keys</code> eingetragen?
+
# Client schickt Username und Passwort (verschlüsselt übertragen)
# Wenn ja: Server schickt eine '''Challenge''' (verschlüsselte Zufallsdaten)
+
# Server prüft das Passwort → Auth OK oder Auth fail
# Client signiert die Challenge mit seinem '''privaten Schlüssel''' und sendet die Signatur zurück
 
# Server prüft die Signatur mit dem öffentlichen Schlüssel gültig → '''Auth SUCCESS'''
 
  
'''Warum ist das sicherer als ein Passwort?''' Der private Schlüssel verlässt den eigenen Rechner nie. Selbst wenn ein Angreifer den gesamten Netzwerkverkehr aufzeichnet, kann er sich nicht einloggen – ohne den privaten Schlüssel ist die Signatur nicht reproduzierbar.
+
* Einfacher, aber weniger sicher als Public-Key-Authentifizierung
 +
* Anfällig für Brute-Force-Angriffe
  
== Phase 3: Session Phase (Channels) ==
+
== Phase 3: Session Phase ==
  
Die Authentifizierung ist erfolgreich. Jetzt öffnet SSH einen oder mehrere '''Channels''' – logische Kanäle innerhalb der verschlüsselten Verbindung.
+
* Verbindung steht – die eigentliche Arbeit beginnt
 +
* SSH öffnet Channels für verschiedene Aufgaben:
  
 
{| class="wikitable"
 
{| class="wikitable"
Zeile 78: Zeile 104:
 
| <code>exec</code> || Einzelnen Befehl ausführen || <code>ssh user@server ls -la</code>
 
| <code>exec</code> || Einzelnen Befehl ausführen || <code>ssh user@server ls -la</code>
 
|-
 
|-
| <code>subsystem sftp</code> || Dateiübertragung per SFTP || <code>sftp user@server</code>
+
| <code>subsystem sftp</code> || Dateiübertragung || <code>sftp user@server</code>
 
|-
 
|-
 
| <code>direct-tcpip</code> || Port-Forwarding / Tunnel || <code>ssh -L 8080:localhost:80 user@server</code>
 
| <code>direct-tcpip</code> || Port-Forwarding / Tunnel || <code>ssh -L 8080:localhost:80 user@server</code>
 
|}
 
|}
  
Alle Daten in diesen Channels sind symmetrisch verschlüsselt und integritätsgeschützt – niemand kann die Daten unbemerkt verändern.
+
* Alle Daten sind verschlüsselt und integritätsgeschützt
  
 
== Häufige Fehlermeldungen ==
 
== Häufige Fehlermeldungen ==
Zeile 91: Zeile 117:
 
  WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
 
  WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
  
'''Ursache:''' Der Host Key des Servers hat sich geändert (z. B. nach Neuinstallation des Servers).
+
* Ursache: Host Key hat sich geändert (z. B. nach Neuinstallation)
 
+
* Lösung:
'''Lösung:''' Den alten Eintrag aus <code>~/.ssh/known_hosts</code> entfernen:
 
 
  ssh-keygen -R server.example.com
 
  ssh-keygen -R server.example.com
  
Zeile 100: Zeile 125:
 
  Permission denied (publickey).
 
  Permission denied (publickey).
  
'''Ursache:''' Der öffentliche Schlüssel ist nicht in <code>~/.ssh/authorized_keys</code> des Servers eingetragen, oder die Dateiberechtigungen stimmen nicht.
+
* Ursache: Public Key nicht in <code>~/.ssh/authorized_keys</code>, oder Berechtigungen falsch
 
+
* Lösung:
'''Lösung:'''
 
 
  ssh-copy-id user@server
 
  ssh-copy-id user@server
 
Berechtigungen auf dem Server prüfen:
 
 
  chmod 700 ~/.ssh
 
  chmod 700 ~/.ssh
 
  chmod 600 ~/.ssh/authorized_keys
 
  chmod 600 ~/.ssh/authorized_keys
Zeile 112: Zeile 134:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Kategorie !! Moderne Empfehlung !! Zweck
+
! Kategorie !! Empfehlung !! Zweck
 
|-
 
|-
| Key Exchange (KEX) || <code>curve25519-sha256</code> || Gemeinsamen Session Key ableiten
+
| Key Exchange || <code>curve25519-sha256</code> || Session Key ableiten
 
|-
 
|-
 
| Host Key || <code>ssh-ed25519</code> || Server-Identität beweisen
 
| Host Key || <code>ssh-ed25519</code> || Server-Identität beweisen
 
|-
 
|-
| Symmetrische Verschlüsselung || <code>aes256-gcm@openssh.com</code> || Datenverschlüsselung
+
| Verschlüsselung || <code>aes256-gcm@openssh.com</code> || Datenverschlüsselung
 
|-
 
|-
| MAC / Integrität || <code>hmac-sha2-256-etm</code> || Manipulation erkennen
+
| Integrität || <code>hmac-sha2-256-etm</code> || Manipulation erkennen
 
|-
 
|-
 
| Client-Schlüssel || <code>ed25519</code> || User Authentication
 
| Client-Schlüssel || <code>ed25519</code> || User Authentication

Aktuelle Version vom 21. April 2026, 13:25 Uhr

SSH-Verbindungsaufbau

SSH baut eine Verbindung in drei Phasen auf:

  • Verschlüsselter Kanal wird aufgebaut
  • Nutzer wird authentifiziert
  • Eigentliche Sitzung beginnt

Hinweis: Dieses Wissen hilft dir, Fehlermeldungen zu verstehen – du brauchst es nicht, um SSH zu benutzen.

Die drei Phasen im Überblick

  • Phase 1 – Transport Layer & Key Exchange: Client und Server einigen sich auf einen gemeinsamen, geheimen Schlüssel – ohne ihn jemals direkt zu übertragen.
  • Phase 2 – User Authentication: Der Server prüft, ob der Client wirklich der ist, der er vorgibt zu sein.
  • Phase 3 – Session Phase: Die eigentliche Arbeit beginnt – Befehle, Dateiübertragungen, Tunnel usw.


Ssh-verbindung-1.png


Phase 1: Transport Layer & Key Exchange

Begrüßung (Hello)

  • Client schickt dem Server, welche Verfahren er unterstützt (KEX, Host-Key, Cipher, Hash, MAC)
  • Server wählt passende Verfahren aus
  • Server schickt seinen öffentlichen Host Key mit

Host-Key-Prüfung

  • Client empfängt den öffentlichen Host Key des Servers
  • SSH prüft: Ist das wirklich der richtige Server?
  • Prüfung erfolgt anhand ~/.ssh/known_hosts
  • Beim ersten Verbindungsaufbau: SSH zeigt den Fingerprint an und fragt nach Bestätigung
  • Nach Bestätigung: Public Key wird in known_hosts gespeichert
  • Bei weiteren Verbindungen: SSH vergleicht automatisch

Warnung: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

  • Der Server präsentiert einen anderen Key als beim letzten Mal
  • Mögliche Ursachen: Angriff oder Server neu aufgesetzt
  • Im Zweifel beim Administrator nachfragen

Diffie-Hellman Key Exchange

  • Client sendet seinen öffentlichen DH-Wert
  • Server berechnet daraus den KEX-Hash (H) und signiert ihn mit seinem privaten Host Key
  • Server sendet seinen eigenen DH-Wert zusammen mit dieser Signatur zurück
  • Client prüft die Signatur anhand des öffentlichen Host Keys – damit ist bewiesen, dass der Server wirklich der Besitzer des Host Keys ist
  • Beide Seiten berechnen daraus unabhängig denselben Session Key
  • Der Session Key wird nie übertragen
  • Ein Lauscher kann den Session Key nicht ableiten

Ab jetzt alles verschlüsselt

  • Beide Seiten besitzen nun denselben Session Key
  • Ab jetzt ist die gesamte Kommunikation symmetrisch verschlüsselt

Phase 2: User Authentication

  • Server prüft: Wer will sich einloggen – und hat diese Person Berechtigung?
  • Sicherste Methode: Public-Key-Authentifizierung

Ssh-verbindung-2.png

Ablauf Public-Key-Authentifizierung

  1. Client schickt: Username, Methode publickey und welchen öffentlichen Schlüssel er verwenden will
  2. Server prüft, ob dieser Schlüssel in ~/.ssh/authorized_keys steht
  3. Wenn nein → Auth fail
  4. Wenn ja → Server schickt eine Challenge (Zufallsdaten)
  5. Client signiert die Challenge mit seinem privaten Schlüssel und schickt die Signatur zurück
  6. Server prüft die Signatur mit dem öffentlichen Schlüssel → Erfolg
  • Der private Schlüssel verlässt nie den eigenen Rechner
  • Sicherer als ein Passwort, weil die Signatur ohne privaten Schlüssel nicht reproduzierbar ist

Ablauf Password-Authentifizierung

  1. Client schickt: Username, Methode password
  2. Client schickt Username und Passwort (verschlüsselt übertragen)
  3. Server prüft das Passwort → Auth OK oder Auth fail
  • Einfacher, aber weniger sicher als Public-Key-Authentifizierung
  • Anfällig für Brute-Force-Angriffe

Phase 3: Session Phase

  • Verbindung steht – die eigentliche Arbeit beginnt
  • SSH öffnet Channels für verschiedene Aufgaben:
Channel-Typ Verwendung Beispiel
shell Interaktive Terminal-Sitzung ssh user@server
exec Einzelnen Befehl ausführen ssh user@server ls -la
subsystem sftp Dateiübertragung sftp user@server
direct-tcpip Port-Forwarding / Tunnel ssh -L 8080:localhost:80 user@server
  • Alle Daten sind verschlüsselt und integritätsgeschützt

Häufige Fehlermeldungen

Host-Key-Warnung

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
  • Ursache: Host Key hat sich geändert (z. B. nach Neuinstallation)
  • Lösung:
ssh-keygen -R server.example.com

Permission denied (publickey)

Permission denied (publickey).
  • Ursache: Public Key nicht in ~/.ssh/authorized_keys, oder Berechtigungen falsch
  • Lösung:
ssh-copy-id user@server
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Verwendete Algorithmen

Kategorie Empfehlung Zweck
Key Exchange curve25519-sha256 Session Key ableiten
Host Key ssh-ed25519 Server-Identität beweisen
Verschlüsselung aes256-gcm@openssh.com Datenverschlüsselung
Integrität hmac-sha2-256-etm Manipulation erkennen
Client-Schlüssel ed25519 User Authentication

Siehe auch

  • SSH – Grundlagen und Einführung
  • OpenSSH – Die meistgenutzte SSH-Implementierung
  • SSH-Keygen – Schlüsselpaare generieren
  • SFTP – Sicherer Dateitransfer über SSH
  • SSH-Tunnel – Port-Forwarding und Tunneling

Weblinks