BLOG | NGINX

Schützen von privaten SSL-Schlüsseln in NGINX mit HashiCorp Vault

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Owen Garrett Miniaturbild
Owen Garrett
Veröffentlicht am 16. April 2019

Im ersten Beitrag dieser Reihe beschreiben wir mehrere Ansätze zur Verbesserung der Sicherheit Ihrer privaten SSL-Schlüssel. Der Beitrag endete mit einer Demonstration eines Remote Password Distribution Point (PDP), der zum sicheren Teilen von Verschlüsselungskennwörtern mit NGINX-Instanzen verwendet wird.

Geheimnisverwaltungssysteme wie HashiCorp Vault funktionieren ähnlich wie dieses Beispiel-PDP:

  • Sie verwenden einen zentralen (oder hochverfügbaren und verteilten) Geheimdienst, auf den über HTTPS oder eine andere API zugegriffen werden kann
  • Die Authentifizierung der Clients erfolgt über Authentifizierungstoken oder andere Mittel
  • Token können bei Bedarf widerrufen werden, um den Zugriff auf das Geheimnis zu kontrollieren

In diesem Beitrag zeigen wir, wie man HashiCorp Vault zum Verteilen von SSL-Passwörtern einrichtet. Für noch mehr Sicherheit können Sie ein externes Hardware-Sicherheitsmodul (HSM) einrichten .

Um die Speicherung von SSL-Zertifikatschlüsselpaaren auf der Festplatte vollständig zu vermeiden, lesen Sie den dritten Beitrag dieser Reihe: „Verwenden des Schlüssel-Wert-Speichers von NGINX Plus zum Sichern temporärer SSL-Schlüssel aus HashiCorp Vault“ . Es wird erklärt, wie temporäre SSL-Schlüssel aus HashiCorp Vault generiert und im Schlüssel-Wert-Speicher von NGINX Plus gespeichert werden.

Dieser Beitrag gilt sowohl für NGINX Open Source als auch für NGINX Plus. Der Einfachheit halber beziehen wir uns durchgehend auf NGINX .

Verwenden von HashiCorp Vault zum Schützen privater SSL-Schlüssel

Die Anweisungen in diesem Abschnitt richten einen zentralen PDP-Server mit Vault ein, um SSL-Passwörter zu verteilen. Sie basieren auf den Anweisungen von DigitalOcean . Ändern Sie sie nach Bedarf, um Ihren eigenen Vault-Richtlinien zu entsprechen.

In unserem Beispiel verfügt jeder Remote-Webserver über ein eindeutiges Authentifizierungstoken. Diese Token können verwendet werden, um auf Geheimnisse im Pfad secret/webservers/ von Vault zuzugreifen, und wir speichern die SSL-Passwörter in secret/webservers/ssl_passwords .

Wir werden sehen, wie die Token gesichert werden und wie einzelne Authentifizierungstoken bei Bedarf widerrufen werden.

Herunterladen, Installieren und Initialisieren von HashiCorp Vault auf dem PDP-Server

  1. Befolgen Sie die Anweisungen von DigitalOcean, um Vault auf Ihren PDP-Server herunterzuladen und zu extrahieren. Wir verwenden die folgende Beispieldatei /etc/vault.hcl , um Vault remote zugänglich zu machen und TLS zu deaktivieren (zur einfacheren Verwendung beim Testen):

    Backend „Datei“ { Pfad = „/var/lib/vault“
    }
    
    Listener „tcp“ {
    Adresse = „0.0.0.0:8200“
    tls_disable = 1
    }
    
  2. Starten Sie Vault mithilfe der Startskripts (sofern Sie diese erstellt haben) oder manuell:

    Benutzer@pdp:~$ sudo /usr/local/bin/vault server -config=/etc/vault.hcl
    
  3. Initialisieren Sie Vault und erhalten Sie das anfängliche Root-Token:

    Benutzer@pdp:~$ export VAULT_ADDR=http://localhost:8200 Benutzer@pdp:~$ vault init -key-shares=3 -key-threshold=2 Benutzer@pdp:~$ vault operator unseal Initial Root Token: 86c5c2a4-8ab2-24dd-1816-48449c83114e
    
  4. In vielen der folgenden Befehle müssen wir das anfängliche Root-Token angeben. Der Einfachheit halber weisen wir es der Shell-Variable root_token zu:

    Benutzer@pdp:~$ root_token=86c5c2a4-8ab2-24dd-1816-48449c83114e
    

Bewahren Sie die Geheimnisse auf

  1. Arbeiten Sie noch immer am PDP-Server und erstellen Sie eine temporäre Datei namens /tmp/ssl_passwords.txt mit den darin enthaltenen Passwörtern.

  2. Speichern Sie diese Datei geheim in Vault und überprüfen Sie, ob Sie sie abrufen können:

    Benutzer@pdp:~$ VAULT_TOKEN=$root_token vault kv put secret/webservers/ssl_passwords value=@/tmp/ssl_passwords.txt Benutzer@pdp:~$ VAULT_TOKEN=$root_token vault kv get -field=Wert secret/webservers/ssl_passwords password1 password2 …
    
  3. Löschen Sie aus Sicherheitsgründen /tmp/ssl_passwords.txt .

  4. Erstellen Sie eine Richtlinienspezifikation in einer Datei namens web.hcl mit folgendem Inhalt:

    Pfad "secret/webservers/*" {
    Fähigkeiten = ["lesen"]
    }
    
  5. Laden Sie die Richtlinie in Vault und nennen Sie sie web :

    Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresorrichtlinie schreibt Web web.hcl
    
  6. Erstellen Sie ein neues Authentifizierungstoken, verknüpfen Sie es mit der Webrichtlinie und fügen Sie optional den Anzeigename- Parameter ein, um ihm einen benutzerfreundlichen Namen zu geben. Notieren Sie sich die Token- und Token_Accessor -Werte. Sie werden sie in den nachfolgenden Befehlen verwenden:

    Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresor-Token erstellen -policy=web -display-name=webserver1 Schlüsselwert --- ----- Token dcf75ffd-a245-860f-6960-dc9e834d3385 Token_Accessor 0c1d6181-7adf-7b42-27be-b70cfa264048
    

    Der NGINX-Webserver verwendet dieses Token, um die SSL-Passwörter abzurufen. Die Webrichtlinie verhindert, dass der Webserver Geheimnisse außerhalb des Pfads secret/webservers/* abruft.

Überprüfen, ob der Webserver das Token abrufen kann

  1. Installieren Sie die Vault-Binärdatei, indem Sie auf dem NGINX-Webserver arbeiten.
  2. Geben Sie den Standort des Remote-Vault-Servers an (hier http://pdp:8200 ) und überprüfen Sie anschließend, ob der Webserver-Computer die SSL-Passwörter mithilfe des Tokens abrufen kann:

    Benutzer@Web1:~$ export VAULT_ADDR=http://pdp:8200 Benutzer@Web1:~$ VAULT_TOKEN=dcf75ffd-a245-860f-6960-dc9e834d3385 Vault kv get -field=Wert Geheimnis/Webserver/SSL-Passwörter Passwort1 Passwort2 …
    

Konfigurieren des NGINX Vault Connectors auf dem Webserver

  1. Als Teil der Einrichtung des Beispiel-PDP im ersten Beitrag haben wir ein Shell-Skript namens connector.sh auf dem NGINX-Host (Webserver-Computer) erstellt. Hier ändern wir es, um Vault zu verwenden:

    #!/bin/sh
    # Verwendung: connector_v.sh 
    
    CONNECTOR=$1
    CREDS=$2
    
    [ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
    
    mkfifo $CONNECTOR; chmod 600 $CONNECTOR
    
    export VAULT_ADDR=http://pdp:8200
    export VAULT_TOKEN=$CREDS
    
    while true; do
    vault kv get -field=value secret/webservers/ssl_passwords > $CONNECTOR
    sleep 0.1 # Race Condition, stellt EOF sicher
    done
    
  2. Führen Sie das Skript als Hintergrundprozess aus, der wie folgt aufgerufen wird:

    root@web1:~# ./connector_v.sh /var/run/nginx/ssl_passwords \dcf75ffd-a245-860f-6960-dc9e834d3385 &
    
  3. Testen Sie den Connector, indem Sie den Connector-Pfad lesen:

    root@web1:~$ cat /var/run/nginx/ssl_passwords Passwort1 Passwort2 …
    
  4. Konfigurieren Sie NGINX so, dass die Datei „ssl_passwords“ beim Start gelesen wird und der Inhalt als Kennwörter zum Entschlüsseln verschlüsselter privater Schlüssel verwendet wird. Sie können die Direktive ssl_password_file entweder in einen Serverblock (wie den, der im ersten Beitrag für die Standardkonfiguration erstellt wurde) oder in den HTTP- Kontext einfügen, um sie auf mehrere virtuelle Server anzuwenden:

    SSL-Passwortdatei /var/run/nginx/ssl_passwords;
    
  5. Überprüfen Sie, ob NGINX das Kennwort lesen und die SSL-Schlüssel entschlüsseln kann:

    root@web1:~# nginx -t nginx: die Syntax der Konfigurationsdatei /etc/nginx/nginx.conf ist in Ordnung nginx: Der Test der Konfigurationsdatei /etc/nginx/nginx.conf war erfolgreich
    

Widerrufen des Authentifizierungstokens eines Webservers

Sie können den Zugriff problemlos widerrufen, wenn der Webserver kompromittiert oder außer Betrieb genommen wird. Dazu können Sie das vom Webserver verwendete Authentifizierungstoken direkt widerrufen:

Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresor-Token widerrufen dcf75ffd-a245-860f-6960-dc9e834d3385

Vault-Token sind vertrauliche Datenelemente und viele Vault-Workflows speichern keine Kopien von Token, die an einen authentifizierten Client ausgegeben werden. Wenn eine Kopie eines Tokens durchsickert, kann ein Angreifer die Identität des Clients annehmen.

Stattdessen ist es üblich, ein aktives Token mithilfe seines Accessors zu verwalten, der eingeschränkte Rechte für das Token erteilt und nicht zum Abrufen des Tokenwerts verwendet werden kann. Anstatt Token bei ihrer Ausgabe zu speichern, speichern Sie den entsprechenden Accessor.

Wenn Sie den Accessor für das Authentifizierungstoken eines Webservers ermitteln müssen, führen Sie den Befehl „Vault List“ aus, um die Liste der Accessoren abzurufen, und den Befehl „Vault Token Lookup für jeden Accessor, um denjenigen mit dem entsprechenden Anzeigenamen und der entsprechenden Richtlinie zu finden:

Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresorliste /auth/token/accessors Schlüssel ---- 83be5a73-9025-1221-cb70-4b0e8a3ba8df 0c1d6181-7adf-7b42-27be-b70cfa264048 f043b145-7a63-01db-ea85-9f22f413c55e Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresortokensuche -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048 Schlüsselwert --- ----- ... Anzeigename Webserver1 ... Richtlinie Web ...

Sie können das Token dann mit seinem Accessor widerrufen:

Benutzer@pdp:~$ VAULT_TOKEN=$root_token Tresor-Token widerrufen -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048

Auswirkungen auf die Sicherheit

Die Verwendung von Vault verfügt über ein ähnliches Sicherheitsprofil wie das im ersten Beitrag beschriebene Beispiel-PDP. An private SSL-Schlüssel kann nur gelangt werden, wenn das entsprechende Passwort vorliegt, und hierzu muss ein Angreifer den Wert eines aktuellen Authentifizierungstokens kennen.

Der Hauptvorteil der Verwendung von Vault besteht in der Automatisierung und Skalierung des geheimen Speichers.

Verwenden eines externen HSM zum Verwalten privater Schlüssel

Keine der Lösungen, die wir bisher in dieser Reihe behandelt haben, schützt den privaten Schlüssel, wenn ein Angreifer Root- Zugriff auf den NGINX-Server erhält. Wenn ein Angreifer auf den Laufzeitspeicher von NGINX zugreifen oder einen Core Dump generieren kann, gibt es bekannte Techniken, um den Speicher des Prozesses zu scannen und private Schlüsseldaten zu lokalisieren.

Externe Hardware-Sicherheitsmodule (HSMs) beheben dieses Problem, indem sie die privaten SSL-Schlüssel auf externer, manipulationssicherer Hardware speichern. Sie bieten die Entschlüsselung als Dienst an und NGINX greift auf diesen Dienst zu, wenn es einen SSL-Vorgang ausführen muss, der das Verschlüsselungsverfahren erfordert.

Der NGINX-Server sieht die privaten SSL-Schlüsseldaten nie. Ein Angreifer, der Root- Zugriff auf den Server erhält, kann zwar nicht an den privaten SSL-Schlüssel gelangen, kann die Daten jedoch bei Bedarf entschlüsseln, indem er mit den NGINX-Anmeldeinformationen auf den HSM-Entschlüsselungsdienst zugreift.

Konfigurieren von NGINX für den Zugriff auf ein HSM

NGINX delegiert alle SSL-Private-Key-Operationen an eine Kryptobibliothek namens OpenSSL. HSM-Geräte von Drittanbietern können für NGINX verfügbar gemacht werden, indem die OpenSSL-Engine des HSM-Anbieters verwendet wird.

Die NGINX-Konfiguration ist für jedes Anbieter-HSM spezifisch, folgt jedoch im Allgemeinen einem einfachen Pfad:

  • Konfigurieren Sie NGINX so, dass die OpenSSL-Engine des Anbieters anstelle der Standardsoftware-Engine verwendet wird:

    SSL-Zertifikatschlüssel -Engine: Anbieter-HSM-Engine: …;
    
  • Konfigurieren Sie NGINX so, dass statt des echten privaten Schlüssels der vom Anbieter bereitgestellte „gefälschte“ Schlüssel verwendet wird. Dieser Schlüssel enthält einen Handle, der den echten Schlüssel auf dem HSM-Gerät identifiziert:

    SSL-Zertifikatsschlüssel ssl/vendor.private.key;
    

    Der Schlüssel kann auch die Anmeldeinformationen für den Zugriff auf das HSM-Gerät enthalten, oder die Anmeldeinformationen können mithilfe einer zusätzlichen anbieterspezifischen Konfiguration bereitgestellt werden.

  • (Optional) Nehmen Sie die gewünschten Optimierungen vor, z. B. eine Erhöhung der Anzahl der NGINX-Arbeitsprozesse, um die Leistung von NGINX und HSM zu maximieren.

Ein Beispiel für die HSM-Einrichtung finden Sie in der CloudHSM-Dokumentation von Amazon .

Auswirkungen auf die Sicherheit

Externe HSMs sind eine äußerst sichere Methode zum Speichern von privaten SSL-Schlüsseln. Ein Angreifer mit Root- Zugriff auf den NGINX-Server kann die NGINX-Anmeldeinformationen nutzen, um mithilfe des HSM beliebige Daten zu entschlüsseln, ist jedoch nicht in der Lage, den unverschlüsselten privaten Schlüssel zu erhalten. Ein HSM macht es einem Angreifer erheblich schwerer, sich als eine Website auszugeben oder beliebige Daten offline zu entschlüsseln.

Abschluss

Es muss unbedingt sichergestellt werden, dass geheime Daten wie der private SSL-Schlüssel vollständig geschützt sind, denn eine Offenlegung hätte schwerwiegende Folgen.

Für viele Organisationen mit entsprechenden Sicherheitsprozessen ist es ausreichend, den privaten Schlüssel auf den Frontend-Load Balancern zu speichern und dann den gesamten Zugriff auf diese Server zu beschränken und zu prüfen (die im ersten Beitrag beschriebene Standardkonfiguration ).

Organisationen, die die NGINX-Konfiguration häufig bereitstellen müssen, können mit den Maßnahmen in diesem und dem ersten Beitrag die Benutzer oder Entitäten einschränken, die die privaten Schlüsseldaten sehen können.

Im dritten Beitrag dieser Reihe, „Sichern temporärer SSL-Schlüssel aus HashiCorp Vault mit dem Schlüssel-Wert-Speicher von NGINX Plus“ , erklären wir, wie die Bereitstellung von Schlüsseln und Zertifikaten aus Vault in den Schlüssel-Wert-Speicher von NGINX Plus mithilfe der NGINX Plus-API automatisiert wird.

Beachten Sie erneut, dass keine dieser Methoden die Notwendigkeit reduziert, die laufenden NGINX-Instanzen vollständig vor Remotezugriff oder Konfigurationsmanipulation zu schützen.

Probieren Sie NGINX Plus selbst aus – starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen .


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."