SSH Keys (Teil 2 / mit CA)

Datum

Wie man sich recht einfach und schnell Schlüsselpaar erstellt, mit welchem man sich dann bequem per SSH einloggen kann haben wir bereits im ersten Teil gesehen.
Dieses Verfahren ist leider nicht besonders praktikabel wenn es um eine größere Infrastruktur geht und hier lässt sich auch schlecht festlegen das ein Benutzer sich z.B.: auf die Webserver einloggen darf aber nicht auf die Datenbank-Server.
Man kann auch zentrale Benutzerverwaltungen wie LDAP und/oder Kerberos verwenden, allerdings ist der Impact recht groß wenn solche Dienste mal nicht erreichbar sind.

Eine gute Idee ist es hier sich eine eigene CA1 anzulegen, welche die SSH-Keys dann signieren und somit vertrauenswürdig machen kann.
Dieses Prinzip ist an die Funktionsweise von HTTPS2 angelehnt.

Die Inspiration mich mit dieser Art der Zugriffskontrolle zu beschäftigen kam von einem gut gemachten Blog-Artikel3, aus welchem ich die Basis-Konfiguration entnehme.

Anlegen der CA

umask 77  # you really want to protect this :-)
mkdir ~/my-ca && cd ~/my-ca
ssh-keygen -C CA -f ca

Auch empfiehlt es sich ein entsprechendes Passwort zu setzen.
Wie bei jeder „normalen“ Erstellung eines Schlüsselpaares erhalten wir 2 Dateien:
ca ist dabei der private Schlüssel
ca.pub ist der öffentlich Schlüssel, die Betonung liegt hier tatsächlich auf öffentlich. D.h. dieser Schlüssel wird auf alle entsprechenden Systeme verteilt, idealerweise nach /etc/ssh/ca.pub und die Berechtigungen sollten 0644 sein.

Nun muss noch die globale SSH-Konfiguration unter /etc/ssh/sshd_config angepasst werden, indem man folgende Zeile hinzufügt:
TrustedUserCAKeys /etc/ssh/ca.pub

Im Grunde haben nun schon unsere „Chain of Trust“ mit der wir nun SSH-Keys signieren können.
Als wichtige Sicherheitsmaßnahme wäre noch zu nennen, dass der private Key niemals das System verlassen sollte auf dem er generiert wurde.

Signieren eines Schlüssels

Auf einem anderen System erstellen wir uns nun ein „normales“ SSH-Schlüsselpaar:

ssh-keygen -t ecdsa  # oder -t rsa
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/mfdutra/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):***
Enter same passphrase again:***
Your identification has been saved in /home/mfdutra/.ssh/id_ecdsa.
Your public key has been saved in /home/mfdutra/.ssh/id_ecdsa.pub.
...

im ~/.ssh Ordner sollten sich nun 2 neue Dateien befinden: id_ecdsa und id_ecdsa.pub.
Den öffentlichen Schlüssel (id_ecdsa.pub) kopieren wir nun auf den Server wo sich die CA befindet, dies kann z.B. per scp realisiert werden.

Nun signieren wir diesen öffentlichen Schlüssel:
ssh-keygen -s ca -I rasputin -n root -V +1w -z 1 id_ecdsa.pub
-s gibt die gewünschte ca an
-I bestimmt die Zertifikats-ID
-n gibt die (es können mehrere sein) principals an (dazu später mehr)
-V bestimmt die Dauer der Gültigkeit
-z ist die Seriennummer, diese sollte immer einmalig sein da man diese später in den Logs findet und darüber eindeutig den entsprechenden SSH-Key identifizieren kann

Bsp.:

ssh-keygen -s ca -I rasputin -n root -V +1w -z 1 id_ecdsa.pub
Enter passphrase: 
Signed user key id_ecdsa-cert.pub: id "rasputin" serial 1 for root valid from 2017-12-17T03:18:00 to 2017-12-24T03:19:29

Um sich die Details noch einmal anzeigen zu lassen, verwendet man einfach den Befehl ssh-keygen -Lf
Bsp.:

ssh-keygen -Lf id_ecdsa-cert.pub                                                                      
id_ecdsa-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
        Public key: ECDSA-CERT SHA256:Tx/MnT+SrXHLjTFkjl+1e1pWQHSwTPPzGKyqDjrz5DI
        Signing CA: RSA SHA256:oO/JSJHA/YJ6qUYiVM2e0lDbXORq+D3vVReck/ElF4A
        Key ID: "rasputin"
        Serial: 2
        Valid: from 2017-12-15T21:21:00 to 2017-12-22T21:22:12
        Principals: 
                root
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Nachdem die Datei id_ecdsa-cert.pub wieder zurück auf ursprüngliche System kopiert wurde, idealerweise in den Ordner in welchem sich der public- und der private-key befinden, sollte man jetzt in der Lage sein sich auf anderen Systemen, welche die CA per Konfiguration aktzeptieren, erfolgreich ohne Passwort einzuloggen.

Und sofern eine eindeutige Seriennummer vergeben wurde kann man anhand der Logeinträge immer eindeutig erkennen wer sich auf dem System eingeloggt hat.

Accepted publickey for root from 192.168.2.43 port 50202 ssh2: ECDSA-CERT ID rasputin (serial 1) CA RSA SHA256:oO/JSJHA/YJ6qUYiVM2e0lDbXORq+D3vVReck/ElF4A

Einrichten der „Principals“

Nun wollen wir uns ein paar Sicherheitszonen einrichten, z.B.: zone-webserver, zone-database and root-everywhere.

Als Vorbereitung muss auf den entsprechenden Systemen folgende Zeile in die globale SSH-Konfiguration /etc/ssh/sshd_config eingetragen werden:
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

Einrichten der entsprechenden Datei:

mkdir /etc/ssh/auth_principals 
echo -e 'zone-webservers\nroot-everywhere' > /etc/ssh/auth_principals/root

So kann der Zugriff für jeden Systembenutzer per eigener Datei geregelt werden.
Die Zone root-everywhere ist hierbei, wie der Name schon vermuten lässt, der volle root-Zugriff. Diese Option ist einfacher zu in der Anwendung als jede einzelne Sicherheitszone einzeln in der entsprechenden Datei einzutragen.
Lädt man nun die neue SSH-Konfiguration und versucht sich mit dem vorher generierten SSH-Key einzuloggen dürfte dies nicht mehr funktionieren und es gibt folgende Fehlermeldung: error: Certificate does not contain an authorized principal.

Also signieren wir nun einen Schlüssel mit den entsprechenden „Principals“:
ssh-keygen -s ca -I rasputin -n zone-webservers -V +1w -z 2 id_ecdsa.pub

Nun sollte auch das Einloggen wieder funktionieren…

Widerrufen von SSH-Zertifikaten

OpenSSH besitzt leider keinen Automatismus, welche eine entsprechende revocation list automatisch entsprechend verteilt wenn mal ein Zertifikat für ein SSH-Schlüssel widerrufen werden soll.
Allerdings ist es einfacher eine entsprechende Liste auf den entsprechenden Systemen auszurollen als jedes mal eine neue CA anzulegen und den Key zu verteilen.

Die Liste mit den widerrufenen Schlüsseln trägt man in die globale SSH-Konfiguration in /etc/ssh/sshd_config ein:
RevokedKeys /etc/ssh/revoked_keys
Achtung: Wenn diese Datei nicht lesbar ist, ist keine Anmeldung per SSH-Keys möglich.

Eine neue Liste kann folgendermaßen erstellt werden:
ssh-keygen -kf /etc/ssh/revoked_keys -z 1 ~/.ssh/id_rsa.pub

Um weitere Zeilen hinzuzufügen verwendet man -u.
Bsp.:
ssh-keygen -ukf /etc/ssh/revoked_keys -z integer ~/.ssh/id_rsa.pub
wo integer die entsprechende Zeilennummer ist

Um zu überprüfen ob ein bestimmter SSH-Keys widerrufen wurde, kann man folgenden Befehl verwenden:
ssh-keygen -Qf /etc/ssh/revoked_keys ~/.ssh/id_rsa.pub

1 https://de.wikipedia.org/wiki/Zertifizierungsstelle

2 https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure

3 https://code.facebook.com/posts/365787980419535/scalable-and-secure-access-with-ssh/

Autor
Kategorien Server, Linux

PRTG Map