Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SSH-Keys

SSH-Keys ermöglichen sichere, passwortlose Authentifizierung bei Remote-Servern. Sie sind sicherer als Passwörter und essentiell für automatisierte Workflows.

1 SSH-Keys erstellen & verwalten

1.1 Funktionsweise

SSH verwendet asymmetrische Kryptografie:

SchlüsselDateiVerbleibFunktion
Private Key~/.ssh/id_ed25519Lokal (geheim!)Zum Signieren
Public Key~/.ssh/id_ed25519.pubServerZum Verifizieren

Der Private Key verlässt niemals den lokalen Rechner. Der Public Key wird auf alle Server kopiert, zu denen man sich verbinden möchte.

1.2 Algorithmen

AlgorithmusEmpfehlungAnmerkung
Ed25519✅ EmpfohlenModern, schnell, sicher, kurze Keys
RSA⚠️ AkzeptabelMindestens 4096 Bit, für ältere Systeme
ECDSA❌ VermeidenPotenzielle Schwächen
DSA❌ VeraltetNicht mehr verwenden

1.3 Key erstellen

Ed25519 (empfohlen):

ssh-keygen -t ed25519 -C "kommentar@example.com"

RSA (für Kompatibilität):

ssh-keygen -t rsa -b 4096 -C "kommentar@example.com"

Interaktiver Dialog:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/max/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/max/.ssh/id_ed25519
Your public key has been saved in /Users/max/.ssh/id_ed25519.pub

Optionen:

OptionBeschreibung
-t TYPEAlgorithmus (ed25519, rsa, ecdsa)
-b BITSSchlüssellänge (nur RSA: 4096)
-C "text"Kommentar (meist E-Mail)
-f DATEIAusgabedatei
-N "phrase"Passphrase (leer = keine)

Beispiele:

# Standard Ed25519 Key
ssh-keygen -t ed25519 -C "max@example.com"

# Key mit bestimmtem Namen
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_ed25519

# Key ohne Passphrase (für Automatisierung)
ssh-keygen -t ed25519 -C "automation" -f ~/.ssh/automation -N ""

# RSA Key für ältere Systeme
ssh-keygen -t rsa -b 4096 -C "legacy-server" -f ~/.ssh/legacy_rsa

1.4 Passphrase

Die Passphrase verschlüsselt den Private Key:

Mit PassphraseOhne Passphrase
Key ist verschlüsseltKey ist unverschlüsselt
Bei Diebstahl geschütztSofort nutzbar bei Diebstahl
Muss bei Verwendung eingegeben werdenKeine Eingabe nötig
SSH-Agent speichert temporärFür Automatisierung geeignet

Empfehlung: Immer Passphrase verwenden, SSH-Agent für Komfort nutzen.

Passphrase ändern:

ssh-keygen -p -f ~/.ssh/id_ed25519

1.5 Dateien und Berechtigungen

Standard-Speicherort: ~/.ssh/

DateiBeschreibungBerechtigung
id_ed25519Private Key600 (nur Besitzer)
id_ed25519.pubPublic Key644 (lesbar)
authorized_keysErlaubte Keys600
known_hostsBekannte Server644
configSSH-Konfiguration600

Berechtigungen setzen:

# Verzeichnis
chmod 700 ~/.ssh

# Private Keys
chmod 600 ~/.ssh/id_*
chmod 600 ~/.ssh/*_ed25519
chmod 600 ~/.ssh/*_rsa

# Public Keys
chmod 644 ~/.ssh/*.pub

# Konfigurationsdateien
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts

SSH verweigert Keys mit zu offenen Berechtigungen!

1.6 Public Key auf Server kopieren

Methode 1: ssh-copy-id (empfohlen)

ssh-copy-id user@server

# Bestimmten Key
ssh-copy-id -i ~/.ssh/github_ed25519.pub user@server

Methode 2: Manuell

# Public Key anzeigen
cat ~/.ssh/id_ed25519.pub

# Auf Server: Key in authorized_keys einfügen
ssh user@server
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "PUBLICKEY" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Methode 3: Einzeiler

cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

1.7 Keys verwalten

Alle Keys auflisten:

ls -la ~/.ssh/

# Fingerprints anzeigen
for key in ~/.ssh/id_*; do
    [-f "$key" && "$key" != *.pub](-f%20"$key"%20&&%20"$key"%20!=%20*.pub.md) && ssh-keygen -lf "$key"
done

Key-Fingerprint anzeigen:

# MD5 (älteres Format)
ssh-keygen -l -E md5 -f ~/.ssh/id_ed25519.pub

# SHA256 (Standard)
ssh-keygen -l -f ~/.ssh/id_ed25519.pub

Public Key aus Private Key extrahieren:

ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub

Key löschen:

# Beide Dateien entfernen
rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub

# Aus authorized_keys auf Server entfernen
ssh user@server
nano ~/.ssh/authorized_keys  # Zeile entfernen

1.8 Mehrere Keys

Für verschiedene Zwecke separate Keys erstellen:

# Persönlicher Key
ssh-keygen -t ed25519 -C "personal" -f ~/.ssh/personal_ed25519

# Arbeit
ssh-keygen -t ed25519 -C "work" -f ~/.ssh/work_ed25519

# GitHub
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_ed25519

# Automation (ohne Passphrase)
ssh-keygen -t ed25519 -C "automation" -f ~/.ssh/automation_ed25519 -N ""

Die Zuordnung erfolgt über ~/.ssh/config (siehe Abschnitt 5.2).

2 SSH-Konfiguration (~/.ssh/config)

Die SSH-Konfiguration vereinfacht Verbindungen und ermöglicht hostspezifische Einstellungen.

2.1 Grundstruktur

Host ALIAS
    Option Wert
    Option Wert

Einfaches Beispiel:

Host server
    HostName 192.168.1.100
    User admin
    Port 22

Statt ssh admin@192.168.1.100 genügt nun ssh server.

2.2 Wichtige Optionen

OptionBeschreibungBeispiel
HostAlias oder Patternserver, *.example.com
HostNameEchter Hostname/IP192.168.1.100
UserBenutzernameadmin
PortSSH-Port22, 2222
IdentityFilePrivate Key~/.ssh/work_ed25519
IdentitiesOnlyNur angegebene Keysyes
ForwardAgentAgent-Forwardingyes
ProxyJumpJump-Hostbastion
LocalForwardPort-Forwarding lokal8080 localhost:80
RemoteForwardPort-Forwarding remote9090 localhost:8080
ServerAliveIntervalKeep-alive Intervall60
ServerAliveCountMaxKeep-alive Versuche3
CompressionKomprimierungyes
AddKeysToAgentKey zum Agentyes
UseKeychainmacOS Keychainyes

2.3 Vollständige Beispielkonfiguration

# ~/.ssh/config

# === Globale Einstellungen ===
Host *
    AddKeysToAgent yes
    UseKeychain yes
    IdentitiesOnly yes
    ServerAliveInterval 60
    ServerAliveCountMax 3

# === Arbeit ===
Host work
    HostName work-server.company.com
    User max.mustermann
    IdentityFile ~/.ssh/work_ed25519

Host work-*
    User max.mustermann
    IdentityFile ~/.ssh/work_ed25519

Host work-web
    HostName 10.0.1.10

Host work-db
    HostName 10.0.1.20

Host work-app
    HostName 10.0.1.30

# === Persönlich ===
Host home
    HostName home.dyndns.org
    User max
    Port 2222
    IdentityFile ~/.ssh/personal_ed25519

Host pi
    HostName 192.168.1.50
    User pi
    IdentityFile ~/.ssh/personal_ed25519

# === GitHub ===
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_ed25519

# Zweiter GitHub Account
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/work_github_ed25519

# === GitLab ===
Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/gitlab_ed25519

# === Jump Host / Bastion ===
Host bastion
    HostName bastion.company.com
    User jump
    IdentityFile ~/.ssh/work_ed25519

Host internal-*
    ProxyJump bastion
    User admin
    IdentityFile ~/.ssh/work_ed25519

Host internal-web
    HostName 10.10.1.10

Host internal-db
    HostName 10.10.1.20

# === Port Forwarding ===
Host tunnel-db
    HostName dbserver.company.com
    User admin
    LocalForward 5432 localhost:5432
    IdentityFile ~/.ssh/work_ed25519

# === Alte/Legacy Server ===
Host legacy
    HostName old-server.example.com
    User root
    IdentityFile ~/.ssh/legacy_rsa
    PubkeyAcceptedAlgorithms +ssh-rsa
    HostkeyAlgorithms +ssh-rsa

2.4 Wildcards und Patterns

PatternBeschreibung
*Beliebige Zeichen
?Ein beliebiges Zeichen
!Negation
# Alle Hosts
Host *
    ServerAliveInterval 60

# Alle .company.com Hosts
Host *.company.com
    User admin
    IdentityFile ~/.ssh/work_ed25519

# Alle außer bestimmte
Host * !github.com !gitlab.com
    IdentityFile ~/.ssh/default_ed25519

2.5 Jump Hosts (ProxyJump)

Verbindung über einen Zwischenserver (Bastion Host):

# Klassisch (alt)
Host internal
    ProxyCommand ssh -W %h:%p bastion

# Modern (empfohlen)
Host internal
    ProxyJump bastion

Mehrere Hops:

Host deep-internal
    ProxyJump bastion,middle-server

Kommandozeile:

ssh -J bastion internal-server
ssh -J bastion,middle deep-server

2.6 Port Forwarding

Local Forward (Zugriff auf Remote-Dienst):

# Remote-Datenbank lokal verfügbar machen
Host tunnel-postgres
    HostName dbserver.com
    LocalForward 5432 localhost:5432
ssh tunnel-postgres
# Dann: psql -h localhost -p 5432

Remote Forward (Lokalen Dienst remote verfügbar):

# Lokalen Webserver remote verfügbar machen
Host expose-local
    HostName server.com
    RemoteForward 8080 localhost:3000

Dynamic Forward (SOCKS Proxy):

Host socks-proxy
    HostName server.com
    DynamicForward 1080
ssh socks-proxy
# Browser: SOCKS5 Proxy auf localhost:1080

2.7 Mehrere GitHub/GitLab Accounts

# Persönlicher GitHub Account
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_personal

# Arbeits-GitHub Account
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_work

Verwendung:

# Persönlich (Standard)
git clone git@github.com:user/repo.git

# Arbeit
git clone git@github-work:company/repo.git

# In bestehendem Repo Remote ändern
git remote set-url origin git@github-work:company/repo.git

2.8 Reihenfolge und Priorität

SSH liest die Config von oben nach unten. Der erste Match für jede Option gewinnt.

# RICHTIG: Spezifisch vor allgemein
Host work-server
    User admin

Host *
    User default

# FALSCH: Allgemein überschreibt spezifisch
Host *
    User default

Host work-server
    User admin  # Wird ignoriert!

Empfohlene Struktur:

  1. Spezifische Hosts
  2. Gruppen-Patterns (work-*, *.company.com)
  3. Globale Einstellungen (Host *)

3 SSH-Agent, Konfiguration und Sicherheit

3.1 SSH-Agent Grundlagen

Der SSH-Agent speichert entschlüsselte Private Keys im Speicher, sodass die Passphrase nicht bei jeder Verbindung eingegeben werden muss.

Funktionsweise:

┌─────────────────────────────────────────────────────┐
│                    SSH-Agent                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│  │ Key 1       │  │ Key 2       │  │ Key 3       │  │
│  │ (entschl.)  │  │ (entschl.)  │  │ (entschl.)  │  │
│  └─────────────┘  └─────────────┘  └─────────────┘  │
└─────────────────────────────────────────────────────┘
        ↑                   ↑                ↑
   ssh server1         ssh server2      git push
   (kein Passwort)     (kein Passwort)  (kein Passwort)

3.2 Agent unter macOS

macOS startet den SSH-Agent automatisch. Die Integration mit der Keychain speichert Passphrasen dauerhaft.

Keychain-Integration aktivieren:

# ~/.ssh/config
Host *
    AddKeysToAgent yes
    UseKeychain yes

Key manuell zur Keychain hinzufügen:

# Key zum Agent hinzufügen (Passphrase in Keychain speichern)
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# Alle Standard-Keys laden
ssh-add --apple-load-keychain

warning

Ältere macOS-Versionen verwenden -K statt --apple-use-keychain und -A statt --apple-load-keychain.

3.3 Agent-Befehle

BefehlBeschreibung
ssh-addStandard-Keys hinzufügen
ssh-add DATEIBestimmten Key hinzufügen
ssh-add -lGeladene Keys auflisten
ssh-add -LPublic Keys der geladenen Keys
ssh-add -d DATEIKey entfernen
ssh-add -DAlle Keys entfernen
ssh-add -t SEKUNDENKey mit Zeitlimit

Beispiele:

# Key hinzufügen
ssh-add ~/.ssh/work_ed25519

# Alle Keys anzeigen
ssh-add -l

# Key für 1 Stunde hinzufügen
ssh-add -t 3600 ~/.ssh/sensitive_ed25519

# Alle Keys entfernen (Sicherheit)
ssh-add -D

3.4 Agent Forwarding

Agent Forwarding erlaubt die Nutzung lokaler Keys auf Remote-Servern, ohne die Keys dorthin zu kopieren.

Lokal          →     Server A     →     Server B
(Agent mit Keys)     (kein Key)        (kein Key)
                     nutzt lokalen     nutzt lokalen
                     Agent             Agent via A

Aktivieren:

# ~/.ssh/config
Host trusted-server
    ForwardAgent yes

Oder per Kommandozeile:

ssh -A trusted-server

caution

Agent Forwarding nur für vertrauenswürdige Server aktivieren! Ein kompromittierter Server könnte den Agent missbrauchen.

Sicherer: ProxyJump statt Agent Forwarding

Host internal
    ProxyJump bastion

ProxyJump ist sicherer, da der Zwischenserver keinen Zugriff auf den Agent erhält.

3.5 Sicherheits-Best-Practices

Key-Management:

PraxisBeschreibung
Passphrase verwendenSchützt bei Diebstahl des Keys
Separate KeysPro Zweck/Dienst eigene Keys
Ed25519 verwendenModernster, sicherster Algorithmus
Keys rotierenRegelmäßig neue Keys erstellen
Alte Keys entfernenNicht mehr benötigte Keys löschen

Berechtigungen:

# Einmalig: Alle Berechtigungen korrekt setzen
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_* ~/.ssh/config ~/.ssh/authorized_keys
chmod 644 ~/.ssh/*.pub ~/.ssh/known_hosts

authorized_keys absichern:

# Optionen vor dem Key einschränken
# In ~/.ssh/authorized_keys auf dem Server:

# Nur von bestimmter IP
from="192.168.1.100" ssh-ed25519 AAAA... user@host

# Kein Agent-Forwarding, kein PTY
no-agent-forwarding,no-pty ssh-ed25519 AAAA... automation@host

# Nur bestimmten Befehl erlauben
command="/usr/local/bin/backup.sh" ssh-ed25519 AAAA... backup@host

# Kombination
from="10.0.0.*",no-agent-forwarding,no-port-forwarding ssh-ed25519 AAAA...

Verfügbare Optionen:

OptionBeschreibung
from="PATTERN"Nur von bestimmten IPs/Hosts
command="CMD"Nur diesen Befehl ausführen
no-agent-forwardingAgent-Forwarding verbieten
no-port-forwardingPort-Forwarding verbieten
no-ptyKein Terminal (nur Befehle)
no-X11-forwardingX11-Forwarding verbieten
environment="VAR=val"Umgebungsvariable setzen

3.6 known_hosts

Die Datei ~/.ssh/known_hosts speichert Fingerprints bekannter Server und schützt vor Man-in-the-Middle-Angriffen.

Erste Verbindung:

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

Fingerprint verifizieren:

# Auf dem Server
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

# Vergleichen mit angezeigtem Fingerprint

Host entfernen (bei legitimem Key-Wechsel):

ssh-keygen -R server.com
ssh-keygen -R 192.168.1.100

Hashed known_hosts (mehr Privatsphäre):

# ~/.ssh/config
Host *
    HashKnownHosts yes

3.7 Server-Konfiguration (sshd_config)

Auf dem Server in /etc/ssh/sshd_config:

# Nur Key-Authentifizierung
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no

# Root-Login verbieten oder einschränken
PermitRootLogin no
# Oder: PermitRootLogin prohibit-password

# Nur bestimmte User erlauben
AllowUsers admin deploy

# Nur bestimmte Gruppen
AllowGroups sshusers

# Agent-Forwarding global deaktivieren
AllowAgentForwarding no

# Idle-Timeout
ClientAliveInterval 300
ClientAliveCountMax 2

# Sichere Algorithmen (modern)
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Nach Änderungen:

# Syntax prüfen
sudo sshd -t

# Dienst neu starten
sudo systemctl restart sshd
# Oder macOS:
sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd

3.8 Troubleshooting

Verbindung debuggen:

# Verbose-Modus
ssh -v user@server      # Level 1
ssh -vv user@server     # Level 2
ssh -vvv user@server    # Level 3 (sehr detailliert)

Häufige Probleme:

ProblemUrsacheLösung
Permission denied (publickey)Key nicht akzeptiertKey in authorized_keys prüfen
Bad permissionsFalsche Dateirechtechmod 600 ~/.ssh/id_*
Host key verification failedServer-Key geändertssh-keygen -R host
Connection refusedSSH nicht aktiv / PortFirewall, sshd-Status prüfen
Too many authentication failuresZu viele Keys probiertIdentitiesOnly yes

Agent prüfen:

# Agent läuft?
echo $SSH_AUTH_SOCK

# Keys geladen?
ssh-add -l

# Agent neu starten (falls nötig)
eval $(ssh-agent -s)
ssh-add

Berechtigungen prüfen:

# Lokal
ls -la ~/.ssh/

# Auf Server
ls -la ~/.ssh/
ls -la ~/.ssh/authorized_keys

3.9 Nützliche Aliase und Funktionen

# ~/.zshrc

# SSH-Key Fingerprints anzeigen
alias ssh-fingerprints='for key in ~/.ssh/id_*; do [-f "$key" && "$key" != *.pub](-f%20"$key"%20&&%20"$key"%20!=%20*.pub.md) && ssh-keygen -lf "$key"; done'

# Neuen Ed25519 Key erstellen
ssh-newkey() {
    local name="${1:-id_ed25519}"
    local comment="${2:-$(whoami)@$(hostname)}"
    ssh-keygen -t ed25519 -C "$comment" -f ~/.ssh/"$name"
}

# Key zu Server kopieren
ssh-copykey() {
    local key="${1:-~/.ssh/id_ed25519.pub}"
    local server="$2"
    if [-z "$server"](-z%20"$server".md); then
        echo "Usage: ssh-copykey [keyfile] server"
        return 1
    fi
    ssh-copy-id -i "$key" "$server"
}

# SSH-Verbindung testen
ssh-test() {
    ssh -o BatchMode=yes -o ConnectTimeout=5 "$1" echo "OK" 2>&1
}

3.10 Cheatsheet

Keys erstellen:

ssh-keygen -t ed25519 -C "comment"           Neuer Ed25519 Key
ssh-keygen -t ed25519 -f ~/.ssh/name         Mit bestimmtem Namen
ssh-keygen -p -f ~/.ssh/id_ed25519           Passphrase ändern
ssh-keygen -y -f private > public            Public aus Private
ssh-keygen -lf ~/.ssh/id_ed25519             Fingerprint anzeigen

Keys verteilen:

ssh-copy-id user@server                      Key auf Server kopieren
ssh-copy-id -i ~/.ssh/key.pub user@server    Bestimmten Key kopieren

Agent:

ssh-add                                      Standard-Keys laden
ssh-add ~/.ssh/key                           Bestimmten Key laden
ssh-add -l                                   Geladene Keys anzeigen
ssh-add -d ~/.ssh/key                        Key entfernen
ssh-add -D                                   Alle Keys entfernen
ssh-add --apple-use-keychain ~/.ssh/key      In macOS Keychain (neu)

Verbindung:

ssh server                                   Mit Alias verbinden
ssh -i ~/.ssh/key user@server                Mit bestimmtem Key
ssh -J bastion internal                      Über Jump-Host
ssh -L 8080:localhost:80 server              Local Port Forward
ssh -v server                                Debug-Modus

Wartung:

ssh-keygen -R hostname                       Host aus known_hosts entfernen
chmod 700 ~/.ssh                             Verzeichnis-Berechtigung
chmod 600 ~/.ssh/id_* ~/.ssh/config          Datei-Berechtigungen