SSH absichern

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.

Mal wieder Ärger mit EVANZO

Ich versuche für einen Kunden seit nun mehr rund zwei Wochen erfolglos Domains per KK zu übernehmen. Doch EVANZO tut wirklich alles, um seiner schlechten Reputation zu entsprechen und blockiert. Allen Anschein nach hilft es tatsächlich nur gegen EVANZO die juristische Keule auszupacken. Zwar finde ich es sehr unschön sich positiv auf Anwälte und Justiz zu beziehen, allerdings scheint es mir in unserer derzeitigen Gesellschaftsform keinen anderen Ausweg zu geben, wenn ein Anbieter eine Domain nicht freigeben möchte.

EVANZO! – Clevere hosten woanders

Bei Billighoster EVANZO kam es häufig zu Störungen und Ausfällen. Bei einem meiner Kunden war alleine in diesem Jahr der Mailserver zusammengerechnet einige Tage nicht erreichbar. Störungsmeldungen per E-Mail werden meiner Erfahrungen nach vom technischen Support rigoros ignoriert – ob absichtlich oder aufgrund Versagens der eigenen Mailserver, sei einmal dahingestellt. So bleibt nur der Weg über die kostenpflichtige Supporthotline. Die Qualität der Hotline lässt noch mehr zu wünschen übrig als die instabilen Server des Hosters: Die Mitarbeiter gaben sich bei meinen zahlreichen Anrufen durchweg inkompetent und unfreundlich. Doch der Dialog von heute Nachmittag stellt alles bisher dagewesene in den Schatten.

Tom: Der Mailserver mail.domain.tld* ist mal wieder nicht erreichbar.
Mitarbeiter: Da brauche ich erst einmal ihre Kundennummer.
Tom: Leider habe ich die nicht griffbereit. Das Problem ist auch nicht vertragsspezifisch. Der Server bedient auch andere Kunden und ist nicht verfügbar.
Mitarbeiter: Dann kann ich ihnen nicht helfen.
Tom: Warum können Sie nicht den Server mail.domain.tld als ausgefallen/gestört melden?
Mitarbeiter: Ok, ich werde das ausnahmsweise überprüfen. Bitte nennen Sie mir die Zugangsdaten zu einer Ihrer E-Mailadressen.
Tom: Warum das?
Mitarbeiter: Wollen Sie, dass ich Ihnen helfe?
Tom: Ja!
Mitarbeiter: Dann nennen Sie mir die Zugangsdaten.
Tom: Nein!
Mitarbeiter: Bitte nicht in diesen Ton, sonst muss ich das Gespräch beenden.
Tom: Wie bitte? Weil ich mich weigere Ihnen die Zugangsdaten zu einem E-Mailaccount zu nennen?
Mitarbeiter: Wenn ich ihnen helfen soll, müssen sie meinen Anweisungen folgen.
Tom: Sie benötigen keine Zugangsdaten um die Erreichbarkeit eines Mailserver zu überprüfen.
Mitarbeiter: Wenn Sie das so genau wissen, warum rufen Sie dann an?
Tom: Ich kann via telnet mail.domain.tld 25 feststellen, ob der Server antwortet oder nicht.
Mitarbeiter: Das ist eine unzulässige Nutzung unserer Server.
Tom: …
Mitarbeiter: Sie müssen schon ein zugelassenes E-Mailprogramm wie Outlook verwenden.
Tom: …
Mitarbeiter: Hallo?! Sind sie noch da.
Tom: Ja. Aber so kommen wir nicht weiter. Bitte melden Sie die Server als ausgefallen.
Mitarbeiter: Dazu muss ich erst überprüfen, ob sie Ihr E-Mailprogramm richtig eingestellt haben. Wenn sie kein richtiges E-Mailprogramm verwendet haben, kann ich ihnen auch nicht helfen.

*Echte Adresse ersetzt.

Ab diesem Punkt fehlten mir die Nerven diesen sinnlosen Dialog fortzuführen. Ich setzte eine Frist, um eine Lösung für den ausgefallenen Mailserver zu finden. Die Frist ist natürlich lange verstrichen und der Mailserver weiterhin nicht erreichbar. Dafür ist nun auch der Webserver ausgefallen.
Ich werde morgen meinen Kunden zu einer außerordentlichen Kündigung unter Auferlegung der Kosten für die Ausfallzeit raten.

bye bye mod_php

Ich habe meine PHP-Apache-Installationen von mod_php auf php_cgi umgestellt. Anlass zu diesem Schritt gab mir, dass ich keine befriedigende Lösung gefunden habe, um beim Schreibzugriff auf Dateien mit PHP Berechtigungskonflikte zwischen Apache und dem User, dem die Dateien eigentlich gehören sollten, auszulösen. Auch war mir schon lange ein Dorn im Auge, dass mod_php nicht mit Threads umgehen kann und dazu zwingt zum ineffizienten Prefork-Modus zurückzukehren. Damit fällt eine wesentliche Verbesserung von Apache2 gegenüber 1.3 weg.
Und nicht zuletzt erscheint es mir in Hinblick auf die Serversicherheit keine gute Idee zu sein PHP mit den weitreichenden Befugnissen des Apache laufen zu lassen – zumal Restriktionen wie open_basedir leicht umgangen werden können.

PHP als FastCGI einzubinden stellt zwar einen etwas höheren Konfigurationsaufwand gegenüber mod_php dar, der jedoch mit Lösung der oben genannten Probleme belohnt wird.

Sobald ich mal wieder ein Quentchen mehr Zeit finde, werde ich ein Mini-Tuorial für Debian 4 an dieser Stelle veröffentlichen. Momentan bin ich noch damit befasst den Geschwindigkeitsunterschied zwischen mod_php und der FastCGI-Variante zu messen.

MyISAM Tabellen reparieren

MyISAM Tabellen arbeiten nicht transaktionsorientiert und können beschädigt werden, zum Beispiel wenn mysqld während eines Schreibzugriffs gewaltsam beendet wurde, ein Hardwarefehler vorliegt und ähnliche Katastrophen. Aufmerksam auf ein solches Problem macht neben unvollständigen oder fehlerhaften Ergebnissen einer Datenbankabfrage die Fehlermeldung:

Incorrect key file for table: ‚…‘. Try to repair it

In der Regel lassen sich die beschädigten Tabellen mit repair table your_table; wieder in einen definierten Zustand versetzen. Wenn es schlecht läuft, können aber auch einzelne Datensätze dabei zerstört werden. Kluge Menschen halten darum ein tägliches Backup ihrer Datenbank vor. 🙂

Wenn Datenbanktabellen ohne erkennbaren Grund (zum Beispiel Strom- oder Hardwareausfall) öfters beschädigt werden, ist gut beraten die Serverkonfiguration genauer zu untersuchen oder den Hoster zu wechseln.