ADMIN

2024

04

2024-03-27T12:00:00

Small-Business-IT

PRAXIS

060

Open-Source-Tipp

Sicherheit

Verschlüsselung

SSH-Host-Keys konfigurieren

Der passende Schlüssel

von Thorsten Scherf

Veröffentlicht in Ausgabe 04/2024 - PRAXIS

Die Secure-Shell kommt immer dann zum Einsatz, wenn ein sicherer Zugang zu einem entfernten Rechner notwendig ist. Die Auswahl der kryptographischen Funktionen spielt für die sichere Konfiguration des Services eine wichtige Rolle. Der Open-Source-Tipp in diesem Monat wirft hierfür einen näheren Blick auf die Konfiguration der SSH-Host-Schlüssel.

Die SSH-Protokollarchitektur besteht im Grunde aus drei unterschiedlichen Spezifikationen. Das Transport Layer Protocol ist für die Authentisierung des Servers, die eigentliche Verschlüsselung zwischen Client und Server sowie die Sicherstellung der Datenintegrität zuständig. Wie Benutzer sich gegenüber dem Server authentisieren können, ist im User Authentication Protocol definiert. Und schließlich regelt das Connection Protocol, wie verschlüsselte Tunnel innerhalb einer Verbindung zwischen Client und Server aufgebaut werden – dies ist gerade dann interessant, wenn Sie andere Protokolle durch einen SSH-Tunnel weiterleiten möchten.
In diesem Artikel geht es primär um das SSH Transport Layer Protocol und die dort beschriebene Authentisierung des Servers und die damit verbundenen kryptografischen Einstellungen.
Verbindungsstufen
Baut ein Client eine neue TCP-Verbindung zu einem Server auf, müssen sich beide Seiten zuerst auf eine Protokollversion einigen. Da die SSH Version 1 als nicht mehr sicher gilt, sollte also eine Einigung auf die Version 2 stattfinden. Diese wird von sämtlichen aktuellen SSH-Implementierungen unterstützt. Im nächsten Schritt authentisiert sich der Server mithilfe seines Host-Keys gegenüber dem Client.
Die SSH-Protokollarchitektur besteht im Grunde aus drei unterschiedlichen Spezifikationen. Das Transport Layer Protocol ist für die Authentisierung des Servers, die eigentliche Verschlüsselung zwischen Client und Server sowie die Sicherstellung der Datenintegrität zuständig. Wie Benutzer sich gegenüber dem Server authentisieren können, ist im User Authentication Protocol definiert. Und schließlich regelt das Connection Protocol, wie verschlüsselte Tunnel innerhalb einer Verbindung zwischen Client und Server aufgebaut werden – dies ist gerade dann interessant, wenn Sie andere Protokolle durch einen SSH-Tunnel weiterleiten möchten.
In diesem Artikel geht es primär um das SSH Transport Layer Protocol und die dort beschriebene Authentisierung des Servers und die damit verbundenen kryptografischen Einstellungen.
Verbindungsstufen
Baut ein Client eine neue TCP-Verbindung zu einem Server auf, müssen sich beide Seiten zuerst auf eine Protokollversion einigen. Da die SSH Version 1 als nicht mehr sicher gilt, sollte also eine Einigung auf die Version 2 stattfinden. Diese wird von sämtlichen aktuellen SSH-Implementierungen unterstützt. Im nächsten Schritt authentisiert sich der Server mithilfe seines Host-Keys gegenüber dem Client.
Beim ersten Verbindungsaufbau muss der Client diesen zwingend verifizieren, um somit sicherzustellen, dass eine Kommunikation mit dem korrekten Server erfolgt. Der Abgleich findet dabei mittels eines Fingerprints statt. Im Anschluss einigen sich Server und Client auf einen Session-Key, der zur Verschlüsselung der Verbindung zum Einsatz kommt. Um diesen gemeinsamen Schlüssel auszutauschen, kommt der Diffie-Hellman-Algorithmus zum Einsatz. Erst danach erfolgt die Authentisierung des Benutzers gegenüber dem Server.
Übersicht der Konfigurationseinstellungen
An dieser Stelle weisen wir darauf hin, dass auf Systemen, die mit Crypto-Policies [1] arbeiten, sämtliche Crypto-relevanten Einstellungen über eben diese Policies definiert werden und die Settings somit nicht Teil der OpenSSH-Konfigurationsdatei "/etc/ssh/sshd_config" sind. Bevor nun aber überhaupt irgendwelche Änderungen an der Konfiguration eines SSH-Servers vorgenommen werden, sollten Sie sich einen kompletten Überblick über die aktuellen Einstellungen verschaffen. Auf einem System, auf dem die OpenSSH Software läuft, zeigt Ihnen der Aufruf sämtliche Einstellungen an.
Über die Einstellung "Ciphers" legen Sie den Algorithmus für den symmetrischen Sitzungsschlüssel fest. Der AES-Algorithmus ist hier Standard, allerdings sollten Sie auf den Einsatz von Cipher Block Chaining (CBC) verzichten, da es hier zu Problemen beim Padding von Textblöcken kommen kann. Die Algorithmen für die digitalen Signaturverfahren setzen Sie über die Anweisungen "HostKeyAlgorithm", "PubkeyAcceptedAlgorithms" und "HostbasedAcceptedAlgorithms".
Der Edwards-Curve Digital Signature Algorithm 25519 (Ed25519) ist hier sicherlich die erste Wahl, wenn es um das Thema Sicherheit geht. Allerdings kann es hiermit Kompatibilitätsproblemen mit älteren Clients geben, sodass eine Variante des Digital Signature Algorithm in Verbindung mit elliptischen Kurven (ECDSA) wahrscheinlich eine bessere Wahl wäre. OpenSSH unterstützt von Haus aus unterschiedliche elliptische Kurven, wobei nist256 standardmäßig zum Einsatz kommt, wenn Sie mittels "ssh-keygen" einen neuen Host-Schlüssel erzeugen.
Host-Schlüssel
Tatsächlich ist es jedoch auch so, dass "ssh-keygen" beim ersten Start des Services mehrere Host-Schlüssel anlegt, sollten noch keine vorhanden sein. Im Quellcode zu "ssh-keygen" [2] sind die Standardwerte für die RSA-Schlüssel (3072) und die ECDSA Kurve (nist256) hinterlegt. Natürlich haben Sie die Möglichkeit, das Tool manuell aufzurufen, um somit neue Schlüssel in der gewünschten Bit-Länge zu erzeugen. Soll dieser Vorgang aber automatisch beim ersten Start des Services oder der Installation des Systems erfolgen, müssen Sie hierfür ein wenig in die Trickkiste greifen.
Starten Sie den OpenSSH-Server mithilfe des systemd-Services (systemctl start sshd), wird automatisch auch der sshd-keygen-Service aktiviert (Listing 1). In der Datei ist das Shell-Skript "/usr/libexec/openssh/ sshd-keygen" aus Listing 2 angegeben, das sich um das Anlegen von unterschiedlichen Host-Keys (Listing 3) kümmert.
Listing 1: sshd-keygen-Service wird automatisch aktiviert
@.service
### Die systemd Unit-Datei kümmert sich darum Host-Schlüssel für den OpenSSH-Services zu erzeugen.
[Unit]
Description=OpenSSH %i Server Key Generation
ConditionFileNotEmpty=|!/etc/ssh/ssh_host_%i_key
[Service]
Type=oneshot
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/libexec/openssh/sshd-keygen %i
[Install]
WantedBy=sshd-keygen.target
Listing 2: Shell-Skript "/usr/libexec/openssh/sshd-keygen"
### Shell-Skript zum Erzeugen von SSH Host-Schlüsseln.
#!/usr/bin/bash
# Host-Schlüssel für den OpenSSH-Server erzeugen.
KEYTYPE=$1
case $KEYTYPE in
"dsa") ;& # disabled in FIPS "ed25519")
    FIPS=/proc/sys/crypto/fips_enabled if [[ -r "$FIPS" && $(cat $FIPS) == "1"
    ]]; then
        exit 0
      fi ;;
    "rsa") ;; # always ok
    "ecdsa") ;;
    *) # wrong argument
        exit 12 ;;
esac
KEY=/etc/ssh/ssh_host_${KEYTYPE}_key
KEYGEN=/usr/bin/ssh-keygen
if [[ ! -x $KEYGEN ]]; then
    exit 13
fi
# Alte Schlüssel entfernen
rm -f $KEY{,.pub}
# Neue Schlüssel erzeugen
if ! $KEYGEN -q -t $KEYTYPE -f $KEY -C '' -N '' >&/dev/null; then
        exit 1
fi
# Berechtigungen einstellen
/usr/bin/chmod 600 $KEY
/usr/bin/chmod 644 $KEY.pub
if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub}
fi
exit 0
Listing 3: Anlegen unterschiedlicher Host-Keys
## Die systemd target-Datei bestimmt, welche Host-Schlüssel im Detail erzeugt werden sollen.
  [Unit]
Wants=sshd-keygen@rsa.service
Wants=sshd-keygen@ecdsa.service
Wants=sshd-keygen@ed25519.service
Neue Schlüssel
Das folgende Beispiel zeigt, dass für den ECDSA-Schlüssel die nist256-Kurve zum Einsatz kam, genau so wie es im Source-Code hinterlegt ist:
ssh-keygen -l -f ssh_host_ecdsa_key.pub
256 SHA256:s92wvduCFEdcPC/ybbIymBa0pTlQZ7YCfFXrsfyChSQ no comment (ECDSA)
Wollen Sie nun aber standardmässig die nist521-Kurve verwenden, müsste der manuelle ssh-keygen Aufruf wie folgt aussehen:
ssh-keygen -t ecdsa -b 521 -N '' -C '' -f ssh_host_ecdsa_key-521
Eine kurze Überprüfung bestätigt, dass nun die nist521-Kurve verwendet wird:
ssh-keygen -l -f ssh_host_ecdsa_key-521.pub
521 SHA256:V08kcVRWP+6lBR4pun/uVVI3RZul7yhmxFSrzATnjd8 no comment (ECDSA)
Um das ganze nun zu automatisieren, erzeugen Sie eine Kopie der "sshd-keygen@.service"-Datei und des "sshd-keygen"-Shell-Skripts – das Sie aber nicht mit dem Programm "/usr/bin/ssh-keygen" verwechseln dürfen. Erzeugen Sie zuerst eine Kopie des Shell-Skripts und ändern dieses so ab, dass die Host-Schlüssel in der von Ihnen gewünschten Länge erzeugt werden:
cp /usr/libexec/openssh/sshd-keygen /usr/local/sbin/
Dann legen Sie eine Kopie der systemd-Unit-Datei an, ändern die "ExecStart"-Zeile so ab, dass diese nun auf das von Ihnen soeben modifizierte Shell-Skript zeigt und laden die systemd-Konfiguration einmal neu:
cp /usr/lib/systemd/system/sshd-keygen@.service /etc/systemd/system
systemctl daemon-reload
Bauen Sie diese Änderung nun in Ihre Automatisierung zur Provisionierung von neuen Systemen, beispielsweise mithilfe von Ansible oder Puppet, ein, stehen Ihnen die gewünschten Host-Keys unmittelbar nach der Installation und Konfiguration eines neuen Systems zur Verfügung.
Fazit
Um Host-Schlüssel in der gewünschten Länge direkt bei der Systeminstallation zu erzeugen, müssen Sie ein wenig in die Trickkiste greifen. Das hier vorgestellte Beispiel basiert auf einem modifiziertem Shell-Skript das die OpenSSH-systemd-Unit-Datei aufgeruft, um somit neue Host-Schlüssel zu erzeugen.
(dr)
Link-Codes