NetBSD SSH Himmel Wolke Sendeturm

wall < "Howto zum Thema SSH"

Broadcast message from spillerm@unixe.de (pts/1) (Mo Mai 18 22:42:46 2009):
4
Diesen Beitrag schrieb ich vor 10 Jahren. Behalte das beim Lesen bitte im Hinterkopf.

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 heisst 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 schliesst 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, einigermassen 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 grosszü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 einschliesslich — 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 »grossen« 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 sitzt, kann ich mich dieser weitverbreiteten Meinung nur bedingt anschliessen; 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 ausschliesslich 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-point« 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 gutes 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 Grossbuchstaben (-c) und ansonsten keine zweideutigen Zeichen (wie »Null vs. gross 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 ausschliesslich ü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 Host gateway 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 Host gateway den Mailserver verwalten soll – deshalb soll er unter der eigens hierfür eingerichteten Kennung mailadmin arbeiten.
  • So wird harald nun dem zuständigen Admin den Inhalt seines Public Keys – also der Datei id_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 das authorized_keys-File muss chmod 0600 sein!).

Nun kann der User harald sich von genau diesem Host, auf dem der SSH-Key generiert wurde, aus 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 »einigermassen 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 (man 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 (ssh -vvv) sehr hilfreich sein.

4
  1. Sebastian

    Du willst nicht
    PermitTunnel
    Du willst
    AllowTcpForwarding

    AllowTcpForwarding ist die Option, die serverseitig benötigt wird, um per „-L“ Ports weiterzuleiten.

    PermitTunnel bezieht sich auf richtige tun-networkinteraces – Damit schiesst sich gerade ein unbedarfter Nutzer schneller in den Fuss als was sinnvolles anzufangen. Das ist durchas zurecht per Default auf „no“ und wird nur in den allerwenigsten Setups jemals einen anderen Wert brauchen. Und wer diese Optionen braucht, der braucht kein sshd_config 101 mehr ;)

    lg,
    Sebastian

  2. Sehr nützliches How-To, mein Kleinserver wird zwar nur mit etwas 10k SSH Loginversuchen belästigt am Tag, aber ich hab trotzdem mal Deine Vorschläge umgesetzt.

    Thänks,
    Thomas

  3. Harr harr, sehr cool — immer her mit genialen Tips :D

  4. Gutes Howto, kann man echt empfehlen.

    Eine weitere Möglichkeit das Login zu sichern besteht in der Verwendung von Einmalpasswörtern mittels OPIE.

    Gruss,
    Chaosblog.

  5. Ein paar Ergänzungen aus meinen Fundus:

    Wer doch Root-Logins braucht und Passwort-Logins bei normalen Usern, für den gibt es

    PermitRootLogin without-password

    Stellt man den den LogLevel auf VERBOSE schreibt der sshd beim Login dein Fingerprint des verwendeten Public Keys ins Log. Bei Verwendung mehrerer Keys – um etwa mehreren Benutzern den Login in einen Funktionsaccount zu ermöglichen – ist das sehr hilfreich.

    Bei Login-Problem unter Verwendung von Public Keys lohnt ein Blick auf die Rechte des User-Homeverzeichung, seines .ssh-Verzeichnisses und der Datei authorized_keys selbst: Keines von dreien darf Gruppen- oder Welt-Schreibrechte aufweisen. Im Zweifelsfall hilft das (VERBOSE-)Log des Servers.

    Bei Problemen mit ssh-Attacken hilft (zumindest unter Linux) ein vorgeschaltetes fail2ban: Es liesst das sshd-Log mit und sperrt Rechner mit zu vielen gescheiterten Login-Versuchen eine kurze Zeit per Firewall aus.

Keine weitere Reaktionen mehr möglich.