NGINX authentification du certificat SSL signée par l'AC intermédiaire (chaîne)

j'essaie d'activer l'authentification du certificat client dans nginx où les certificats ont été signés par une AC intermédiaire. Je suis capable d'obtenir ce bon de travail lorsque j'utilise un certificat signé par une AC racine auto-signée; cependant, cela ne fonctionne pas lorsque L'AC de signature est une AC intermédiaire.

ma section de serveur simple ressemble à ceci:

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;
    }
}

Pour le contenu de ca.pem, j'ai essayé d'utiliser le CA intermédiaire et aussi concaténation du CA cert intermédiaire et du CA cert racine, c'est-à-dire quelque chose comme:

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

j'ai également validé la validité du certificat du point de vue d'openssl en utilisant la même chaîne CA:

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

j'ai essayé de définir ssl_verify_depth explicitement à 1 (comme ci-dessus) et même à 0 (pas sûr de ce que ce nombre signifie exactement), mais j'obtiens toujours la même erreur.

l'erreur que j'obtiens dans toutes les variantes de L'AC intermed est " 400 Bad Request" et plus précisément "L'erreur de certificat SSL" (pas sûr de ce que cela signifie exactement).

peut-être que nginx ne supporte tout simplement pas les chaînes cert pour les Cert intermédiaires? Toute aide grandement appréciée!

29
demandé sur Hans L 0000-00-00 00:00:00

6 réponses

Edit: j'ai eu aussi ce "problème", la solution et l'explication se trouve au bas du texte.

il semble que nginx ne supporte pas les certificats intermédiaires. Mes certs auto-créés: (RootCA est auto-signé, IntrermediateCA1 est signé par RootCA,etc.)

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

je veux utiliser dans Nginx "IntermediateCA1", pour permettre l'accès au site seulement au propriétaire du certificat" Client1".

quand je mets dans le fichier" ssl_client_certificate" IntermediateCA1 et RootCA, et définir "ssl_verify_depth 2" (ou plus), les clients peuvent se connecter au site à la fois en utilisant le certificat Client1 et Client2 (ne devrait S'appliquer qu'au Client1). Le même résultat est quand je mets le fichier" ssl_client_certificate " avec seulement RootCA - les deux clients peuvent se connecter.

quand je mets dans le fichier" ssl_client_certificate " avec uniquement IntermediateCA1 et réglez la "ssl_verify_depth 1" (ou "2" ou n'importe) , il est imposible de vous connecter, j'obtiens l'erreur 400. Et en mode debug je vois logs:

verify:0, error:20, depth:1, subject:"/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=RootCA/emailAddress=cert@asdf.com"
verify:0, error:27, depth:1, subject:"/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=RootCA/emailAddress=cert@asdf.com"
verify:1, error:27, depth:0, subject:"/C=PL/CN=Client1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com"
(..)
client SSL certificate verify error: (27:certificate not trusted) while reading client request headers, (..)

je pense que c'est un bug. Testé sur Ubuntu, nginx 1.1.19 et 1.2.7-1~dotdeb.1, openssl 1.0.1. Je vois que nginx 1.3 a peu d'autres options sur l'utilisation des certificats clients, mais je ne vois pas de solution à ce problème.

actuellement, la seule façon de séparer les clients 1 et 2 est de créer deux RootCAs auto-signés, mais ce n'est qu'une solution..

Edit 1: J'ai signalé ce problème ici: http://trac.nginx.org/nginx/ticket/301

Edit 2" * Ok, ce n'est pas un bug, c'est une fonctionnalité ;)*

je reçois la réponse ici: http://trac.nginx.org/nginx/ticket/301 Il est de travail, vous devez vérifier que votre ssl_client_i_dn est (. Au lieu de l'émetteur vous pouvez utiliser aussi sujet du certificat, ou ce que vous voulez de http://wiki.nginx.org/HttpSslModule#Built-in_variables

c'est ainsi que fonctionne la vérification du certificat: le certificat doit être vérifié jusqu'à une racine de confiance. Si la chaîne ne peut pas être construite à un racine (pas d'intermédiaire) - la vérification échoue. Si vous faites confiance à root - all les certificats signés par elle, directement ou indirectement, sera vérifiée avec succès.

limiter la profondeur de vérification peut être utilisé si vous limiter les certificats clients aux certificats émis directement seulement, mais il est plus sur la prévention DoS, et évidemment, il ne peut pas être utilisé pour limiter le verificate aux intermédiaires 1 seulement (mais pas intermediate2).

Ce que vous voulez de certains, ici l'autorisation basé sur la couche sur le résultat de la vérification-c'est - à-dire que vous pouvez vouloir vérifier que le client l'émetteur du certificat est intermediate1. Solution la plus simple serait de demandes de rejet si le DN de l'émetteur ne correspond pas à celui autorisé, par exemple: quelque chose comme ce (non testé):

[ Edit par moi, il fonctionne correctement dans ma configuration ]

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/emailAddress=cert@asdf.com") {
        return 403;
    }
}
42
répondu Jack 2013-02-15 16:02:53

avez-vous essayé d'augmenter ssl_verify_depth la directive? Docs dis:

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

mais votre profondeur de vérification est de 1. Vous dites:

j'ai essayé de définir ssl_verify_depth explicitement à 1 (comme ci-dessus) et même à 0 (pas sûr de ce que ce nombre signifie exactement), mais j'obtiens toujours la même erreur.

alors, essayez 2 ou 3..

PS: Partout où je trouve ce problème mentionné, son dit de combiner Certificats de L'AC avec votre serveur cert. en un seul fichier (comme @vikas-nalwar suggère et vous avez fait) dans l'ordre de vérification (mais je ne suis pas sûr si l'ordre importe) et en gros Ensemble ssl_verify_depth au nombre de certs dans le faisceau.

11
répondu Andrew D. 2017-05-23 12:26:20

je crois que vous voulez activer le client validation côté serveur. Si c'est le cas, je ne vois pas que vous avez votre certificat client dans la chaîne. Essayez ce qui suit dans le même ordre. Utiliser le certchain.pem.

  cat client.crt > certchain.pem
  cat intermediate.crt >> certchain.pem
  cat root.crt >> certchain.pem
2
répondu Drona 2011-12-08 16:44:19

comme je me pavanais avec nginx et cloudflare,

ces lignes a fait le tour pour moi:

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

la deuxième ligne avec optional_no_ca est la partie importante

2
répondu Tal 2016-01-26 10:04:14

une autre façon facile est de concaténer les certificats (y compris les certificats de domaine) dans un seul fichier et de les utiliser sur vos serveurs et le fichier de conf nginx

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

n'oubliez pas D'utiliser d'abord les certificats du serveur et ensuite seulement les certificats du serveur de L'AC

vous pouvez en lire plus à propos dehttp://nginx.org/en/docs/http/configuring_https_servers.html#chains

0
répondu Naveen 2015-06-17 07:53:18

je dois dire que sa fonctionne très bien pour moi avec nginx/1.13.2, i.e.

  • j'ai un AC racine qui a signé deux AC intermédiaires
  • les deux intermédiaires ont signé chacun un client
  • Je concatte les certs comme cat client-intermediate1.crt ca-client.crt > ca.chained1.crt et cat client-intermediate2.crt ca-client.crt > ca.chained2.crt et cat ca.chained1.crt ca.chained2.crt > ca.multiple.intermediate.crt

  • si je mets seulement ca.chained1.crt ssl_client_certificate alors seulement client1.crt peut se connecter, de même pour ca.chained2.crt / client2.crt

  • quand j'utilise ca.multiple.intermediate.crt puis les deux clients peuvent se connecter

pour révoquer un intermédiaire, il suffit de retirer la chaîne cert du ca.plusieurs.intermédiaire.crt

voici la config. ses paramètres de haute sécurité sont également

# 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;

si vous voulez séparer les certs CN et les transmettre à backend, alors ajoutez ceci en dehors de la server {.. bloc

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

et à l'INTÉRIEUR du bloc, vous pouvez utiliser

# 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;
0
répondu pHiL 2017-07-18 13:56:23