Sichern von PostgreSQL-Verbindungen mit SSL/TLS-Konfiguration: Eine vollständige Anleitung

Erfahren Sie, wie Sie PostgreSQL-Verbindungen mit SSL/TLS-Verschlüsselung sichern. Dieser umfassende Leitfaden behandelt die serverseitige und clientseitige Konfiguration, einschließlich der Generierung von Zertifikaten, der Änderung von `postgresql.conf` und `pg_hba.conf` sowie der Einrichtung von Clients für sichere, verschlüsselte Kommunikation. Schützen Sie Ihre sensiblen Daten während der Übertragung und stellen Sie die Einhaltung moderner Sicherheitsstandards sicher.

Sichern von PostgreSQL-Verbindungen mit SSL/TLS-Konfiguration: Eine vollständige Anleitung

Die SSL/TLS-Konfiguration von PostgreSQL umfasst zwei separate Aufgaben. Die erste ist die Verschlüsselung, sodass jemand im Netzwerk keine Anmeldeinformationen oder Abfrageergebnisse während der Übertragung lesen kann. Die zweite ist die Identität, sodass der Client weiß, dass er mit dem echten Datenbankserver spricht und nicht mit einer Maschine, die vorgibt, er zu sein. Viele Konfigurationen erledigen den ersten Teil und überspringen versehentlich den zweiten.

Diese Unterscheidung ist in realen Bereitstellungen von Bedeutung. sslmode=require verschlüsselt die Verbindung, überprüft aber allein nicht vollständig den Server-Hostnamen. sslmode=verify-full tut dies. Wenn Ihre Anwendung über ein öffentliches Netzwerk, ein gemeinsames Unternehmensnetzwerk, ein Kubernetes-Overlay, das Sie nicht vollständig kontrollieren, oder eine andere Umgebung, in der Datenverkehr abgefangen werden könnte, verbindet, sollte verify-full das Ziel sein.

SSL/TLS in PostgreSQL verstehen

SSL/TLS (Secure Sockets Layer/Transport Layer Security) ist ein kryptografisches Protokoll, das die Kommunikationssicherheit über ein Computernetzwerk gewährleisten soll. Bei PostgreSQL verschlüsselt es die zwischen dem Datenbankserver und seinen Clients ausgetauschten Daten. Dies verhindert, dass unbefugte Dritte vertrauliche Informationen wie Anmeldeinformationen, Finanzdaten oder persönliche Details abfangen und lesen.

PostgreSQL-Clients unterstützen mehrere SSL-Modi:

  • sslmode=disable: Nur eine unverschlüsselte Verbindung verwenden.
  • sslmode=prefer: Zuerst TLS versuchen, dann auf einfaches TCP zurückfallen, wenn TLS nicht verfügbar ist. Dies ist praktisch, kann aber Fehlkonfigurationen verbergen.
  • sslmode=require: TLS-Verschlüsselung erzwingen, aber den Server-Hostnamen nicht unbedingt überprüfen.
  • sslmode=verify-ca: TLS erzwingen und überprüfen, ob das Zertifikat zu einer vertrauenswürdigen CA führt.
  • sslmode=verify-full: TLS erzwingen, die CA überprüfen und überprüfen, ob der Hostname mit dem Zertifikat übereinstimmt.

Auf der Serverseite bedeutet ssl = on nur, dass PostgreSQL in der Lage ist, TLS-Verbindungen zu akzeptieren. Es zwingt nicht jeden Client zur Verwendung von TLS. Die Durchsetzung erfolgt in pg_hba.conf mit hostssl-Regeln und durch Vermeidung breiterer host-Regeln, die denselben Benutzern und Netzwerken erlauben, sich ohne TLS zu verbinden.

Voraussetzungen für die SSL/TLS-Konfiguration

Bevor Sie mit der Konfiguration von PostgreSQL für SSL/TLS beginnen, stellen Sie sicher, dass Sie Folgendes haben:

  1. OpenSSL installiert: Das OpenSSL-Toolkit ist für die Generierung und Verwaltung von SSL-Zertifikaten unerlässlich. Es ist normalerweise auf Linux- und macOS-Systemen vorinstalliert. Für Windows müssen Sie es möglicherweise separat herunterladen und installieren.
  2. Zugriff auf PostgreSQL-Konfigurationsdateien: Sie benötigen Administratorrechte, um die Dateien postgresql.conf und pg_hba.conf zu ändern.
  3. Verständnis von Zertifizierungsstellen (CAs): Während Sie für Tests selbstsignierte Zertifikate erstellen können, sollten Produktionsumgebungen idealerweise Zertifikate verwenden, die von einer vertrauenswürdigen Zertifizierungsstelle (CA) oder einer internen Unternehmens-CA signiert wurden.

Serverseitige SSL/TLS-Konfiguration

Die serverseitige Konfiguration umfasst das Aktivieren von SSL, das Angeben des Speicherorts von SSL-Zertifikaten und -Schlüsseln sowie das Konfigurieren der Client-Authentifizierung.

1. Generieren oder Beschaffen von SSL-Zertifikaten und -Schlüsseln

Es gibt zwei Hauptwege, um SSL-Zertifikate für Ihren PostgreSQL-Server zu erhalten:

  • Selbstsignierte Zertifikate (für Tests/Entwicklung): Diese werden mit OpenSSL erstellt und sind standardmäßig nicht von externen Clients vertrauenswürdig. Sie sind nützlich für die erste Einrichtung und interne Tests.
  • Zertifikate von einer Zertifizierungsstelle (CA) (für die Produktion): Beziehen Sie Zertifikate von einer vertrauenswürdigen öffentlichen CA (z. B. Let's Encrypt, DigiCert) oder einer internen Unternehmens-CA. Dadurch wird sichergestellt, dass Clients die Identität des Servers überprüfen können.

Erstellen selbstsignierter Zertifikate mit OpenSSL:

Dies ist ein gängiger Ansatz für Entwicklungs- und interne Umgebungen. Führen Sie die folgenden Befehle auf Ihrem PostgreSQL-Server oder einem Rechner mit OpenSSL aus:

  1. Erstellen Sie ein Verzeichnis für Zertifikate: Es ist gute Praxis, Zertifikate organisiert zu halten.

    sudo mkdir -p /etc/postgresql/ssl
    sudo chown postgres:postgres /etc/postgresql/ssl
    cd /etc/postgresql/ssl
    
  2. Generieren Sie den privaten Serverschlüssel: Dieser Schlüssel sollte geheim gehalten werden.

    sudo openssl genrsa -out server.key 2048
    
  3. Erstellen Sie eine Zertifikatsignieranforderung (CSR) für den Server: Diese enthält Informationen über Ihren Server.

    sudo openssl req -new -key server.key -out server.csr
    

    Verwenden Sie den Hostnamen, mit dem Ihre Clients verbinden werden, z. B. db01.internal.example.com. Moderne Clients prüfen normalerweise den Subject Alternative Name (SAN), daher fügen Sie DNS-Namen in die Zertifikatsanforderung ein, wenn Ihr CA-Prozess dies unterstützt.

  4. Signieren Sie das Zertifikat mit Ihrer eigenen CA (für den internen Gebrauch):

    • Erstellen Sie einen privaten Root-CA-Schlüssel und ein Zertifikat (falls Sie noch keins haben):
      # Generieren Sie den privaten CA-Schlüssel
      sudo openssl genrsa -des3 -out root.key 2048
      # Erstellen Sie das CA-Zertifikat (gültig für 3650 Tage)
      sudo openssl req -new -x509 -days 3650 -key root.key -out root.crt
      
    • Signieren Sie die Server-CSR mit der CA: Dies erstellt das vertrauenswürdige Serverzertifikat.
      sudo openssl x509 -req -days 365 -in server.csr -CA root.crt -CAkey root.key -set_serial 01 -out server.crt
      
  5. Legen Sie Berechtigungen fest: Stellen Sie sicher, dass der PostgreSQL-Benutzer diese Dateien lesen kann.

    sudo chown postgres:postgres server.key server.crt root.crt
    sudo chmod 600 server.key
    sudo chmod 644 server.crt root.crt
    

Verwenden von Zertifikaten einer öffentlichen/Unternehmens-CA:

Wenn Sie Zertifikate von einer CA erhalten, erhalten Sie normalerweise:

  • server.crt: Das öffentliche Zertifikat Ihres Servers.
  • server.key: Der private Schlüssel Ihres Servers.
  • root.crt (oder ähnlich): Das Root-Zertifikat der CA (und möglicherweise Zwischenzertifikate).

Legen Sie diese Dateien in einem sicheren Verzeichnis ab (z. B. /etc/postgresql/ssl/) und stellen Sie sicher, dass der PostgreSQL-Benutzer Leseberechtigungen hat.

2. Konfigurieren von postgresql.conf

Bearbeiten Sie Ihre postgresql.conf-Datei (normalerweise in Ihrem PostgreSQL-Datenverzeichnis), um SSL zu aktivieren und die Zertifikatsdateien anzugeben.

#------------------------------------------------------------------------------
# SSL
#------------------------------------------------------------------------------

ssl = on

# Diese sind alle im PEM-Format und werden ignoriert, wenn Server-Schlüssel/Zertifikat
# nicht konfiguriert sind. Standardmäßig werden die Dateien im Datenverzeichnis des
# Servers erwartet. Alternativ können sie als vollständige Pfade angegeben werden.
ssl_cert_file = '/etc/postgresql/ssl/server.crt'     # (Dateinamen bei Bedarf ändern)
ssl_key_file = '/etc/postgresql/ssl/server.key'      # (Dateinamen bei Bedarf ändern)
ssl_ca_file = '/etc/postgresql/ssl/root.crt'         # (optional, für Client-Zertifikatsprüfung)

# Optional: Geben Sie bei Bedarf eine Chiffre-Liste an
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'

# Optional: Aktivieren Sie die Client-Zertifikatsprüfung
#ssl_ca_file muss auf eine Datei gesetzt werden, die das/die zu vertrauende(n) CA-Zertifikat(e) enthält
#ssl_crl_file = ''
#ssl_crl_dir = ''
  • ssl = on: Aktiviert die SSL-Unterstützung auf dem Server.
  • ssl_cert_file: Pfad zum öffentlichen Zertifikat des Servers.
  • ssl_key_file: Pfad zum privaten Schlüssel des Servers.
  • ssl_ca_file: Pfad zu CA-Zertifikaten, denen PostgreSQL bei der Überprüfung von Client-Zertifikaten vertrauen soll. Clients verwenden ihre eigene CA-Datei, wie z. B. sslrootcert, um den Server zu überprüfen.

3. Konfigurieren von pg_hba.conf für die SSL-Durchsetzung

Die Datei pg_hba.conf steuert die Client-Authentifizierung. Sie müssen Einträge ändern, um SSL-Verbindungen durchzusetzen.

Standardmäßig sehen Einträge in pg_hba.conf so aus:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256

Um SSL durchzusetzen, ändern Sie die host-Einträge in hostssl:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     peer
# IPv4 local connections:
hostssl all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
hostssl all             all             ::1/128                 scram-sha-256

# Beispiel für externen Netzwerkzugriff - erfordert SSL
hostssl all             app_user        10.20.0.0/16            scram-sha-256
hostssl all             app_user        2001:db8:20::/48        scram-sha-256
  • hostssl: Dieser Datensatztyp erfordert SSL-Verbindungen. Jeder Verbindungsversuch ohne SSL wird abgelehnt.
  • hostnossl: Dieser Datensatztyp verbietet SSL-Verbindungen ausdrücklich.
  • host: Erlaubt sowohl SSL- als auch Nicht-SSL-Verbindungen. Wenn eine passende host-Regel vor oder anstelle Ihrer hostssl-Regel existiert, können Clients möglicherweise immer noch ohne TLS verbinden.

Vermeiden Sie die Veröffentlichung von 0.0.0.0/0-Zugriff, es sei denn, es gibt einen triftigen Grund und andere Kontrollen sind vorhanden. Die meisten Produktionsdatenbanken sollten Verbindungen nur von Anwendungssubnetzen, Bastion-Hosts, Verbindungspoolern oder privaten Netzwerkbereichen akzeptieren.

4. Neustart des PostgreSQL-Servers

Nachdem Sie postgresql.conf und pg_hba.conf geändert haben, müssen Sie den PostgreSQL-Dienst neu starten, damit die Änderungen wirksam werden.

# Für Systeme mit systemd (die meisten modernen Linux-Distributionen)
sudo systemctl restart postgresql

# Für Systeme mit init.d
sudo service postgresql restart

Clientseitige SSL/TLS-Konfiguration

Clients müssen ebenfalls konfiguriert werden, um sicher zu verbinden. Dies umfasst das Angeben von Verbindungsparametern, das mögliche Bereitstellen von Client-Zertifikaten und das Überprüfen des Server-Zertifikats.

1. Verbindungszeichenfolgen-Parameter

Wenn Sie über psql oder eine beliebige PostgreSQL-Clientbibliothek verbinden, können Sie SSL-Parameter in der Verbindungszeichenfolge oder als einzelne Optionen angeben.

Basis-SSL-Verbindung (nur Server-Authentifizierung):

psql "sslmode=require host=your_server_hostname dbname=your_db user=your_user"
  • sslmode: Steuert das SSL-Verhalten des Clients.
    • disable: Nur Nicht-SSL-Verbindungen zulassen.
    • allow: Nicht-SSL zulassen, aber SSL bevorzugen, wenn der Server es unterstützt.
    • prefer (Standard): SSL bevorzugen, aber Nicht-SSL zulassen, wenn SSL fehlschlägt.
    • require: Nur SSL-Verbindungen zulassen. Wenn der Server SSL nicht unterstützt, schlägt die Verbindung fehl.
    • verify-ca: Nur SSL-Verbindungen zulassen und überprüfen, ob das Server-Zertifikat von einer vertrauenswürdigen CA signiert ist. Der Parameter sslrootcert muss gesetzt sein.
    • verify-full: Nur SSL-Verbindungen zulassen, das Server-Zertifikat gegen eine vertrauenswürdige CA überprüfen und überprüfen, ob der Server-Hostname mit dem Common Name (CN) oder Subject Alternative Name (SAN) des Zertifikats übereinstimmt.

Überprüfen des Server-Zertifikats (verify-ca oder verify-full):

Für erhöhte Sicherheit sollten Clients die Identität des Servers überprüfen. Dies erfordert, dass der Client der CA vertraut, die das Server-Zertifikat signiert hat.

  1. Holen Sie das CA-Zertifikat: Besorgen Sie sich die Datei root.crt (oder das entsprechende CA-Zertifikat), die zum Signieren des Server-Zertifikats verwendet wurde.
  2. Geben Sie sslrootcert an: Teilen Sie dem Client mit, wo er dieses CA-Zertifikat findet.
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user sslrootcert=/path/to/your/root.crt"

Dies ist die Verbindungszeichenfolge, die Sie von demselben Host oder Container aus testen sollten, der die Anwendung ausführt. Ein häufiger Fehler ist, dass psql von einem Administrator-Laptop aus funktioniert, weil die CA-Datei dort existiert, während der Anwendungscontainer fehlschlägt, weil das CA-Bundle nie eingebunden wurde.

2. Client-Zertifikate (Gegenseitige Authentifizierung)

Für ein noch höheres Sicherheitsniveau können Sie eine gegenseitige Authentifizierung implementieren, bei der der Server auch die Identität des Clients mithilfe von Client-Zertifikaten überprüft.

Generieren von Client-Zertifikaten:

Ähnlich wie bei Server-Zertifikaten benötigen Sie einen privaten Client-Schlüssel und ein Client-Zertifikat, das von einer vom Server vertrauenswürdigen CA signiert ist (oft dieselbe CA wie das Server-Zertifikat).

  1. Generieren Sie den privaten Client-Schlüssel:

    openssl genrsa -des3 -out client.key 2048
    
  2. Erstellen Sie eine Client-CSR:

    openssl req -new -key client.key -out client.csr
    

    Geben Sie Details an und stellen Sie sicher, dass der Common Name für den Client eindeutig ist.

  3. Signieren Sie die Client-CSR mit der CA:

    sudo openssl x509 -req -days 365 -in client.csr -CA root.crt -CAkey root.key -set_serial <unique_serial> -out client.crt
    
  4. Legen Sie Berechtigungen fest:

    chmod 600 client.key
    chmod 644 client.crt
    

Konfigurieren von pg_hba.conf für die Client-Zertifikatsauthentifizierung:

Auf dem Server müssen Sie pg_hba.conf konfigurieren, um die Client-Zertifikatsauthentifizierung zu akzeptieren. Dies verwendet oft die cert-Authentifizierungsmethode.

# TYPE  DATABASE        USER            ADDRESS                 METHOD
# SSL und Client-Zertifikatsauthentifizierung für bestimmten Benutzer/Datenbank erzwingen
hostssl all             your_user       your_client_ip/32       cert map=your_cert_map

Möglicherweise müssen Sie auch eine Zertifikatszuordnungsdatei (cert_map-Option) definieren, wenn Sie bestimmte Client-Zertifikatsdetails (wie Subject oder SubjectAltName) PostgreSQL-Benutzern zuordnen möchten. Konsultieren Sie die PostgreSQL-Dokumentation für detaillierte cert-Authentifizierungs- und Zertifikatszuordnungseinrichtung.

Konfigurieren des Clients zur Verwendung von Zertifikaten:

Aktualisieren Sie die Verbindungszeichenfolge des Clients, um Pfade zu seinem Zertifikat und Schlüssel einzuschließen:

psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user \
sslrootcert=/path/to/your/root.crt sslcert=/path/to/your/client.crt sslkey=/path/to/your/client.key"

Best Practices und Tipps

  • Verwenden Sie sslmode=verify-full: Streben Sie an, auf der Clientseite verify-full zu verwenden, um das Man-in-the-Middle-Risiko zu reduzieren.
  • Schützen Sie private Schlüssel: Stellen Sie sicher, dass private Schlüssel (.key-Dateien) strenge Dateiberechtigungen haben (z. B. chmod 600) und nur vom PostgreSQL-Benutzer auf dem Server und dem verbindenden Benutzer auf dem Client gelesen werden können.
  • Erneuern Sie Zertifikate regelmäßig: Zertifikate haben Ablaufdaten. Implementieren Sie einen Prozess, um sie vor ihrem Ablauf zu erneuern, um Verbindungsunterbrechungen zu vermeiden.
  • Zentralisiertes Zertifikatsmanagement: Erwägen Sie für größere Bereitstellungen die Verwendung eines Zertifikatsverwaltungssystems oder die Automatisierung der Zertifikatsausstellung und -erneuerung.
  • Überwachen Sie Protokolle: Überprüfen Sie die PostgreSQL-Protokolle auf SSL-bezogene Fehler während des Starts oder von Verbindungsversuchen.
  • Dokumentation: Lesen Sie die offizielle PostgreSQL-Dokumentation für die aktuellsten Parameter und erweiterten Konfigurationsoptionen, die für Ihre PostgreSQL-Version spezifisch sind.

Schnelle Überprüfungs-Checkliste

Überprüfen Sie nach dem Neustart von PostgreSQL, ob der Server mit aktiviertem TLS lauscht:

SHOW ssl;
SHOW ssl_cert_file;
SHOW ssl_key_file;

Testen Sie dann von einem Client-Host aus:

psql "host=your_server_hostname dbname=your_db user=your_user sslmode=verify-full sslrootcert=/path/to/root.crt"

Bestätigen Sie innerhalb der Sitzung, dass die Verbindung verschlüsselt ist:

SELECT ssl, version, cipher
FROM pg_stat_ssl
WHERE pid = pg_backend_pid();

Wenn ssl falsch ist, erzwingen Ihre pg_hba.conf-Regeln nicht das, was Sie denken. Wenn verify-full fehlschlägt, aber require funktioniert, fehlt dem Zertifikat wahrscheinlich der richtige Hostname, der Client vertraut der CA nicht oder die Anwendung verbindet über eine IP-Adresse, während das Zertifikat für einen DNS-Namen ausgestellt ist.

Eine gute PostgreSQL-TLS-Einrichtung ist nicht nur ssl = on. Es ist eine Kette: ein Zertifikat mit den richtigen Namen, private Schlüssel mit strengen Berechtigungen, hostssl-Regeln, die TLS tatsächlich durchsetzen, und Clients, die den Server überprüfen, anstatt nur den Socket zu verschlüsseln.