web-dev-qa-db-fra.com

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

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.

13
Bastien974

Est-il suffisant 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.

20
jwilkins

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;
    ...
}
5
Nicolas Malbran

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 answer https://serverfault.com/a/636455/16269 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 dorsal 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 puisqu'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;
  }
}

uncomenting 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 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

4
Wolfgang Fahl

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

1
Erik Kaplun

Il semble que ce module SEnginx soit ce que vous recherchez: http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate

0
xatr0z