Vor einiger Zeit schon habe ich mir vorgenommen etwas darüber zu schreiben, wie ein Webserver abgesichert werden kann. Darum nehme ich die heute kürzlich gestellte Frage zum Anlass endlich damit zu beginnen und fange bei SSH an. Im folgenden beziehe ich mich auf die Implementierung OpenSSH. Die Konfiguration anderer Implementierung wie etwas SSH.com verläuft ähnlich, weicht jedoch im Detail ab.
Bevor wir beginnen, solltest du sicherstellen, dass du eine aktuelle SSH Version benutzt. Unter Debian genügt dazu der Einzeiler apt-get update; apt-get dist-upgrade. Unter anderen Distributionen stehen ähnliche Werkzeuge zum Update zur Verfügung wie etwas yast unter Suse.
Nun ist es an der Zeit die Konfigurationsdatei /etc/ssh/sshd_config zu bearbeiten. Ich werde im folgenden die sicherheitsrelevanten Optionen durchgehen und kurz kommentieren.
ListenAddress 217.79.182.18
Wenn ein Server mit mehr als einem Netzwerkinterface ausgestattet ist, kann es sinnvoll sein den Zugriff bestimmte Interfaces zu beschränken. Beim klassischen Webserver dürfte das allerdings nicht der Fall sein.
Port 2222
Standardmäßig lauscht der SSH-Dämon auf Port 22. Viele Bruteforceattacken gegen ganze Netzwerksegmente können durch Nutzung eines anderen Ports erfolgreich abgewehrt werden. Solche Angriffe gehen meist von Botnetzen oder bereits gekaperten Servern aus, die mit großer Bandbreite tausende Logins gegen Port 22 feuern. Dabei werden Standardbenutzernamen (admin, root, httpd, mail usw.) mit leerem Passwort oder Passwörter aus Wörterbüchern und Passwortlisten durchprobiert. Solche Angriffe können zwar einen sicher konfigurierten Server nicht gefährden, blähen aber die Logdateien auf, führen zu verminderten Reaktionszeiten und schlimmstenfalls können sich legitimierte Benutzer ob der vielen Anfragen nicht über SSH einloggen. Selbstverständlich bietet die Nutzung eines anderen Ports keinen Schutz gegen gezielte Brutforceangriffe, bei denen dem eigentlichen Angriff ein Portscan vorausgeht. Abhilfe können hier zum Beispiel sshblack schaffen oder eine Kombination von Snort, Netfilter und iptables. Da DoS-Attacken kein SSH-spezifisches Problem sind, werde ich an dieser Stelle nicht weiter darauf eingehen.
Protocol 2
Die Version 1 des SSH-Protokoll enthält Designschwächen, die einen unbefugten Login ermöglichen, und sollte darum nicht benutzt werden.
PermitRootLogin no
Es ist eine gute Idee root den Zugang über SSH zu verwehren. Denn wenn jemand gelänge sich über SSH unbefugt Zugang zum Server zu verschaffen, könnte er als unprivilegierter Nutzer nur begrenz Schaden anrichten. Da es ohnehin von Leichtsinn zeugt stets als root zu arbeiten, spricht auch wenig dafür den direkten Login als root zu erlauben. Wichtig ist auf einen frisch installierten System einen neuen Benutzer anzulegen, bevor wir über PermitRootLogin no root vom SSH-Login ausschließen.
AllowUsers tom thomasfalkner@thomas-falkner.de
AllowGroups admin
Wenn nur bestimmte Nutzer sich via SSH auf dem Server einloggen dürfen, können diese über AllowUsers bestimmt werden. Wenn Benutzer nur von einem bestimmten Host aus Zugang zum Rechner erhalten sollen, kann dass über user@host geregelt werden. Das kann sinnvoll sein, wenn ein Webdesigner sich nur aus dem Firmennetzwerk, nicht aber von zu Hause auf dem Server anmelden darf. Durch die Option AllowGroups kann der Login auf bestimmte Benutzergruppen beschränkt werden.
Sollen mehr Benutzer erlaubt als ausgeschlossen werden, ersparen die Gegenstücke zu AllowUsers und AllowGroups, DenyUsers und DenyGroups, eine Menge Tipparbeit.
Doch es ist nicht nur wichtig festzulegen, wer sich über SSH anmelden darf, sondern auch welche Authentifizierungsverfahren dazu genutzt werden sollen. Hier greift die Regle: Alles deaktivieren, was nicht benötigt wird.
Wer mit dem höchsten Sicherheitsstandard arbeiten möchten, sollte ausschließlich die PubKeyAuthentication nutzen und alle anderen Authentifizierungsverfahren ausschalten.
RhostsRSAAuthentication no
HostbasedAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
RSAAuthentication no
Obwohl die meisten Optionen wie etwa RhostsRSAAuthentication per Default abgeschaltet sind, halte ich es für sinnvoll sie explizit auf no zu setzen, um eine klare Konfiguration vor Augen zu haben. Ferner wäre es töricht davon auszugehen, dass die Defaulteinstellungen sich bei neueren Versionen nicht ändern würden. Updates sollten übrigens ohnehin nie ungeprüft eingespielt werden.
Bevor wir die Passwort basierte Anmeldung mittels PasswordAuthentication no und UsePAM no vollständig deaktivieren, muss zuerst die Anmeldung über PubKey konfiguriert und getestet werden – sonst laufen wir Gefahr uns selbst auszusperren.
Dazu ergänzen wir /etc/ssh/sshd_config wie folgt:
PubkeyAuthentication yes
Damit wird die Authentifizierungs per RSA- oder DSA-Schlüssel aktiviert.
AuthorizedKeysFile %h/.ssh/authorized_keys
Gibt an, wo die öffentlichen Schlüssel auf dem Server gespeichert werden.
Per Default im Homeverzeichnis des jeweiligen Benutzers unter .ssh/authorized_keys.
Nun sollte der der SSH-Dämon neu gestartet werden: sudo /etc/init.d/sshd restart
Damit ist der Server vorbereitet für den passwortfreien Login über Schlüssel. Was fehlt ist der Schlüssel, oder genauer gesagt das Schlüsselpaar. Da der private Teil des Schlüssels auf dem Client verbleibt und nur der öffentliche auf den Server kopiert wird, empfiehlt es sich das Schlüsselpaar auf dem Client zu erzeugen. Unter UNIX-Derivaten starten wir dazu unter dem Useraccount, der sich später auf dem Server einloggen können soll, ssh-keygen.
ssh-keygen -t dsa
Wenn die Voreinstellung bestätigt wird, legt ssh-keygen den private Schlüssel id_dsa als auch den öffentlich id_dsa_pub unter ~/.ssh ab. Die Frage nach der Passphrase kann mit 2x Return übergangen werden, wenn man den Schlüssel nicht mit einem Passwort schützen möchte. Eine generelle Empfehlung ob es sinnvoll ist den Schlüssel mit einem Passwort zu schützen oder nicht, ist schwer möglich. Wird kann Passwort vergeben, kann jeder sich auf dem Server anmelden, der in Besitz des Schlüssels ist. Soll heißen: Wird der Rechner, auf dem der private Schlüssel hinterlegt ist geknackt oder gerät in falsche Hände, steht dem Angreifer auch der Zugang zum Server offen.
Sind die Schlüssel mit einem Passwort zusätzlich geschützt, müsste der Angreifer erst das Passwort per Bruteforce knacken – was bei ausreichend starken Passwort nicht in angemessener Zeit möglich ist.
Das höhere Maß an Sicherheit erkauft man sich jedoch mit der lästigen Eingabe des Passworts beim Login über SSH.
Ist der Schlüssel je nach Gusto mit oder ohne Passpharse erzeugt, muss er auf den Server übertragen werden.
Zuerst prüfen wir, ob es in unserem Homeverzeichnis auf dem Server einen Order .ssh bereits gibt. Wenn nicht, legen wir ihn an. Dazu kann folgender Einzeiler vom Client aus abgesetzt werden:
ssh domain.tld -p2222 "test -d .ssh || mkdir .ssh && chmod 700 .ssh"
Wie oben erwähnt, gehe ich davon aus, dass der User auf dem Client den gleichen Namen trägt wie auf dem Server.
Aus Sicherheitsgründen ist es unerlässlich, dass die Zugriffsrechte des .ssh-Verzeichnisses auf 700 und die für authorized_keys auf 600. Ferner müssen sowohl Datei als auch Verzeichnis dem anzumeldenden User gehören.
Letztere Bedingung erfüllen wir, indem wir Verzeichnis und Datei selbst anlegen, die Zugriffsrechte indes sollten wir explizit setzen.
Auch das lässt sich zu einem Befehl zusammenfassen:
cat ~/.ssh/id_dsa_pub | ssh domain.tld -p2222 "cat >> .ssh/authorized_keys && chmod 600 .ssh/authorized_keys"
Der passwortlose Login sollte damit funktionieren.
Zu den Möglichkeiten von SSH lässt sich noch eine Menge schreiben. Zu gegebener Zeit an dieser Stelle mehr.