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/