Howto zum Thema SSH
- Das Protokoll
- root-Login verbieten
- Nur bestimmte User zulassen
- Verbindungszeiten kontrollieren
- Anzahl paralleler Tasks kontrollieren
- Umlegen auf anderen Port
- Listen Address
- X11Forwarding
- PermitTunnel
- Ein sicheres Passwort für jeden User
- Sicherheit gewinnen durch Key-Auth
- forced-commands-only
- SSH-Keys mit Passphrase
- Einschränkungen durch TCP-Wrapper
- Troubleshooting
In aller Regel ist das Konfigurations-File des sshd
die /etc/ssh/sshd_config
; hier werden die Änderungen vorgenommen. Tiefergehende Fragen beantwortet unter anderem die Manpage (man 5 sshd_config
). Fangen wir also vorne an…
Das Protokoll
Die ursprüngliche SSH-Protokoll-Version (1) wurde schon vor längerer Zeit durch Version 2 abgelöst; aus Gründen der Abwärtskompatibilität kann mittels Protocol 2,1 definiert werden, dass beide Protokolle verwendet werden können – je nachdem, was der Client anfordert. Ist dies jedoch nicht zwingend benötigt, sollte man Abstand davon nehmen – Version 1 weist mehrere bekannte Sicherheitslücken auf. Der entsprechende Parameter in der Konfiguration heißt dann
Protocol 2
root-Login verbieten
Für den User root
sollte die grundsätzliche Login-Möglichkeit deaktiviert werden; sicherer und auch besser nachvollziehbar ist es, wenn einzelne angemeldete User per su
bzw. sudo
arbeiten. Der entsprechende Parameter in der Konfiguration lautet
PermitRootLogin no
Nur bestimmte User zulassen
In aller Regel ist die Menge der User, die sich auf einem Server per SSH anmelden müssen, recht begrenzt; erlaubt man diesen Usern explizit den Zugriff, ist er allen anderen implizit verboten, und das schließt dann beispielsweise System-User mit ein. Um den Usern fritz
, martha
und hugibaz
den Zugriff zu gewähren, lautet der entsprechende Parameter in der Konfiguration also
AllowUsers fritz martha hugibaz
Versuchen sich nun die User mail
, operator
und frank
an der Maschine anzumelden, so erscheint im /var/log/auth.log
(systemabhängig, kann bsp. auch /var/log/secure
sein) eine Ausgabe wie diese:
auth.log:May 8 01:06:28 gateway sshd[3653]: User mail from 12.34.56.78 not allowed because not listed in AllowUsers
auth.log:May 8 01:06:31 gateway sshd[3658]: User operator from 12.34.56.78 not allowed because not listed in AllowUsers
auth.log:May 8 01:06:47 gateway sshd[3691]: User frank from 12.34.56.78 not allowed because not listed in AllowUsers
Verbindungszeiten kontrollieren
Man kann davon ausgehen, dass ein User, der vor seinem Terminal sitzt und sich anmelden möchte, einigermaßen zeitnah Nutzernamen und Passwort eingeben wird; jeder SSH-Task, der gestartet wurde und nun auf Eingabe der Login-Credentials wartet, kostet Rechenzeit und Speicher – weshalb die Zahl der Prozesse möglichst nicht unnötig hoch sein sollte. Mit dem Parameter LoginGraceTime 60
gibt man dem sshd
auf den Weg, dass er, sollte sich innerhalb von 60 Sekunden nichts getan haben, den gestarteten Task wieder beenden kann. Diese 60 Sekunden erscheinen auf Anhieb recht großzügig, ein geringerer Wert ist jedoch kaum anzuraten; im Falle, dass die Maschine einmal unter enormer Last stünde, würde die Kommunikation mit dem sshd
verzögert und der Task beendet, noch bevor ein Login überhaupt möglich war – das kann gefährlich werden, da es ein Eingreifen bzw. Einloggen unmöglich macht.
LoginGraceTime 60
Anzahl paralleler Tasks kontrollieren
Wie wir eben gesehen haben, startet jeder Login-Versuch einen SSH-Task auf dem Server; steht der Server nun unter einer SSH-Attacke, muss er potentiell hunderte Logins innerhalb kürzester Zeit abarbeiten – und für jeden dieser Logins einen eigenen Task starten, was zu lasten der Performance der Maschine gehen wird. Diese Zahl paralleler Tasks kann jedoch kontrolliert werden, in unserer Konfiguration würde sich beispielsweise der folgende Parameter finden:
MaxStartups 3:30:10
Zur Erklärung: hier sind nun zwei unbestätigte (also noch im Login-Vorgang befindliche) SSHD-Verbindungen immer erlaubt (entspricht dem ersten Wert abzüglich 1). Ab der dritten einschließlich – was dem ersten Wert entspricht – wird jede weitere Verbindung mit einer Wahrscheinlichkeit von 30% abgelehnt (was dem zweiten Wert entspricht). Die Wahrscheinlichkeit steigt linear an, bis bei 10 offenen Verbindungen – was dem dritten Wert entspricht – jeder weitere Verbindungsversuch mit einer Wahrscheinlichkeit von 100% abgewiesen wird. Aber: bestehende SSH-Sessions mit erfolgreich eingeloggten Usern werden hier nicht eingerechnet, insofern sind die o.g. Defaults in der Regel ausreichend; bei „großen“ Maschinen mit vielen Usern müssen die Werte entsprechend angepasst werden.
Umlegen auf anderen Port
Port 22 ist der Standard-Port für sshd
, und lange Zeit galt es als sicher, den Dienst auf einem anderen Port (bsp. 24) lauschen zu lassen; da die Netzwerkscanner inzwischen nicht mehr nur prüfen, ob auf einem Port ein Dienst sitzt, sondern auch welcher Dienst da lauscht, kann ich mich dieser weitverbreiteten Meinung nur bedingt anschließen; der Vollständigkeit halber sei es aber erwähnt, die Option lautet
Port 24
Listen Address
Es ist möglich (und in einigen Fällen sogar ratsam), den IP-Adressbereich einschränken, so dass sshd nur auf einen klar definierten internen Netzbereich lauscht; ein denkbarer Einsatzbereich wäre hier unter anderem, SSH-Zugriffe ausschließlich aus einem OpenVPN-Netz zu gestatten.
ListenAddress 172.16.4.1
X11Forwarding
Per Default ist diese Option auf „no“ gesetzt, d.h. X11Forwarding über SSH wird nicht zugelassen; möchte man dieses erlauben, muss der Parameter explizit auf „yes“ gesetzt werden:
X11Forwarding yes
PermitTunnel
SSH-Tunnel können nur dann aufgebaut und benutzt werden, wenn dies explizit erlaubt wird (per Default wird es nicht erlaubt); mögliche Werte sind „yes“, „no“, „point-to-“ und „ethernet“.
PermitTunnel yes
Ein sicheres Passwort für jeden User
Natürlich ist die Absicherung des Servers hinfällig, wenn dem Angreifer Usernamen bekannt sind und die dazugehörigen Passwörter schlicht erraten werden können; ein mögliches Tool zum Erstellen der Passwörter ist pwgen
, das auf allen gängigen Distributionen einfach als Paket nachinstalliert werden kann.
$ pwgen -B -C -n 12 1
caiph7eChaex
So generiert der Aufruf uns ein (kenntlich gemacht durch die 1 am Ende) 12-stelliges Passwort (kenntlich gemacht durch die 12), das mindestens eine Ziffer enthält (-n), mindestens einen Großbuchstaben (-c) und ansonsten keine zweideutigen Zeichen (wie „Null vs. groß O“ oder „Ziffer eins vs. klein L“). Dieses Passwort ist so sicher, dass es sich kein Schwein merken wird :D
Sicherheit gewinnen durch Key-Auth
Der Zugriff auf die Maschine kann so weit eingeschränkt werden, dass das Login ausschließlich über den SSH-Key erfolgt und nicht mehr, wie zuvor, über die Eingabe des Passworts; das verringert die Wahrscheinlichkeit einer erfolgreichen Attacke, da der Angreifer die entsprechenden Schlüssel in seine Gewalt bringen müsste, und es hat einen weiteren Vorteil: der User muss sich das 12-stellige pwgen
-Passwort nicht merken (und auch nicht auf einem Post-It an den Monitor kleben), da er es zum Login nicht benötigt (es sei denn, er möchte oder muss mit sudo
arbeiten).
PermitEmptyPasswords no
PasswordAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
Gehen wir nun also von User harald aus; harald
ist ein neuer User und möchte Zugriff auf die Maschine gateway
haben, gateway
jedoch akzeptiert nur Logins mit hinterlegten Keys. Als erstes muss der User sich also einen SSH-Key generieren, sofern er noch keinen besitzt:
$ ssh-keygen -t rsa
Dies erzeugt im $HOME
des Users den Ordner .ssh/
, in welchem unter anderem diese beiden Dateien zu finden sind:
-rw------- 1 harald users 887 Apr 16 16:48 id_rsa # das ist der private Schlüssel, der unter allen Umständen beim User verbleiben muss
-rw------- 1 harald users 222 Apr 16 16:48 id_rsa.pub # das ist der öffentliche Schlüssel (Public Key)
WICHTIG: beide Dateien müssen dem User harald
gehören und dürfen nur durch ihn gelesen und beschrieben werden (chmod 0600
)!
Um nun auf den Host gateway
zugreifen zu können, müssen die folgenden Schritte vorgenommen werden:
- Nur weil
harald
auf seinem Rechner mit der Login-ID harald arbeitet, muss er das auf dem Hostgateway
nicht zwingend auch tun; im Vorfeld ist also zu klären, unter welcher Nutzerkennung er wird arbeiten müssen. - Inzwischen ist bekannt, dass
harald
auf dem entfernten Hostgateway
den Mailserver verwalten soll – deshalb soll er unter der eigens hierfür eingerichteten Kennungmailadmin
arbeiten. - So wird
harald
nun dem zuständigen Admin den Inhalt seines Public Keys – also der Dateiid_rsa.pub
– zur Verfügung stellen. - Der Admin wird diesen Key an die Datei
/home/mailadmin/.ssh/authorized_keys
anhängen bzw. dieses File erstellen, sollte es noch nicht existieren (auch dasauthorized_keys
-File musschmod 0600
sein!).
Nun kann der User harald
sich von genau diesem Host, auf dem sein SSH-Key verfügbar ist, auf dem Host gateway
einloggen:
$ ssh mailadmin@gateway
forced-commands-only
Beispiel: in unserem Setup ist nicht gewünscht, dass root
sich über SSH einloggen kann; wir möchten aber einen SSH-Tunnel aufbauen zwischen einer lokalen und einer entfernten Maschine, und dieses Tunnel-Setup möchten wir durch Scripte automatisieren. Das Problem: nur root
darf per ifconfig
die Konfiguration der Interfaces ändern. Deshalb setzen wir in der sshd_config
statt, wie vorher einfach „no“, den entsprechenden Parameter auf yes:
PermitRootLogin forced-commands-only
Auf diesem Rechner wird für root
dann eine autorized_keys
hinterlegt, die dem folgenden Schema folgt:
command="$KOMMANDO_NEBST_PARAMETERN" $KEY
Soll User root
also das Login grundsätzlich verwehrt bleiben, das Setzen der Tunnel-Parameter aber erlaubt sein, so könnte das in etwa so aussehen:
command="/sbin/ifconfig tun0 192.168.6.2 dstaddr 192.168.6.1 up" ssh-rsa [...]
SSH-Keys mit Passphrase
Jeder hat nun prinzipell Zugang als User mailadmin
auf gateway
– sofern er, auf welchem Wege auch immer, Zugriff auf haralds
Maschine hat und über den hinterlegten harald
-Key. Natürlich kann das ein Sicherheitsloch darstellen; deshalb gibt es die Möglichkeit, beim Anlegen eines neuen SSH-Keys diesem eine Passphrase mit auf den Weg zu geben. Im vorliegenden Falle würde dann nicht mehr das (12-stellige computergenerierte) Host-Passwort abgefragt werden, sondern lediglich die Passphrase des SSH-Keys. Die kann der User sich selbst aussuchen, und mit etwas Glück gelingt ihm dabei die Grätsche zwischen „merkbar“ und „einigermaßen sicher“.
Einschränkungen durch TCP-Wrapper
Ist sshd
mit Unterstützung für TCP-Wrapper kompiliert, können auch die Dateien
-
/etc/hosts.allow
und /etc/hosts.deny
zum Einsatz kommen; prüfen lässt sich dies mit einem Aufruf wie diesem:
# ldd /usr/sbin/sshd | grep wrap
libwrap.so.0 => /lib/libwrap.so.0 (0xb7f71000)
Möchte man nun einem konkreten Host mit IP 192.168.1.2 den Zugriff verbieten (User-unabhängig!), kann beispielsweise in der Datei /etc/hosts.deny
dieser Eintrag hinterlegt werden:
sshd: 192.168.1.2
Nach Abspeichern der Datei – ein Reload des sshd
ist nicht nötig – werden Login-Versuche von diesem Host abgewehrt; der User erhält als Fehlermeldung
ssh_exchange_identification: Connection closed by remote host
Währenddessen wird im Logfile (/var/log/auth.log
oder /var/log/secure
) eine Meldung wie diese vermerkt:
May 18 14:38:10 gateway sshd[12455]: refused connect from 192.168.1.2 (192.168.1.2)
An dieser Stelle gibt es vielfältige Möglichkeiten, so kann beispielsweise der Admin bzgl. jeden Anmeldeversuchs benachrichtigt werden usw. … Sinnvollerweise sollte man sich die Manpages (vman 5 hosts_access`) zu Gemüte führen, um die Möglichkeiten der TCP-Wrapper voll auszuschöpfen.
Troubleshooting
Bei Problemen sind die Logfiles zu konsultieren, bei Connect-Problemen kann der „verbose“ Aufruf (vssh -vvv`) sehr hilfreich sein.
Hintergrundbild: Bild genauer anschauen – © Marianne Spiller – Alle Rechte vorbehalten