Post

Einen PostgreSQL Server gegen Denial-Of-Service absichern

Einen PostgreSQL Server gegen Denial-Of-Service absichern

Wenn man einen Server mit einer Datenbank (z.B. PostgreSQL) betreibt, sollte man diesen im Idealfall nur für lokal laufende Anwendungen freigeben. Manchmal muss man aber den Zugang zur Datenbank für externe Anwendungen erlauben und spätestens dann sollte man sich Gedanken darüber machen, wie man den Server nach außen hin dicht bekommt.

In diesem kleinen Blog geht es um das Dreiergespann:

  • PostgreSQL Datenbank Server
  • UFW Firewall
  • fail2ban Überwachungsdienst

PostgreSQL installieren und Freigaben konfigurieren

Unter Ubuntu installiert man PostgreSQL ganz einfach aus den Paketquellen:

1
sudo apt install postgresql 

Festlegen, auf welchen Netzwerkschnittstellen der Server lauschen soll

Abgesehen von ‘localhost’ gibt es möglicherweise mehrere Netzwerkschnittstellen, auf denen der Server auf Kommunikation warten soll. Dies wird in der Konfigurationsdatei

1
/etc/postgresql/14/main/postgresql.conf

konfiguriert (wobei man die 14 durch die jeweilige Version ersetzen muss). Die Zeile

1
listen_addresses = '*'

definiert, dass der Server auf allen Schnittstellen lauschen soll. Man kann das auch einschränken, aber häufig ist das ok so.

Festlegen, wer von außen überhaupt mit dem Server reden darf

Von außen eingehende Verbindungen konfiguriert man in der Datei:

1
/etc/postgresql/14/main/pg_hba.conf

Dort definiert man, welche externen Adressen auf welche Datenbank und mit welcher Authentifizierung zugreifen dürfen. Das geht für IP4 und IP6 und kann recht komplex werden. Ein paar Beispiele, die ich benötige:

1
2
3
4
5
6
7
8
# IP4 Regel für Zugriff auf die Datenbank 'meinedb' für Nutzer 'mein_admin'  
# von überall her und unter Verwendung eines Passworts
host    meinedb    mein_admin    0.0.0.0/0               scram-sha-256
# die analoge IP6 Regel
host    meinedb    mein_admin    ::/0                    scram-sha-256

# Vollzugriff von einer einzelnen, exakt spezifizierten IP-Adresse zulassen
host    all        all           141.30.49.298/32        scram-sha-256

Die IP-Adressen mit /xx am Ende sind sogenannte CIDR-Adressen; /32 bedeutet, dass nur exakt die angegebene IP-Adresse Zugriff bekommt.

Die Regeln für den Zugriff vom local kann man so lassen. Nur wenn man via host einen externen Zugang ermöglicht, sollte man eher restrictiv sein. Vor allem den Zugriff zur zentralen Datenbank postgres sollte man auf ganz wenige, möglichst klar definierte IP-Adressen einschränken, wenn man diesen Zugang überhaupt nach außen geben will. Schließlich kann man sich ja auch jederzeit via ssh auf den Server einloggen und PostgreSQL in der Konsole administrieren.

Nach Änderungen der Konfiguration kann man entweder den Dienst neu starten

1
sudo service postgresql restart

oder einfach auch neu booten.

Zugriff überwachen

Der PostgreSQL loggt Zugriffe und nach Einrichten des Dienstes sollte man hier mal nachschauen:

1
sudo tail -f /var/log/postgresql/postgresql-14-main.log

Das zeigt die letzten Zeilen der Logdatei an und schreibt neu eintreffende Meldungen gleich raus (-f = follow). Kurz nachdem der Server von außen zugänglich ist, wird er mit Sicherheit auch schon mit Anfragen bombardiert werden. Die Logdatei zeigt dann viele Meldungen dieser Art an:

1
2
3
4
5
6
7
8
9
10
2026-02-05 21:02:26.663 UTC [241357] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:27.152 UTC [241361] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:27.632 UTC [241362] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:28.109 UTC [241363] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:28.594 UTC [241366] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:29.070 UTC [241370] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:29.546 UTC [241371] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:30.033 UTC [241372] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:02:30.514 UTC [241375] postgres@postgres FATAL:  no pg_hba.conf entry for host "200.129.251.3", user "postgres", database "postgres", no encryption
2026-02-05 21:05:33.044 UTC [243731] vaultwarden@vaultwarden FATAL:  no pg_hba.conf entry for host "213.209.159.66", user "vaultwarden", database "vaultwarden", SSL encryption

Wie man sieht gibt es sehr viele schnell aufeinander folgenden Anmeldeversuche, meist zur Datenbank postgres (welche ich natürlich nicht freigegeben habe). Aber auch anderen Kombinationen aus Datenbanken und Nutzernamen werden sicher ausprobiert werden. Die Anmeldefehlversuche können stundenlang so weitergehen und die Logdatei zuspammen. Außerdem hat der Server auch mit dem Ablehnen von Kommunikation etwas zu tun, und das könnte dann irgendwann ein Performanceproblem (Denial-Of-Service) werden.

Zugriff von bestimmten IPs mit der UFW Firewall beschränken

Um die Netzwerkommunikation zu begrenzen, greift man zu einer Firewall. Unter Linux ist die UFW recht bequem und lässt sich auch einfach aus den Paketquellen installieren, bzw. bei Ubuntu bereits standardmäßig installiert. Ansonsten:

1
sudo apt install ufw

WICHTIG: gleich als erste Regel sollte man die Kommunikation via ssh erlauben, sonst sperrt man sich aus dem Server aus.

1
sudo ufw allow ssh

Die Firewall ist dann eigentlich schon bereit und kann eingeschaltet werden:

1
sudo ufw enable

Den Status prüft man mit

1
sudo ufw status verbose

Dieser Befehl gibt eine Liste der konfigurierten Regeln aus. WICHTIG: die Reihenfolge der Regeln ist entscheident!

Standardkonfiguration

Zunächst die Standardregeln setzen (alles blockieren, alles ausgehend erlauben):

1
2
sudo ufw default deny incoming
sudo ufw default allow outgoing

Dieser Webartikel beschreibt typische Regeln: UFW Essentials: Common Firewall Rules and Commands for Linux Security

Dann gewünschte Dienste freigeben, hier also den Standard-PostgreSQL Port:

1
sudo ufw allow 5432/tcp

Man kann den Standard-PostgreSQL-Port auch auf eine andere Portnummer legen, und damit schon eine ganze Menge Hackscripte auf die falsche Fährte locken. Dazu muss man in der Datei postgresql.conf in der Zeile port = 5432 einfach eine andere Zahl eintragen. Natürlich muss man dann in der Firewall auch diesen selbstgewählten Port freigeben.

Zugriff für bosartige IPs verbieten

Man könnte jetzt natürlich mit dem Befehl

1
sudo ufw deny from 103.217.220.251 to any

die gesamte eingehende Kommunikation von der Adresse 103.217.220.251 blockieren (eine der Adressen, die bei mir so schön regelmäßig getestet haben, diesmal aus Pune, Indien).

Nach Änderungen der UFW Konfiguration muss man natürlich die Regeln neu einladen:

1
sudo ufw reload

Wenn man dann allerdings die PostgreSQL-Logs weiter anschaut, wird man feststellen, dass weiterhin eingehende Verbindungen blockiert werden, trotz der neuen Firewall-Regel. Das liegt daran, dass die “Erlaubnis für Kommunikation mit Port 5432 für alle” zuerst gefunden wird, und damit vor der später folgenden “die IP hier darf gar nix”-Regel Vorrang hat.

Man kann sich das auch schön in der Konfigurationsdatei

1
/etc/ufw/user.rules

ansehen.

Um solche Blockierregeln ganz oben einzufügen, verwendet man stattdessen:

1
sudo ufw insert 1 deny from 103.217.220.251 to any

Damit wird die Regel ganz oben eingefügt und stets zuerst bearbeitet.

Grundsätzlich ist es eine gute Idee, die Ausschlussregeln zuerst zu definieren, und dann erst die Erlaubnisregeln aufzulisten.

Automatisches Blockieren von bösartigen/verdächtigen IPs mit fail2ban

Wenn man jetzt eine der aufdringlichen IP-Adressen geblockt hat, dann dauert es keine fünf Minuten und schon klopft eine andere Adresse an. Um nun nicht ständig IP-Adressen manuell zu blocken, könnte man ja die Logdatei vom PostgreSQL-Server mit einem kleinen Dienst überwachen und immer bei unerlaubter Kommunikation die betreffende IP-Adresse in die Ausschlussliste setzen. Genau das ist die Aufgabe von fail2ban.

Fail2ban wird aus den Paketquellen installiert:

1
sudo apt install fail2ban

Eine recht ausführliche Doku zur Konfiguration von fail2ban gibt dieser Blog-Artikel: So installierst und konfigurierst du Fail2ban unter Ubuntu 22.04

This post is licensed under CC BY 4.0 by the author.