Zum Inhalt springen

SSH

Um auf einem entfernten Linux-System zu arbeiten, brauchst du dort eine Shell. Früher lieferten telnet und rsh («remote shell») diese Shell, und zwar im Klartext: Jeder im selben Netz konnte Passwörter und Befehle mitlesen. SSH («secure shell») löste beide in den späten Neunzigern ab und ist seither der Standard für den Serverzugriff: Die ganze Verbindung ist verschlüsselt, der Server weist sich mit einem Schlüssel aus, und du kannst dich statt mit einem Passwort mit einem Schlüsselpaar anmelden.

SSH ist mehr als eine Shell. Über dieselbe Verbindung laufen Dateitransfer (scp, sftp, rsync), Git (git clone git@...), die Editor-Erweiterung Remote - SSH und bei Bedarf ganze Dateisysteme (sshfs).

Das Programm auf deiner Seite heisst ssh (Client), auf der Server-VM läuft sshd (Daemon). Du gibst Benutzer und Host an:

eigener Rechner
ssh alice@10.0.0.42

Beim ersten Verbinden erscheint diese Frage:

The authenticity of host '10.0.0.42 (10.0.0.42)' can't be established.
ED25519 key fingerprint is SHA256:Xr3kT9q...
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Das ist keine Fehlermeldung. Jeder SSH-Server hat einen eigenen Host-Schlüssel, und dein Client kennt ihn noch nicht. Mit yes speicherst du den Fingerabdruck in ~/.ssh/known_hosts. Ab jetzt prüft der Client bei jeder Verbindung, ob der Server noch derselbe ist. Ändert sich der Schlüssel, zum Beispiel weil du die VM neu installiert hast, warnt SSH laut (REMOTE HOST IDENTIFICATION HAS CHANGED) und verweigert die Verbindung. In dem Fall löschst du den alten Eintrag mit ssh-keygen -R 10.0.0.42. Siehst du die Warnung, ohne dass du etwas am Server geändert hast, ist Misstrauen angebracht.

Hands-on:

eigener Rechner
ssh alice@10.0.0.42
hostname
whoami
exit
cat ~/.ssh/known_hosts

Achte auf den Prompt: Nach dem Login zeigt er alice@server-vm statt deines lokalen Rechners. Alles, was du jetzt tippst, läuft dort. exit (oder Ctrl+D) beendet die Sitzung.

Ein Passwort kann erraten, abgeschaut oder auf einem fremden Server abgefangen werden. Das Public-Key-Verfahren ersetzt es durch ein Schlüsselpaar:

  • Der private Schlüssel bleibt auf deinem Rechner. Immer. Er verlässt ihn nie, wird nie kopiert, nie per Mail verschickt, nie committet.
  • Der öffentliche Schlüssel darf jeder sehen. Du hinterlegst ihn auf jedem Server, auf dem du dich anmelden willst.
sequenceDiagram
    participant C as Client (privater Schlüssel)
    participant S as Server-VM (authorized_keys)
    C->>S: Login als alice, hier mein öffentlicher Schlüssel
    S->>S: Steht der Schlüssel in ~alice/.ssh/authorized_keys?
    S->>C: Zufallswert (Challenge)
    C->>C: signiert den Zufallswert mit dem privaten Schlüssel
    C->>S: Signatur
    S->>S: prüft die Signatur mit dem öffentlichen Schlüssel
    S->>C: Login erlaubt, Shell wird gestartet

Der Server stellt eine Aufgabe, die nur der Besitzer des privaten Schlüssels lösen kann. Ein Passwort geht nie über die Leitung, und was auf dem Server liegt, nützt einem Angreifer nichts.

  1. Schlüsselpaar erzeugen. ed25519 ist der heutige Standard: kurz, schnell, sicher. Gib eine Passphrase ein, sie schützt den privaten Schlüssel, falls dein Rechner abhandenkommt.
    eigener Rechner
    ssh-keygen -t ed25519 -C "alice@laptop"
    ls -l ~/.ssh/
    Du hast jetzt id_ed25519 (privat, Rechte 600) und id_ed25519.pub (öffentlich). Falls du in Modul 2 schon einen Schlüssel für GitLab erzeugt hast, verwende den weiter.
  2. Öffentlichen Schlüssel auf die Server-VM bringen. ssh-copy-id fragt ein letztes Mal nach dem Passwort und hängt den Schlüssel an ~/.ssh/authorized_keys an:
    eigener Rechner
    ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@10.0.0.42
  3. Testen. Jetzt wird nur noch nach der Passphrase gefragt, nicht mehr nach dem Passwort des Servers:
    eigener Rechner
    ssh alice@10.0.0.42 'cat ~/.ssh/authorized_keys'

Der ssh-agent hält den entschlüsselten privaten Schlüssel im Speicher, solange du angemeldet bist. Ubuntu Desktop und macOS starten ihn automatisch, in einer Server-VM oder unter WSL startest du ihn selbst:

eigener Rechner
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l

Danach fragt ssh bis zum Abmelden nicht mehr nach der Passphrase.

IP-Adressen und Benutzernamen tippt man nicht jedes Mal. Die Datei ~/.ssh/config definiert Kurznamen:

~/.ssh/config
Host server
HostName 10.0.0.42
User alice
IdentityFile ~/.ssh/id_ed25519
eigener Rechner
chmod 600 ~/.ssh/config
ssh server

Der Alias gilt für alle Programme, die SSH benutzen: scp server:..., rsync ... server:..., git, VS Code.

scp funktioniert wie cp, nur dass eine Seite host:pfad heisst. Pfade ohne führendes / sind relativ zum Home-Verzeichnis auf dem Server:

eigener Rechner
echo "Hallo Server" > gruss.txt
scp gruss.txt server:
scp server:gruss.txt gruss-zurueck.txt
scp -r server:/etc/ssh/sshd_config.d ./sshd_config.d-kopie

sftp ist die interaktive Variante mit ls, cd, get und put, praktisch, wenn du nicht genau weisst, wo die Datei liegt:

eigener Rechner
sftp server
sftp> ls
sftp> get gruss.txt
sftp> bye

Für ganze Verzeichnisbäume und wiederholte Übertragungen ist rsync die bessere Wahl.

Hängst du einen Befehl an ssh, wird er ausgeführt und die Verbindung gleich wieder geschlossen. Das ist die Grundlage für Skripte, die mehrere Server abfragen:

eigener Rechner
ssh server uptime
ssh server 'df -h / && free -h'
ssh -t server sudo systemctl status ssh --no-pager

Die Anführungszeichen sorgen dafür, dass && auf dem Server ausgewertet wird und nicht lokal. -t fordert ein Terminal an, das braucht sudo für die Passwortabfrage.

Mit sshfs erscheint ein Verzeichnis der Server-VM wie ein lokales, ganz ohne Freigabe-Dienst auf dem Server. Praktisch, um Serverdateien mit einem grafischen Editor zu bearbeiten:

lokale VM
sudo apt install sshfs
mkdir -p ~/server-home
sshfs server: ~/server-home
ls ~/server-home
fusermount -u ~/server-home

Solange sshd Passwörter akzeptiert, probieren Bots rund um die Uhr Passwörter aus; ein Blick in sudo journalctl -u ssh auf einem Server im Internet zeigt das. Zwei Einstellungen stoppen das, und du setzt sie erst, nachdem der Schlüssel-Login nachweislich funktioniert.

Ubuntu 24.04 liest Zusatzdateien aus /etc/ssh/sshd_config.d/ ein, noch vor dem Rest von sshd_config. Bei doppelten Einträgen gilt der erste gefundene Wert, darum bekommt deine Datei eine kleine Nummer, damit sie vor dem Installer-Rest (50-cloud-init.conf) gelesen wird:

/etc/ssh/sshd_config.d/10-haerten.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
  1. Datei als root anlegen (sudo vim /etc/ssh/sshd_config.d/10-haerten.conf).
  2. Konfiguration prüfen, bevor du den Dienst neu startest. sshd -T zeigt die wirksamen Werte:
    Server-VM
    sudo sshd -t
    sudo sshd -T | grep -E 'passwordauthentication|permitrootlogin|kbdinteractive'
  3. Dienst neu starten. Lass deine aktuelle Sitzung offen und teste den Login in einem zweiten Terminal. Scheitert er, kannst du in der offenen Sitzung die Datei wieder entfernen:
    Server-VM
    sudo systemctl restart ssh
  4. Gegenprobe vom eigenen Rechner: Ein Login mit erzwungenem Passwort muss jetzt abgewiesen werden:
    eigener Rechner
    ssh -o PubkeyAuthentication=no server
    Erwartete Antwort: Permission denied (publickey).
Lösung anzeigen
Terminal-Fenster
script labs/linux/10-remote-backup/ssh.txt
ssh-keygen -l -f ~/.ssh/id_ed25519.pub
cat ~/.ssh/config
ssh -t server 'cat ~/.ssh/authorized_keys; sudo sshd -T | grep -iE "passwordauth|permitroot"'
ssh -o PubkeyAuthentication=no server
# 5: Sonst sperrt man sich aus, wenn der Schlüssel nicht akzeptiert wird (Tippfehler,
# falsche Rechte). Ausgesperrt: Proxmox-Konsole der VM öffnen, dort anmelden und
# /etc/ssh/sshd_config.d/10-haerten.conf entfernen, systemctl restart ssh.
exit

Selbstcheck · 5 Fragen

1. Was bedeutet die Frage nach dem Fingerprint beim ersten Verbinden?
2. Welche Datei verlässt deinen Rechner nie?
3. Wo hinterlegt der Server die erlaubten öffentlichen Schlüssel eines Benutzers?
4. Welche Aussagen zu ~/.ssh stimmen? (mehrere Antworten möglich)
5. In welcher Reihenfolge sicherst du sshd ab?