SSL 클라이언트 인증서 인증으로 백엔드 할 Nginx 프록시


14

두 개의 서버가 있으며 둘 다 nginx가 있습니다. 서버 A가 443을 청취 중이며 클라이언트 SSL 인증서로 인증하도록 구성되었습니다.

서버 B에는 nginx를 통해 서버 A와 통신해야하는 내부 프로세스가 있습니다.

서버 B에서 Nginx를 구성하여 8080 (모든 로컬 통신이므로 암호화 없음)과 server_ : 443에 대한 proxy_pass를 수신합니다.

문제는 어떻게 클라이언트 인증서를 주입합니까? 그렇게 할 proxy_xxxx 함수를 찾지 못했습니다.

socat을 사용하여 이에 상응하는 방법을 알고 있지만 nginx를 사용해야합니다.


2
nginx의 프록시 모듈에서 지시문을 보면 인증을 위해 인증서를 사용하도록 nginx 서버를 만들 수없는 것 같습니다. nginx.org/en/docs/http/ngx_http_proxy_module.html Apache는 해당 기능을 지원합니다.
NuTTyX

그것이 내가 두려워했던 것입니다 ... 맞춤형 모듈이 나이 작업을 수행 할 수있는 것이 있다면 어떤 아이디어입니까? 그런 종류의 기능이 존재해야합니다!
Bastien974

구성 파일을 아파치에서 nginx ( github.com/nhnc-nginx/apache2nginx ) 로 마이그레이션하는 유틸리티를 찾았 으므로 다운로드하여 더미 apache.conf를 작성하고 도구를 통해 전달했지만이 결과를 얻었습니다. :### 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

답변:


21

클라이언트 인증서 정보를 전달하는 것으로 충분합니까?

추가 할 수 있습니다

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

인증서 정보는 X-SSL-Cert 헤더를 통해 서버 B에서 사용할 수 있습니다.


1
comented으로 여기 백엔드 대체 할 수있는 경우,주의 \t\n읽혀질하면이 헤더에서.
lucasvc

3
에 따르면 의 nginx의 문서$ssl_client_cert변수가되지 않습니다; $ssl_client_escaped_cert변수가 대신 사용되어야한다.
dubek

1
@ dubek 좋은 캐치, 나는 이런 경우에 직접 답변을 업데이트 할 것입니다.
Chris Stryczynski

이 솔루션을 시도했지만 인증서 유효성 검사가 ON으로 설정된 경우에만 인증서를 통과하는 것으로 보입니다. 유효성 검사를 설정하지 않고 작동시키는 방법이 있습니까?
juhako

5

분명히 이것은 당신이 찾고있는 것입니다 : http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate 버전 1.7.8부터 사용 가능합니다.

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

1
이것은 잘못이다. 백엔드 요청에 사용할 클라이언트 인증서를 프록시에 할당합니다. 그러나이 통신은이 통신이 로컬에서만 암호화되지 않으므로 클라이언트 인증서 검사가 없다고 말했다. jwilkins의 답변이 잘 작동합니다.
Kenyakorn Ketsombut

@KenyakornKetsombut 나는 당신이 질문을 잘못 읽었다 고 생각합니다. 서버 B에는 암호화가 없지만 (8080에서 수신) 서버 A와 통신해야합니다 (암호로 443에서 수신). 따라서 B는 인증을 위해 클라이언트 인증서를 A로 보내야합니다. proxy_ssl_certificate를 사용하여이를 수행 할 수 있습니다. jwilkins가 대답하고 A에게 B에게 주어진 인증서를 전달합니다. 둘 다 필요한 것에 따라 작동 할 수 있습니다.
Nicolas Malbran

안녕 니콜라스. 서버 B가 포트 8080에서 암호화를 사용하지 않으면 HTTPS / SSL과 같은 것을 사용하지 않거나 호출합니다. 클라이언트 인증서는 SSL의 일부이므로 서버 B에서이 부분을 수행 할 수 없습니다. B는 클라이언트 인증서를 보내거나받을 수 없습니다.
Kenyakorn Ketsombut

1
nginx : [emerg] "certs / Roro_Client.pem"인증서에 대해 "proxy_ssl_certificate_key"가 정의되어 있지 않습니다. nginx : 1.8.0으로 이것을 시도 할 때 구성 파일 /etc/nginx/nginx.conf 테스트에 실패했습니다
Wolfgang Fahl

4

문제는 버전 의존적 인 것 같습니다. 우분투 14.04 LTS에서 기본 nginx는 오래된 1.4입니다. 먼저 PPA 기반 버전을 설치해야합니다.

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

이 작업을 수행하는 방법을 보여줍니다.

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

당신은 결국

nginx -v
nginx version: nginx/1.8.0

@ xatr0z의 구성은 https://serverfault.com/a/636455/162693 에서 http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate 가 작동하지 않습니다.

작동하지 않는 제안

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

1.8.0에서는 기본적으로 작동하지 않습니다. 아마도 힌트로만 사용되며 구성 파일로 사용되거나 다른 버전에 의존하지 않습니다.

SSL 및 자체 서명 클라이언트 인증서가 활성화 된 apache2 기반 백엔드 서버 A로 테스트하고 있습니다. Apache config SSLOptions는 다음과 같이 설정됩니다.

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

백엔드 측의 phpinfo () 스크립트가 서버 및 클라이언트 측 정보를 표시하므로 상황을 쉽게 디버깅 할 수 있습니다.

이것을 확인하기 위해 내가 사용한 :

https : // backend / test / phpinfo

브라우저에 SSL 인증서가 설치되어 있고 서버 인증서의 경우 SSL_SERVER_S_DN_CN 및 클라이언트 인증서의 경우 SSL_CLIENT_S_DN_CN과 같은 섹션이 있습니다.

첫 번째 시작으로 프론트 엔드 서버 B에서 nginx를 구성하기 위해 괄호 안에 부품을 채우십시오.

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

리버스 프록시 자체가 작동하는지 확인하기 위해 SSL 클라이언트 인증서 특정 부분의 주석을 해제하십시오.

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 작동

서버 인증서의 SSL_SERVER_S_DN_CN이 표시되고 클라이언트 인증서의 SSL_CLIENT_S_DN_CN 이 (아직) 표시되지 않습니다

주석 해제 후 :

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

확인 / 다시 시작

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 작동 및

서버 인증서의 SSL_SERVER_S_DN_CN이 표시되고 클라이언트 인증서의 SSL_CLIENT_S_DN_CN 이 표시됩니다.

이제 요청한대로 작동합니다.

버그 https://trac.nginx.org/nginx/ticket/872#ticket


쇼를 망칠 수도 있는 재협상 문제 ruby-forum.com/topic/6875137에주의 하십시오
Wolfgang Fahl

1

nginx 및 SSL 클라이언트 인증서에 대한 깔끔한 기사가 있습니다. PHP는 FastCGI와 함께 PHP를 사용하지만 리버스 프록시 설정에 적용 할 수 있다고 생각합니다.

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

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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.