it-swarm.com.de

NGinx-SSL-Zertifikatauthentifizierung von zwischengeschalteter Zertifizierungsstelle (Kette)

Ich versuche, die Authentifizierung des Clientzertifikats in Nginx zu aktivieren, wenn die Zertifikate von einer zwischengeschalteten Zertifizierungsstelle signiert wurden. Wenn ich ein von einer selbstsignierten Stammzertifizierungsstelle signiertes Zertifikat benutze, kann ich dies problemlos ausführen. Dies funktioniert jedoch nicht, wenn die signierende Zertifizierungsstelle eine Zwischenzertifizierungsstelle ist.

Mein einfacher Serverabschnitt sieht folgendermaßen aus:

server {
    listen       443;
    server_name  _;

    ssl                  on;
    ssl_certificate      cert.pem;
    ssl_certificate_key  cert.key;

    ssl_session_timeout  5m;

    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;

    ssl_client_certificate ca.pem;
    ssl_verify_client on;
    ssl_verify_depth 1;

    location / {
        root   html;
        index  index.html index.htm;
    }
}

Für den Inhalt von ca.pem habe ich versucht, only die Zwischen-CA zu verwenden und auch das Zwischen-CA-Zertifikat und das Root-CA-Zertifikat zu verketten, d. H.

cp intermediate.crt ca.pem
cat root.crt >> ca.pem

Ich habe auch bestätigt, dass das Zertifikat aus der Sicht von openssl gültig ist, wenn dieselbe CA-Kette verwendet wird:

openssl verify -CAfile /etc/nginx/ca.pem certs/client.crt 
certs/client.crt: OK

Ich habe experimentiert mit der Einstellung von ssl_verify_depth explizit auf 1 (wie oben) und dann sogar auf 0 (nicht sicher, was diese Zahl genau bedeutet), aber immer noch den gleichen Fehler erhalten.

Der Fehler, den ich in allen Varianten der eingebundenen Zertifizierungsstelle bekomme, lautet "400 Bad Request" und genauer "Der SSL-Zertifikatfehler" (nicht genau wissen, was das genau bedeutet).

Vielleicht unterstützt nginx nur Zertifikatsketten für Zwischenzertifikate? Jede Hilfe sehr geschätzt!

31
Hans L

Edit: Ich hatte auch dieses "Problem", Lösung und Erklärung sind am Ende des Textes

Es scheint, als würde nginx keine Zwischenzertifikate unterstützen. Meine Zertifikate selbst erstellt: (RootCA ist selbst signiert, IntrermediateCA1 ist von RootCA signiert usw.)

RootCA -> IntermediateCA1 -> Client1 
RootCA -> IntermediateCA2 -> Client2

Ich möchte in nginx "IntermediateCA1" verwenden, um nur dem Besitzer des Zertifikats "Client1" Zugriff auf die Site zu gewähren.

Wenn ich die Datei "ssl_client_certificate" mit IntermediateCA1 und RootCA setze und "ssl_verify_depth 2" (oder mehr) setze, können sich die Clients sowohl mit dem Zertifikat Client1 als auch mit Client2 anmelden (sollte nur Client1). Das gleiche Ergebnis ist, wenn ich die Datei "ssl_client_certificate" mit only rootCA setze - beide Clients können sich anmelden.

Wenn ich die Datei "ssl_client_certificate" mit only IntermediateCA1 setze und "ssl_verify_depth 1" (oder "2" oder mehr - egal) setze, ist das Anmelden unmöglich, ich bekomme den Fehler 400. Im Debug-Modus Ich sehe Protokolle:

verify:0, error:20, depth:1, subject:"/C=PL/CN=IntermediateCA1/[email protected]",issuer: "/C=PL/CN=RootCA/[email protected]"
verify:0, error:27, depth:1, subject:"/C=PL/CN=IntermediateCA1/[email protected]",issuer: "/C=PL/CN=RootCA/[email protected]"
verify:1, error:27, depth:0, subject:"/C=PL/CN=Client1/[email protected]",issuer: "/C=PL/CN=IntermediateCA1/[email protected]"
(..)
client SSL certificate verify error: (27:certificate not trusted) while reading client request headers, (..)

Ich denke das ist ein Fehler. Getestet auf Ubuntu, nginx 1.1.19 und 1.2.7-1 ~ dotdeb.1, openssl 1.0.1 . Ich sehe, dass nginx 1.3 einige weitere Optionen für die Verwendung von Client-Zertifikaten hat, aber ich würde keine Lösung für dieses Problem finden .

Derzeit besteht die einzige Möglichkeit, die Clients 1 und 2 voneinander zu trennen, in der Erstellung von zwei selbstsignierten Root-CAs. Dies ist jedoch nur eine Problemumgehung.

Edit 1: Ich habe dieses Problem hier gemeldet: http://trac.nginx.org/nginx/ticket/301

Edit 2 " * Ok, es ist kein Fehler, es ist eine Funktion;) *

Ich erhalte die Antwort hier: http://trac.nginx.org/nginx/ticket/301Es funktioniert, Sie müssen nur überprüfen, was Ihr ssl_client_i_dn ist (. Anstelle des Emittenten können Sie dies tun Verwenden Sie auch den Betreff des Zertifikats oder was Sie wollen von http://wiki.nginx.org/HttpSslModule#Built-in_variables

So funktioniert die Zertifikatsüberprüfung: Das Zertifikat muss .__ sein. bis zu einem vertrauenswürdigen root verifiziert. Wenn die Kette nicht zu einem vertrauenswürdigen .__ aufgebaut werden kann. root (nicht zwischen) - Überprüfung fehlgeschlagen. Wenn Sie root - all Vertrauen. Von ihr direkt oder indirekt signierte Zertifikate werden erfolgreich verifiziert 

Eine begrenzte Überprüfungstiefe kann verwendet werden, wenn Sie möchte Client-Zertifikate auf direkt ausgegebene Zertifikate beschränken nur, aber es geht mehr um DoS-Prävention, und offensichtlich kann es nicht .__ sein. Wird verwendet, um das Zertifikat auf intermedi1 zu beschränken (aber nicht intermedi2). 

Was Sie hier wollen, ist ein Authorization Layer-basierter auf dem Überprüfungsergebnis - d. h. Sie möchten die .__ des Clients überprüfen. Der Aussteller des Zertifikats ist mittelschwer1. Die einfachste Lösung wäre zu Ablehnen von Anforderungen, wenn der DN des Ausstellers nicht mit einem zulässigen übereinstimmt, z. B. . so etwas (völlig ungeprüft):

[Bearbeiten von mir, es funktioniert korrekt in meiner Konfiguration]

server {
    listen 443 ssl;

    ssl_certificate ...
    ssl_certificate_key ...

    ssl_client_certificate /path/to/ca.crt;
    ssl_verify_client on;
    ssl_verify_depth 2;

    if ($ssl_client_i_dn != "/C=PL/CN=IntermediateCA1/[email protected]") {
        return 403;
    }
}
44
Jack

Haben Sie versucht, die ssl_verify_depth-Direktive zu erhöhen? Dokumente sagen:

(it) sets a verification depth in the client certificates chain.

Ihre Prüftiefe ist jedoch 1. Sie sagen:

Ich habe experimentiert mit dem Setzen von ssl_verify_depth explizit auf 1 (wie oben) und dann sogar auf 0 (nicht sicher, was diese Zahl genau bedeutet), aber immer noch den gleichen Fehler erhalten.

Also probiere 2 oder 3 ..

PS:Überall dort, wo ich dieses Problem anspreche, wird empfohlen, CA-Zwischenzertifikate mit Ihrem Serverzertifikat zu kombinieren. in eine Datei (wie @ vikas-nalwar vorgeschlagen und Sie haben es getan) in der Reihenfolge der Überprüfung (aber ich bin nicht sicher, ob die Reihenfolge von Bedeutung ist) und grob gesagt ssl_verify_depth auf die Anzahl der Zertifikate im Bundle setzen.

11
Andrew D.

Ich glaube, Sie möchten die Client-Validierung auf Ihrer Serverseite aktivieren. In diesem Fall sehe ich nicht, dass Sie Ihr Client-Zertifikat in der Kette haben. Versuchen Sie Folgendes in genau derselben Reihenfolge. Verwenden Sie die certchain.pem. 

  cat client.crt > certchain.pem
  cat intermediate.crt >> certchain.pem
  cat root.crt >> certchain.pem
2
Drona


ssl_client_certificate /etc/nginx/ssl/ca-bundle-client.crt; ssl_verify_client optional_no_ca; ssl_verify_depth 2;

Die zweite Zeile mit  optional_no_ca  ist der wichtige Teil

2
Tal

Ich muss sagen, dass es mit nginx/1.13.2 gut funktioniert, d. H.

  • Ich habe eine Stammzertifizierungsstelle, die zwei Zwischenzertifizierungsstellen signiert hat
  • beide Vermittler unterzeichneten jeweils einen Kunden
  • Ich bestätige die Zertifikate wie cat client-intermediate1.crt ca-client.crt > ca.chained1.crt und cat client-intermediate2.crt ca-client.crt > ca.chained2.crt und cat ca.chained1.crt ca.chained2.crt > ca.multiple.intermediate.crt

  • wenn ich nur ca.chained1.crt als ssl_client_certificate setze, kann sich nur client1.crt verbinden, ebenfalls für ca.chained2.crt/client2.crt

  • wenn ich ca.multiple.intermediate.crt verwende, können sich beide Clients verbinden

um ein Zwischenprodukt zu widerrufen, entfernen Sie einfach die cert-Kette von ca.multiple.intermediate.crt

hier ist die relevante config. es hat auch hohe Sicherheitseinstellungen

# minimum settings for ssl client auth 
ssl_client_certificate /etc/ssl/ca.multiple.intermediate.crt;
ssl_verify_client on;
ssl_verify_depth 2;

# ssl high security settings (as of writing this post)
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

wenn Sie die Zertifikate CN analysieren und an das Backend übergeben möchten, fügen Sie diesen AUSSEN den server {..-Block hinzu

# parse out CN
map $ssl_client_s_dn $ssl_client_s_dn_cn {
    default "should_not_happen";
    ~CN=(?<CN>[^,]+) $CN;
}

und innerhalb des Blocks kannst du ihn dann benutzen

# add headers for backend containing SSL DN/CN
add_header X-SSL-client-s-dn $ssl_client_s_dn;
add_header X-SSL-client-s-dn_cn $ssl_client_s_dn_cn;
1
pHiL

eine andere einfache Möglichkeit besteht darin, Zertifikate (einschließlich Domänenzertifikat) in einer einzigen Datei zu verketten und diese auf Ihren Servern und der Nginx-Conf-Datei zu verwenden

cat www.example.com.crt bundle.crt> www.example.com.chained.crt

Denken Sie immer daran, zuerst das Serverzertifikat und dann nur CA-Serverzertifikate zu verwenden

Weitere Informationen finden Sie unter http://nginx.org/de/docs/http/configuring_https_servers.html#chains

0
Naveen