Proxy Nginx al back-end con autenticazione del certificato client SSL


14

Ho due server, entrambi hanno nginx. Il server A sta ascoltando 443 ed è configurato per l'autenticazione con un certificato SSL client.

Il server B ha un processo interno che deve comunicare con il server A tramite nginx.

Vorrei configurare Nginx sul server B che ascolterà 8080 (nessuna crittografia, poiché è tutta comunicazione locale) e proxy_pass su ServerA: 443.

La domanda è: come posso iniettare un certificato client? Non ho trovato alcuna funzione proxy_xxxx che lo farebbe.

So come equivalere a quello con socat, ma il mio requisito è usare nginx.


2
Osservando le direttive nel modulo proxy di nginx, sembra che non sia possibile creare un server nginx per utilizzare un certificato per l'autenticazione: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache, tuttavia, supporta tale funzionalità.
NuTTyX

Questo è ciò di cui avevo paura ... qualche idea se c'è un modulo personalizzato o qualcosa che possa farlo funzionare? Questo tipo di funzionalità deve esistere!
Bastien974,

Ho trovato un'utilità per migrare i file di configurazione da apache a nginx ( github.com/nhnc-nginx/apache2nginx ), quindi l'ho scaricato, ho creato un apache.conf fittizio e lo ho passato attraverso lo strumento, ma ho questo risultato :### 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,

Risposte:


21

È sufficiente far passare i dettagli del certificato client?

Puoi aggiungere

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

nella tua configurazione e quindi le informazioni sul certificato sono disponibili per il server B tramite un'intestazione X-SSL-Cert.


1
Come indicato qui , sii consapevole se il tuo back-end può essere sostituito \tcon \nda questa intestazione una volta letto.
lucasvc,

3
Secondo la documentazione di nginx , la $ssl_client_certvariabile è obsoleta; la $ssl_client_escaped_certvariabile dovrebbe essere usata invece.
Dubek,

1
@dubek buona cattura, vorrei aggiornare la risposta direttamente in casi come questo.
Chris Stryczynski,

Ho provato questa soluzione, ma sembra passare il certificato solo se la convalida del certificato è impostata su ON. Non voglio accenderlo, c'è un modo per farlo funzionare senza impostare la convalida?
juhako,

5

Apparentemente, questo è quello che stai cercando: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Disponibile dalla versione 1.7.8.

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

1
Questo è sbagliato. Ciò assegna un certificato client al proxy da utilizzare per le richieste al back-end. Ma la domanda, ha detto che questa comunicazione non è crittografata solo a livello locale, quindi non esiste un controllo del certificato client. La risposta di Jwilkins funziona bene.
Kenyakorn Ketsombut,

@KenyakornKetsombut Credo che tu abbia letto male la domanda. Il server B non ha crittografia (ascolto su 8080) ma deve comunicare con il server A (ascolto su 443, con crittografia). Quindi B deve inviare il certificato client ad A per l'autenticazione. È possibile utilizzare proxy_ssl_certificate per farlo. jwilkins risponde, inoltrerà ad A il certificato dato a B. Entrambi possono funzionare a seconda delle necessità.
Nicolas Malbran,

Ciao Nicolas Stavo cercando di dire: se il Server B non utilizza la crittografia (sulla porta 8080) non utilizza nulla come HTTPS / SSL o comunque lo chiami. I certificati client fanno parte di SSL, quindi questa parte non può essere eseguita dal Server B. B non può inviare o ricevere alcun certificato client.
Kenyakorn Ketsombut,

1
Ottengo nginx: [emerg] nessun "proxy_ssl_certificate_key" è definito per il certificato "certs / Roro_Client.pem" nginx: test del file di configurazione /etc/nginx/nginx.conf fallito quando provo questo con 1.8.0
Wolfgang Fahl

4

Il problema sembra dipendere in gran parte dalla versione. Su Ubuntu 14.04 LTS il nginx predefinito è un 1.4 obsoleto. Innanzitutto è necessario installare una versione basata su PPA

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

mostra come farlo con:

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

dovresti finire con:

nginx -v
nginx version: nginx/1.8.0

La configurazione da @ xatr0z risponde https://serverfault.com/a/636455/162693 che punta a http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate non funziona:

proposta non operativa

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

non funziona con la versione 1.8.0. Probabilmente è inteso solo come suggerimento e non può essere utilizzato come file di configurazione in quanto tale o dipende da un'altra versione.

Sto testando con un server back-end A basato su apache2 con SSL e certificati client autofirmati abilitati. Le impostazioni SSLO di configurazione di Apache sono impostate su:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Ciò semplifica il debug della situazione poiché uno script phpinfo () sul lato backend mostrerà le informazioni sul lato server e client.

Per verificarlo ho usato:

https: // backend / test / phpinfo

con il certificato SSL installato nel browser e ottengo sezioni come: SSL_SERVER_S_DN_CN per il certificato del server e SSL_CLIENT_S_DN_CN per il certificato client.

Come primo avvio ho usato (compilare le parti tra parentesi) per configurare nginx sul server frontend 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;
  }
}

decomprimere la parte specifica del certificato client SSL solo per verificare che il proxy inverso stesso funzioni.

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

Ora http: // frontend: 8080 / test / phpinfo.php funziona

SSL_SERVER_S_DN_CN per il certificato del server viene visualizzato e SSL_CLIENT_S_DN_CN per il certificato client non viene (ancora) visualizzato

Ora dopo il commento:

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

e controllo / riavvio

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 funziona e

SSL_SERVER_S_DN_CN per il certificato del server viene visualizzato e SSL_CLIENT_S_DN_CN per il certificato del client viene visualizzato

così ora abbiamo fatto funzionare le cose come richiesto.

Si prega di notare bug https://trac.nginx.org/nginx/ticket/872#ticket


Potresti voler fare attenzione al problema di rinegoziazione ruby-forum.com/topic/6875137 che potrebbe rovinare lo spettacolo
Wolfgang Fahl,

1

C'è un articolo abbastanza accurato sui certificati client nginx e SSL; usa PHP con FastCGI come esempio ma penso che tu possa adattarlo a una configurazione proxy inversa:

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

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


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.