Proxy Nginx pour back-end avec authentification par certificat client SSL


14

J'ai deux serveurs, les deux ont nginx. Le serveur A écoute 443 et est configuré pour s'authentifier avec un certificat SSL client.

Le serveur B a un processus interne qui doit communiquer avec le serveur A via nginx.

Je voudrais configurer Nginx sur le serveur B qui écoutera 8080 (pas de cryptage, car il s'agit uniquement de communications locales) et proxy_pass vers ServerA: 443.

La question est de savoir comment injecter un certificat client? Je n'ai trouvé aucune fonction proxy_xxxx qui ferait cela.

Je sais comment faire un équivalent à celui avec socat, mais mon exigence est d'utiliser nginx.


2
En regardant les directives du module proxy de nginx, il semble qu'il ne soit pas possible de faire en sorte qu'un serveur nginx utilise un certificat pour s'authentifier: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache prend cependant en charge cette fonctionnalité.
NuTTyX

C'est ce dont j'avais peur ... une idée s'il y a un module personnalisé ou quelque chose qui peut faire fonctionner cela? Ce genre de fonctionnalité doit exister!
Bastien974

J'ai trouvé un utilitaire pour migrer les fichiers de configuration d'apache vers nginx ( github.com/nhnc-nginx/apache2nginx ), alors je l'ai téléchargé, créé un apache.conf factice et le faire passer par l'outil, mais j'ai ce résultat :### Section 2: Unconverted directives ### # Flag Description # [S] Unsupported directives. # In conf file: dummy.conf # Line 32: SSLProxyMachineCertificateFile /path/to/cert (mod_ssl.c) # [S] SSLProxyMachineCertificateFile: No relevant directive in Nginx.
NuTTyX

Réponses:


21

Suffit-il de faire passer les détails du certificat client?

Vous pouvez ajouter

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

à votre configuration, puis les informations de certificat sont disponibles sur le serveur B via un en-tête X-SSL-Cert.


1
Comme indiqué ici , sachez si votre backend peut être remplacé \tpar à \npartir de cet en-tête une fois lu.
lucasvc

3
Selon la documentation de nginx , la $ssl_client_certvariable est déconseillée; la $ssl_client_escaped_certvariable doit être utilisée à la place.
dubek

1
@dubek good catch, je mettrais à jour la réponse directement dans des cas comme celui-ci.
Chris Stryczynski

J'ai essayé cette solution, mais elle ne semble transmettre le certificat que si la validation du certificat est activée. Je ne veux pas l'activer, existe-t-il un moyen de le faire fonctionner sans activer la validation?
juhako

5

Apparemment, c'est ce que vous recherchez: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Disponible depuis la version 1.7.8.

location / {
    ...
    proxy_pass     the_other_nginx;
    proxy_ssl_certificate  the_certificate.pem;
    ...
}

1
C'est faux. Cela affecte un certificat client au proxy à utiliser pour les demandes au backend. Mais le demandé, a déclaré que cette communication n'est pas cryptée uniquement locale, donc il n'y a pas de vérification de certificat client. La réponse de jwilkins fonctionne bien.
Kenyakorn Ketsombut

@KenyakornKetsombut Je pense que vous avez mal lu la question. Le serveur B n'a pas de cryptage (écoute sur 8080) mais doit communiquer avec le serveur A (écoute sur 443, avec cryptage). B doit donc envoyer le certificat client à A pour s'authentifier. Vous pouvez utiliser proxy_ssl_certificate pour accomplir cela. réponse jwilkins, transmettra à A le certificat donné à B. Les deux peuvent fonctionner en fonction de vos besoins.
Nicolas Malbran

Salut Nicolas. J'essayais de dire: si le serveur B n'utilise pas de cryptage (sur le port 8080), il n'utilise rien de tel que HTTPS / SSL ou comme vous l'appelez. Les certificats clients font partie de SSL, cette partie ne peut donc pas être effectuée par le serveur B. B ne peut envoyer ou recevoir aucun certificat client.
Kenyakorn Ketsombut

1
J'obtiens nginx: [Emerg] aucun "proxy_ssl_certificate_key" n'est défini pour le certificat "certs / Roro_Client.pem" nginx: le fichier de configuration /etc/nginx/nginx.conf a échoué lorsque j'essaye avec 1.8.0
Wolfgang Fahl

4

Le problème semble dépendre largement de la version. Sur Ubuntu 14.04 LTS, le nginx par défaut est un 1.4 obsolète. Vous devez d'abord installer une version basée sur PPA

https://leftshift.io/upgrading-nginx-to-the-latest-version-on-ubuntu-servers

montre comment procéder avec:

sudo add-apt-repository ppa:nginx/stable
sudo aptitude safe-upgrade

vous devriez vous retrouver avec:

nginx -v
nginx version: nginx/1.8.0

La configuration de @ xatr0z répond à https://serverfault.com/a/636455/162693 pointant vers http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate ne fonctionne pas:

proposition non fonctionnelle

backend {
    server some-ip:443;
}

server {
    listen 80;


    location / {
        proxy_ssl_certificate        certs/client.crt;
        proxy_ssl_certificate_key    certs/client.key;


        proxy_pass https://backend;
    }
}

ne fonctionne pas avec la version 1.8.0. Il est probablement conçu uniquement à titre indicatif et ne doit pas être utilisé comme fichier de configuration en tant que tel ou dépend d'une autre version.

Je teste avec un serveur backend A basé sur apache2 avec SSL et certificats clients auto-signés activés. Les SSLOptions de configuration Apache sont définies sur:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Cela facilite le débogage de la situation car un script phpinfo () du côté backend affichera les informations côté serveur et côté client.

Pour vérifier cela, j'ai utilisé:

https: // backend / test / phpinfo

avec le certificat SSL installé dans le navigateur et j'obtiens des sections comme: SSL_SERVER_S_DN_CN pour le certificat serveur et SSL_CLIENT_S_DN_CN pour le certificat client.

Comme premier démarrage, j'ai utilisé (remplissez les parties entre parenthèses) pour configurer nginx sur le serveur frontal B:

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    #proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    #proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

décourager la partie spécifique du certificat client SSL juste pour vérifier que le proxy inverse lui-même fonctionne.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

Maintenant, http: // frontend: 8080 / test / phpinfo.php fonctionne

SSL_SERVER_S_DN_CN pour le certificat serveur est affiché et SSL_CLIENT_S_DN_CN pour le certificat client n'est pas (encore) affiché

Maintenant, sans commenter:

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

et vérification / redémarrage

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

http: // frontend: 8080 / test / phpinfo.php fonctionne et

SSL_SERVER_S_DN_CN pour le certificat de serveur s'affiche et SSL_CLIENT_S_DN_CN pour le certificat client s'affiche

alors maintenant nous avons fait fonctionner les choses comme demandé.

Veuillez noter le bug https://trac.nginx.org/nginx/ticket/872#ticket


Vous voudrez peut-être faire attention au problème de renégociation ruby-forum.com/topic/6875137 qui pourrait gâcher le spectacle
Wolfgang Fahl

1

Il y a un article assez soigné sur les certificats clients nginx et SSL; il utilise PHP avec FastCGI comme exemple mais je pense que vous pouvez l'adapter à une configuration de proxy inverse:

server {
    listen        443;
    ssl on;
    server_name example.com;

    ssl_certificate      /etc/nginx/certs/server.crt;
    ssl_certificate_key  /etc/nginx/certs/server.key;
    ssl_client_certificate /etc/nginx/certs/ca.crt;
    ssl_verify_client optional;

    location / {
        root           /var/www/example.com/html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME /var/www/example.com/lib/Request.class.php;
        fastcgi_param  VERIFIED $ssl_client_verify;
        fastcgi_param  DN $ssl_client_s_dn;
        include        fastcgi_params;
    }
}

Source http://nategood.com/client-side-certificate-authentication-in-ngi


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.