SSH absichern mit Fail2ban, Google Authenticator und Endlessh

Aus LinuxUser 11/2023

SSH absichern mit Fail2ban, Google Authenticator und Endlessh

© Jakub Krechowicz / 123RF.com

Verschlusssache

Wer eigene Dienste im Netz anbietet, etwa eine private Own- oder Nextcloud, will sie mitunter von unterwegs administrieren können. Das funktioniert unter Linux am besten per SSH, ausgestattet mit dem ein oder anderen Abwehrmechanismus.

Security-affine Nutzer dürften davor warnen, Management-Ports extern zu öffnen. Prinzipiell haben sie damit recht. Wer andere Möglichkeiten hat wie echte VPN-Lösungen per IPsec oder Wireguard hat, sollte lieber den Weg durch einen solchen Tunnel wählen.

Wollen Sie dennoch lieber direkt über SSH an Ihren Server kommen, sollten Sie diesen Weg bestmöglich absichern. Das beginnt schon bei automatischen Updates. Im nächsten Schritt deaktivieren Sie die passwortbasierte Authentifizierung zugunsten einer Public Key Authentication [1]. Dazu finden Sie online jede Menge guter Anleitungen [2].

Ein Wachhund namens Fail2ban

Fail2ban [3] erblickte 2004 das Licht der Welt und gilt damit inzwischen als recht ausgereift. Es handelt sich um ein Host-basiertes Intrusion Prevention System (HIPS), also um ein Tool, das Kompromittierungsversuche aktiv verhindert. Die Python-Software findet sich in den Repos praktisch aller Linux-Distributionen. Fail2ban analysiert Log-Dateien nach vordefinierten Mustern und sperrt bei wiederholtem Fehlverhalten die entsprechenden IP-Adressen per Iptables/Nftables aus.

Nach der Installation des HIPS (Listing 1, erste Zeile) definieren Sie zunächst das sogenannte lokale Jail, indem Sie die Datei jail.conf als jail.local kopieren (zweite Zeile). In der ausgesprochen gut kommentierten Konfigurationsdatei setzen Sie per ignoreip bestimmte IP-Bereiche auf eine Whitelist, zum Beispiel mit ignoreip=192.168.178.0/24. Das hat den Charme, dass Sie sich bei Tests nicht ständig selbst aussperren, birgt aber gleichzeitig das Risiko, dass über zu weitgefasste Ranges Angreifer durchs Netz rutschen. Hier sollten Sie also Umsicht walten lassen.

Listing 1

Fail2ban einrichten

$ sudo apt install fail2ban
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Mit Netfilter gibt es ein exzellentes Kernel-Modul, um unter Linux Firewalls einzurichten. Viele dürften das etwas betagte Netfilter-Frontend Iptables kennen, das inzwischen von Nftables [4] abgelöst wurde. Über die Direktive banaction legen Sie in der Fail2ban-Konfiguration fest, welches Backend Fail2ban im Fall eines Fehlverhaltens verwenden soll. Für unser Beispiel passt banaction = nftables-multiport.

Der wichtigste Teil der Konfiguration gebührt allerdings den Jails. Wie bei den althergebrachten INI-Dateien gliedern diese sich die entsprechenden Anweisungen in eine Header-Zeile, die den Namen des Jails in eckigen Klammern trägt, und die zugehörigen Parameter. Ein Beispiel hilft hier dem Verständnis am schnellsten auf die Sprünge: Das Jail aus Listing 2 heißt ssh und sorgt dafür, dass Fail2ban die Datei /var/log/auth.log auf Unregelmäßigkeiten hin überwacht.

Listing 2

Beispiel-Jail

[ssh]
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 3
bantime  = 86400 ; 1 day
findtime  = 86400 ; 1 day

Der Parameter maxretry benennt dabei die Toleranzschwelle. Im Beispiel greift der Bann ab dem dritten Fehlversuch. Die bantime legt die Dauer der Quarantäne auf einen Tag fest. Wie lange maxretry gelten soll, bestimmt die findtime; im konkreten Beispiel ist es ebenfalls ein Tag. Kommt es also innerhalb von 24 Stunden zu mindestens drei Fehlauthentifizierungen per SSH, sperrt Nftables die Client-IP für 24 Stunden (Abbildung 1).

Abbildung 1: Nach drei Anmeldeversuchen eines Bots greift <code>maxretry = 3</code>, und Fail2ban schickt ihn in die Verbannung.

Abbildung 1: Nach drei Anmeldeversuchen eines Bots greift maxretry = 3, und Fail2ban schickt ihn in die Verbannung.

Fail2ban prüft jedoch mitnichten allein SSH auf Fehlanmeldungen. Über Filter-Dateien unterhalb von /etc/fail2ban/filter.d/ erweitern Sie das Tool für beliebige Log-Dateien, zum Beispiel für Nextcloud. Die Grundlage bilden reguläre Ausdrücke wie in Listing 3.

Listing 3

Fehlanmeldungen erkennen

[Definition]
failregex = ^{.*Login failed: '.*' \(Remote IP: '<HOST>'\).*}$
^{.*Login failed: .* \(Remote IP: <HOST>\).*}$
^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\)".*}$
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":"no app in context","method":".*","url":"/login","message":"Login failed: .* \(Remote IP: <HOST>\)".*}$

Failregex akzeptiert für den Parameter failregex mehrere Alternativen. Statt ein hochkompliziertes Muster für alle Eventualitäten anzugeben, definiere ich lieber mehrere Patterns für spezielle Fälle. Schon reguläre Ausdrücke an sich sind ein sehr komplexes Thema. Möchten Sie sich wirklich selbst an die Definition eigener Filter wagen, empfehle ich Ihnen die vielen Beispiele im Ordner /etc/fail2ban/filter.d/. Darüber hinaus sollten Sie in diesem Zusammenhang eines der zahlreichen Tools zum Testen von regulären Ausdrücken nutzen.

Kam es vermehrt zu gescheiterten Anmeldeversuchen und damit zu einer Sperre durch Fail2ban, setzen Sie fail2ban-client als Mittel der Wahl ein (Listing 4). Eine (fälschlich) gebannte IP-Adresse entsperren Sie über folgenden Befehl:

$ sudo fail2ban-client set ssh unbanip IP

Listing 4

Fail2ban-client

$ sudo fail2ban-client status ssh
[sudo] Passwort für thomas:
Status for the jail: ssh
|- Filter
|  |- Currently failed: 3
|  |- Total failed:     3
|  `- File list: var/log/auth.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

Das Potenzial von Fail2ban ist wirklich beachtlich, prinzipiell überwachen Sie damit jede beliebige Protokolldatei. Dementsprechend eignet sich das Tool ausgezeichnet als Mittel gegen Brute-Force-Attacken auf allerlei Anwendungen, seien es nun über Tomcat servierte Java-Servlets oder PHP-Webanwendungen und vieles mehr.

TOTP mit Google Authenticator

Fail2ban entschärft vor allem dumpfe Brute-Force-Attacken gegen Accounts wie root, mysql und admin. OATH-TOTP-Verfahren, die Apps wie Google Authenticator oder Authy implementieren, bieten darüber hinaus einen erweiterten Schutz für persönliche Logins [5]. Das Kürzel OATH steht für die Initiative for Open Authentication, TOTP für Time-based One-time Password, also zeitlich veränderliche Einwegpasswörter.

Wird ein persönliches Passwort im Rahmen eines Datenlecks mit einem Mal öffentlich, ist es überaus hilfreich, noch einen weiteren Sicherheitsfaktor wie TOTP in der Hinterhand zu haben. Das Verfahren lässt sich daneben zum Absichern von SSH-Logins einsetzen, auch in Kombination mit Public Key Authentication.

Die Installation gestaltet sich einmal mehr recht trivial. Dazu müssen Sie lediglich die entsprechende Bibliothek einrichten (Listing 5, erste Zeile). Anschließend starten Sie die Applikation (Zeile 2) und bejahen die Frage, ob Sie zeitbasierte Einmalpasswörter verwenden wollen (Zeile 3). Nach dem Bestätigen erscheint auf der SSH-Konsole ein QR-Code, den Sie mit einer beliebigen Authenticator-App einscannen.

Listing 5

Google Authenticator

$ sudo apt install libpam-google-authenticator
$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y

Abschließend müssen Sie die PAM-Konfiguration noch etwas anpassen. In der Datei /etc/pam.d/sshd kommentieren Sie zunächst die in der dritten Zeile von Listing 6 gezeigte include-Zeile aus. Dann ergänzen Sie die ab Zeile 5 aufgeführten Anweisungen, sodass Sie im eigenen LAN nach wie vor ohne Authenticator eine SSH-Verbindung herstellen können. In der Datei /etc/security/access-local.conf definieren Sie zu guter Letzt all jene IP-Adressen, die sich ohne TOTP-Verfahren einloggen dürfen (Listing 7).

Listing 6

/etc/pam.d/sshd

[...]
# Standard Un*x authentication.
# @include common-auth
[...]
# success=done: Für interne IP-Adressen die
# Authentifizierung als erledigt kennzeichnen
auth [success=done default=ignore] pam_access.so accessfile=/etc/security/access-local.conf
auth required pam_google_authenticator.so
[...]

Listing 7

access-local.conf

# only allow from local IP range
+ : ALL : 192.168.178.0/24
+ : ALL : LOCAL
- : ALL : ALL

Nun adjustieren Sie noch die Konfiguration des SSH-Diensts. Dazu setzen Sie einige Parameter in /etc/ssh/sshd_config (Listing 8). Über die Direktive aus der ersten Zeile gewährleisten Sie, dass Clients nicht einfach Benutzername und Passwort an den Server schicken können, sondern sich zwingend interaktiv über das aktuelle TTY authentifizieren müssen. Die Pluggable Authentification Modules (PAMs) haben Sie bereits zuvor um Google Authenticator erweitert. Jetzt müssen Sie diese Erweiterung auch für SSH zur Verwendung freigeben (zweite Zeile). Da Sie künftig Ihr TOTP-Passwort per SSH eingeben müssen, aktivieren Sie keyboard-interactive als Authentifizierungsmethode (letzte Zeile).

Listing 8

/etc/ssh/sshd_config

ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive

Zum Schluss starten Sie über das Kommando sudo systemctl restart sshd den SSH-Daemon neu. Ab sofort wird bei externen SSH-Verbindungen nicht nur per Public Key authentifiziert, sondern zusätzlich per TOTP.

Ab in die Teergrube

Nachdem die 3-Faktor-Authentifizierung – Public Key Authentication inklusive Passphrase und TOTP – nun steht, richten Sie in Form von Endlessh [6] noch einen kleinen Honeypot ein, der Angreifer (oder vermutlich überwiegend Bots) auf eine falsche Fährte führt. Hinter Endlessh verbirgt sich ein Tarpit-Honeypot, quasi eine Teergrube, in der die angelockten Opfer nur extrem langsam und mühselig vorankommen.

Den zähen Honigtopf installieren Sie denkbar einfach via sudo apt install endlessh. Als erste Vorarbeit leiten Sie auf dem Internet-Router SSH per NAT auf einen Nicht-Standard-Port um. Welcher Wert dafür passt, dürfte individuell recht verschieden sein. Jedenfalls lauscht künftig auf TCP/22 nicht mehr der OpenSSH-Daemon, sondern von nun an Endlessh.

Bevor Sie Endlessh starten, legen Sie eine Konfigurationsdatei dafür an. In /etc/endlessh/config hinterlegen eine Reihe von Parametern. Port Nummer markiert einen beliebigen Port, auf dem Endlessh lauscht (Standard 2222). Der Wert für Delay gibt die Anzahl an Millisekunden an, die Endlessh zwischen den einzelnen Zeilen seines Banners vergehen lässt. Dementsprechend erscheint mit Delay 10000 nur alle zehn Sekunden eine neue Zeile das endlosen SSH-Banners.

Die maximale Zeilenlänge erzwingen Sie mit der Anweisung MaxLineLength Anzahl. Ein Zufallsgenerator würfelt bis zu dieser Grenze die ausgegebenen Zeichen aus. Es empfiehlt sich, hier einen nicht allzu großen Wert anzugeben, da manche Clients nur eine bestimmte Anzahl von Bytes im Banner akzeptieren.

Logischerweise birgt ein Tarpit die Gefahr, sich zu einer selbstgebauten Denial-of-Service-Schwachstelle auszuwachsen. Deswegen sollten Sie unbedingt die maximale Anzahl an Client-Verbindungen begrenzen, die Endlessh bedient. MaxClients 4096 gilt als sinnvolle Voreinstellung, da die hierfür aufzuwendenden Betriebsmittel (Ports, Dateideskriptoren, RAM) leicht zu verschmerzen sind. Stellen mehr Clients Verbindungsanfragen, lehnt Endlessh diese nicht direkt ab, sondern stellt sie in eine Warteschlange.

Für ein ausgewogenes Logging wählen Sie Loglevel 1. Im konkreten Fall interessiert mich nur IPv4, weswegen ich BindFamily 4 nutze. Letztlich bedarf es nur noch des Kommandos sudo systemctl start endlessh, um Endlessh aufzurufen.

Sie testen das Ganze, indem Sie SSH mit explizit angegebenem Port auf Ihre derzeit gültige externe IP-Adresse losschicken. Ärgerlicherweise protokolliert der Debug-Modus des OpenSSH-Clients keine Zeitstempel, denn sonst könnten Sie in Abbildung 2 sehen, dass zwischen dem Absetzen des Befehls ssh und der letzten Zeile eine ganze Minute vergangen ist. Endlessh fühlt sich für einen Menschen unglaublich zäh an – wie ein Server, der kurz vor dem Exitus steht.

Abbildung 2: Per SSH-Client stellen Sie eine Verbindung mit Endlessh her.

Abbildung 2: Per SSH-Client stellen Sie eine Verbindung mit Endlessh her.

Erwartungsgemäß musste ich bei meinen Tests nicht lange warten, bis sich in /var/log/syslog die ersten Einträge von Endlessh tummelten. Einsamer Spitzenreiter war hier ein Bot (und hoffentlich nur ein solcher) mit der IP-Adresse 81.17.25.50, der sich nahezu zwei Stunden lang ein kryptisches SSH-Banner ansah (Abbildung 3). Nach einer kurzen Abfrage per Whois (Abbildung 4) würde Janosch da wohl fragen: “Oh, wie blöd ist Panama?”

Abbildung 3: Die Top&nbsp;10 der geduldigsten Bots hielten mindestens 15&nbsp;Minuten Wartezeit durch.

Abbildung 3: Die Top 10 der geduldigsten Bots hielten mindestens 15 Minuten Wartezeit durch.


Abbildung 4: Ein Auszug des Whois-Eintrags enth&uuml;llt die Herkunft des Bots (oder Clients?).

Abbildung 4: Ein Auszug des Whois-Eintrags enthüllt die Herkunft des Bots (oder Clients?).

Fazit und Ausblick

Mit einem SSH-Standard-Setup erreichen Sie noch lange nicht das Ende der Fahnenstange sicherheitsrelevanter Optimierungen. Haben Sie SSH auf Port 22 im Internet veröffentlicht und gleichzeitig Fail2ban aktiviert, werden Sie überrascht sein, wie interessant die eigene Umgebung doch für viele IPs da draußen ist. Es kommt praktisch andauernd zu Ban-Vorfällen, was auf Dauer derartig nerven kann, dass wohl viele – wie auch ich – SSH per NAT auf irgendeinen hohen Port verfrachten.

Die meisten Bots erkennen freilich nicht einmal, dass die Password-Authentifizierung deaktiviert ist, und scheitern schon mehrfach im PreAuth-Stadium. Ernst zu nehmende Angreifer verhalten sich freilich deutlich cleverer, aber dank Multifaktorauthentifizierung und noch einiger weiterer Hürden kann zumindest ich nachts gut schlafen. (jlu)

Glossar

Honeypot

Ein Programm, das als Scheinziel Netzwerkdienste oder ein ganzes Rechnernetz simuliert. Honeypots werden eingesetzt, um Informationen über Angriffsmuster und das Verhalten von Angreifern zu sammeln.

Infos

  1. Secure Shell: Harald Zisler, “Sicherer Transfer”, LU 11/2017, S. 74, https://www.linux-community.de/39062

  2. “How To Configure SSH Key-Based Authentication on a Linux Server”: https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server

  3. Fail2ban: http://www.fail2ban.org

  4. Nftables: Frank Hofmann, “Türsteher-Nachwuchs”, LU 06/2019, S. 92, https://www.linux-community.de/42230

  5. 2FA: Charly Kühnast, “Doppelt sicher”, LU 11/2020, S. 16, https://www.linux-community.de/45182

  6. Endlessh: https://github.com/skeeto/endlessh

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 11/2023 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben