Proxy Nginx para back-end com autenticação de certificado de cliente SSL


14

Eu tenho dois servidores, ambos têm nginx. O servidor A está escutando 443 e está configurado para se autenticar com um certificado SSL do cliente.

O servidor B possui um processo interno que precisa se comunicar com o servidor A através do nginx.

Gostaria de configurar o Nginx no servidor B que ouvirá 8080 (sem criptografia, pois é toda a comunicação local) e proxy_pass para o ServerA: 443.

A questão é como injetar um certificado de cliente? Não encontrei nenhuma função proxy_xxxx que fizesse isso.

Eu sei como fazer um equivalente a isso com o socat, mas meu requisito é usar o nginx.


2
Observando as diretivas no módulo proxy do nginx, parece que não é possível fazer um servidor nginx usar um certificado para autenticar: nginx.org/en/docs/http/ngx_http_proxy_module.html O Apache suporta esse recurso.
— NuTTyX

Era disso que eu tinha medo ... alguma idéia se existe um módulo personalizado ou algo que possa fazer isso funcionar? Esse tipo de recurso precisa existir!
— precisa saber é o seguinte

Encontrei um utilitário para migrar arquivos de configuração do apache para o nginx ( github.com/nhnc-nginx/apache2nginx ), então baixei-o, criei um apache.conf fictício e passe-o pela ferramenta, mas obtive esse resultado :### 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

Respostas:


21

É suficiente passar os detalhes do certificado do cliente?

Você pode adicionar

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

à sua configuração e as informações do certificado estão disponíveis para o servidor B por meio de um cabeçalho X-SSL-Cert.


1
Como comentado aqui , estar ciente se o seu back-end pode substituir \tcom \na partir deste cabeçalho uma vez readed.
— lucasvc

3
De acordo com a documentação do nginx , a $ssl_client_certvariável está obsoleta; a $ssl_client_escaped_certvariável deve ser usada em seu lugar.
— Dubek

1
@dubek boa captura, eu atualizaria a resposta diretamente em casos como este.
— Chris Stryczynski

Eu tenho tentado esta solução, mas apenas parece estar passando o certificado se a validação do certificado estiver ativada. Não quero ativá-lo. Existe uma maneira de fazê-lo funcionar sem ativar a validação?
— juhako

5

Aparentemente, é isso que você está procurando: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Disponível desde a versão 1.7.8.

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

1
Isto está errado. Isso atribui um certificado de cliente ao proxy a ser usado para as solicitações ao back-end. Mas o perguntou, disse que esta comunicação não é criptografada apenas como local, portanto não há verificação de certificado de cliente. A resposta de jwilkins funciona bem.
— Kenyakorn Ketsombut 10/09

@KenyakornKetsombut Eu acredito que você interpretou mal a pergunta. O servidor B não possui criptografia (escutando 8080), mas precisa se comunicar com o servidor A (escutando 443, com criptografia). Então, B precisa enviar o certificado do cliente para A para se autenticar. Você pode usar proxy_ssl_certificate para fazer isso. jwilkins responder, encaminhará para A o certificado dado a B. Ambos podem funcionar dependendo do que você precisa.
— Nicolas Malbran

Oi Nicolas. Eu estava tentando dizer: se o Servidor B não estiver usando criptografia (na porta 8080), ele não usará nada como HTTPS / SSL ou como você chamar. Os certificados de cliente fazem parte do SSL, portanto, essa parte não pode ser feita pelo Servidor B. B não pode enviar ou receber nenhum certificado de cliente.
— Kenyakorn Ketsombut

1
Eu recebo o nginx: [emerg] nenhum "proxy_ssl_certificate_key" está definido para o certificado "certs / Roro_Client.pem" nginx: o arquivo de configuração /etc/nginx/nginx.conf falhou ao tentar isso com 1.8.0
— Wolfgang Fahl

4

A questão parece ser amplamente dependente da versão. No Ubuntu 14.04 LTS, o nginx padrão é um 1.4 desatualizado. Primeiro você precisa instalar uma versão baseada em PPA

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

mostra como fazer isso com:

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

você deve terminar com:

nginx -v
nginx version: nginx/1.8.0

A configuração da resposta @ xatr0z https://serverfault.com/a/636455/162693 apontando para http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate não funciona:

proposta não útil

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

não funciona imediatamente com 1.8.0. Provavelmente é apenas uma sugestão e não deve ser usado como um arquivo de configuração como tal ou depende de outra versão.

Estou testando com um servidor back-end A baseado em apache2 com SSL e certificados de cliente autoassinado ativados. As SSLOptions de configuração do Apache estão definidas para:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Isso facilita a depuração da situação, pois um script phpinfo () no lado de back-end mostra as informações do lado do servidor e do cliente.

Para verificar isso, usei:

https: // back-end / test / phpinfo

com o certificado SSL instalado no navegador e recebo seções como: SSL_SERVER_S_DN_CN para o certificado do servidor e SSL_CLIENT_S_DN_CN para o certificado do cliente.

Como primeira inicialização, usei (preencha as partes entre colchetes) para configurar o nginx no servidor front-end 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;
  }
}

desassociando a parte específica do Certificado de Cliente SSL apenas para verificar se o próprio proxy reverso funciona.

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

Agora, o http: // frontend: 8080 / test / phpinfo.php funciona

SSL_SERVER_S_DN_CN para o certificado do servidor é exibido e SSL_CLIENT_S_DN_CN para o certificado do cliente (ainda) não é exibido

Agora, depois de descomentar:

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 verificando / reiniciando

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

SSL_SERVER_S_DN_CN para o certificado do servidor é exibido e SSL_CLIENT_S_DN_CN para o certificado do cliente é exibido

então agora temos as coisas funcionando conforme solicitado.

Observe o bug https://trac.nginx.org/nginx/ticket/872#ticket


Você pode querer atente para a questão renegociação ruby-forum.com/topic/6875137 que poderia estragar o show
— Wolfgang Fahl

1

Há um artigo bastante interessante sobre os certificados de cliente nginx e SSL; ele usa PHP com FastCGI como exemplo, mas acho que você pode adaptar isso a uma configuração de proxy reverso:

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


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.