Serwer proxy Nginx do zaplecza z uwierzytelnianiem certyfikatu klienta SSL

14

Mam dwa serwery, oba mają nginx. Serwer A nasłuchuje 443 i jest skonfigurowany do uwierzytelniania za pomocą certyfikatu SSL klienta.

Serwer B ma wewnętrzny proces, który musi komunikować się z serwerem A za pośrednictwem nginx.

Chciałbym skonfigurować Nginx na serwerze B, który będzie nasłuchiwał 8080 (bez szyfrowania, ponieważ jest to cała komunikacja lokalna) i proxy_pass do serwera A: 443.

Pytanie brzmi: jak wstrzyknąć certyfikat klienta? Nie znalazłem żadnej funkcji proxy_xxxx, która by to zrobiła.

Wiem, jak zrobić odpowiednik socat, ale moim wymaganiem jest użycie nginx.

Bastien974
źródło
2
Patrząc na dyrektywy w module proxy nginx, wydaje się, że nie jest możliwe, aby serwer nginx używał certyfikatu do uwierzytelnienia: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache obsługuje tę funkcję.
NuTTyX,
Właśnie się tego obawiałem ... jakiś pomysł, jeśli istnieje niestandardowy moduł lub coś, co może sprawić, że to zadziała? Tego rodzaju funkcja musi istnieć!
Bastien974,
Znalazłem narzędzie do migracji plików konfiguracyjnych z apache do nginx ( github.com/nhnc-nginx/apache2nginx ), więc pobrałem je, utworzyłem atrapę apache.conf i przekazałem je przez narzędzie, ale mam ten wynik :### 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

Odpowiedzi:

21

Czy wystarczy przekazać szczegóły certyfikatu klienta?

Możesz dodać

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

do konfiguracji, a następnie informacje o certyfikacie są dostępne dla serwera B za pośrednictwem nagłówka X-SSL-Cert.

jwilkins
źródło
1
Jak tu komentujesz , pamiętaj, że po przeczytaniu twój backend może zastąpić \tz \ntego nagłówka.
lucasvc
3
Według dokumentacji nginx w The $ssl_client_certzmienna jest przestarzała; $ssl_client_escaped_certzmienny powinien być stosowany zamiast.
dubek
1
@dubek dobry haczyk, zaktualizowałbym odpowiedź bezpośrednio w takich przypadkach.
Chris Stryczyński
Próbowałem tego rozwiązania, ale wydaje się, że przekazuje certyfikat tylko wtedy, gdy sprawdzanie poprawności certyfikatu jest włączone. Nie chcę go włączać, czy istnieje sposób, aby działał bez włączania sprawdzania poprawności?
juhako
5

Najwyraźniej tego właśnie szukasz: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Dostępne od wersji 1.7.8.

location / {
    ...
    proxy_pass     the_other_nginx;
    proxy_ssl_certificate  the_certificate.pem;
    ...
}
Nicolas Malbran
źródło
1
To jest źle. To przypisuje certyfikat klienta do serwera proxy, który ma być używany dla żądań do zaplecza. Ale zapytany powiedział, że ta komunikacja jest nieszyfrowana tylko lokalnie, więc nie ma sprawdzania certyfikatu klienta. Odpowiedź Jwilkinsa działa dobrze.
Kenyakorn Ketsombut,
@KenyakornKetsombut Uważam, że źle odczytałeś pytanie. Serwer B nie ma szyfrowania (nasłuchuje na 8080), ale musi komunikować się z serwerem A (nasłuchuje na 443, z szyfrowaniem). Więc B musi wysłać certyfikat klienta do A, aby się uwierzytelnić. Aby to zrobić, możesz użyć proxy_ssl_certificate. Odpowiedź jwilkins, prześle do A certyfikat nadany B. Oba mogą działać w zależności od potrzeb.
Nicolas Malbran,
Cześć Nicolas. Próbowałem powiedzieć: jeśli serwer B nie używa szyfrowania (na porcie 8080), nie używa niczego takiego jak HTTPS / SSL lub jak go nazywacie. Certyfikaty klienta są częścią protokołu SSL, więc ta część nie może być wykonana przez serwer B. B nie może wysłać ani odebrać żadnego certyfikatu klienta.
Kenyakorn Ketsombut
1
Dostaję nginx: [emerg] nie zdefiniowano „klucza_ proxy_ssl_certificate” dla certyfikatu „certs / Roro_Client.pem” test nginx: plik konfiguracyjny /etc/nginx/nginx.conf nie powiódł się, gdy spróbuję tego z 1.8.0
Wolfgang Fahl
4

Wydaje się, że problem zależy w dużej mierze od wersji. W Ubuntu 14.04 LTS domyślnym nginx jest przestarzały 1.4. Najpierw musisz zainstalować wersję opartą na PPA

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

pokazuje, jak to zrobić za pomocą:

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

powinieneś skończyć z:

nginx -v
nginx version: nginx/1.8.0

Konfiguracja z @ xatr0z odpowiedź https://serverfault.com/a/636455/162693 wskazująca na http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate nie działa:

niedziałająca propozycja

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

nie działa od razu z wersją 1.8.0. Prawdopodobnie jest to tylko wskazówka i nie może być używany jako plik konfiguracyjny jako taki lub zależy od innej wersji.

Testuję z serwerem zaplecza A opartym na Apache2 z włączonym SSL i samopodpisanymi certyfikatami klienta. Konfiguracje SSLOptions konfiguracji Apache są ustawione na:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Ułatwia to debugowanie sytuacji, ponieważ skrypt phpinfo () po stronie zaplecza wyświetla informacje po stronie serwera i klienta.

Aby to sprawdzić, użyłem:

https: // backend / test / phpinfo

z certyfikatem SSL zainstalowanym w przeglądarce i otrzymuję sekcje: SSL_SERVER_S_DN_CN dla certyfikatu serwera i SSL_CLIENT_S_DN_CN dla certyfikatu klienta.

Jako pierwszy start użyłem (wypełnij części w nawiasach) do skonfigurowania nginx na serwerze frontonu 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;
  }
}

odkomentowanie określonej części certyfikatu klienta SSL tylko po to, aby sprawdzić, czy działa samo odwrotne proxy.

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

Teraz http: // frontend: 8080 / test / phpinfo.php działa

SSL_SERVER_S_DN_CN dla certyfikatu serwera jest wyświetlany, a SSL_CLIENT_S_DN_CN dla certyfikatu klienta nie jest (jeszcze) wyświetlany

Teraz po odkomentowaniu:

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

i sprawdzanie / restartowanie

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 działa i

SSL_SERVER_S_DN_CN dla certyfikatu serwera jest wyświetlana i SSL_CLIENT_S_DN_CN dla certyfikatu klienta jest wyświetlana

więc teraz mamy rzeczy działające zgodnie z wymaganiami.

Zwróć uwagę na błąd https://trac.nginx.org/nginx/ticket/872#ticket

Wolfgang Fahl
źródło
Możesz uważać na problem renegocjacji ruby-forum.com/topic/6875137, który może zepsuć program
Wolfgang Fahl
1

Jest całkiem fajny artykuł na temat certyfikatów klienta nginx i SSL; używa PHP z FastCGI jako przykładem, ale myślę, że możesz dostosować to do konfiguracji odwrotnego proxy:

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

Źródło http://nategood.com/client-side-certificate-authentication-in-ngi

Erik Kaplun
źródło