Nginx proxy to back-end dengan otentikasi sertifikat klien SSL

14

Saya memiliki dua server, keduanya memiliki nginx. Server A sedang mendengarkan 443 dan dikonfigurasi untuk otentikasi dengan sertifikat SSL Klien.

Server B memiliki proses internal yang perlu berkomunikasi ke Server A hingga nginx.

Saya ingin mengonfigurasi Nginx di server B yang akan mendengarkan 8080 (tanpa enkripsi, karena ini semua komunikasi lokal) dan proxy_pass ke ServerA: 443.

Pertanyaannya adalah bagaimana cara saya menyuntikkan Sertifikat Klien? Saya tidak menemukan fungsi proxy_xxxx yang akan melakukan itu.

Saya tahu cara membuat yang setara dengan socat, tetapi persyaratan saya adalah menggunakan nginx.

Bastien974
sumber
2
Melihat arahan dalam modul proksi nginx, tampaknya tidak mungkin membuat server nginx untuk menggunakan sertifikat untuk mengotentikasi: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache memang mendukung fitur itu.
NuTTyX
Itu yang saya takutkan ... ada ide apakah ada modul khusus atau sesuatu yang bisa membuat ini bekerja? Fitur semacam itu harus ada!
Bastien974
Saya telah menemukan utilitas untuk memigrasikan file konfigurasi dari apache ke nginx ( github.com/nhnc-nginx/apache2nginx ), jadi saya mengunduhnya, membuat apache.conf dummy dan meneruskannya melalui alat, tetapi saya mendapatkan hasil ini :### 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

Jawaban:

21

Apakah cukup agar perincian sertifikat klien dilewati?

Anda dapat menambahkan

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

ke konfigurasi Anda dan kemudian info sertifikat tersedia untuk server B melalui header X-SSL-Cert.

jwilkins
sumber
1
Seperti yang dibuat di sini , berhati-hatilah jika backend Anda dapat menggantikan \tdengan \ndari header ini setelah dibaca.
lucasvc
3
Menurut dokumentasi nginx , $ssl_client_certvariabelnya sudah usang; yang $ssl_client_escaped_certvariabel harus digunakan sebagai gantinya.
dubek
1
@dubek tangkapan bagus, saya akan memperbarui jawabannya langsung dalam kasus seperti ini.
Chris Stryczynski
Saya sudah mencoba solusi ini, tetapi sepertinya hanya akan lulus dari sertifikasi jika validasi sertifikat diatur ON. Saya tidak ingin menyalakannya, apakah ada cara untuk membuatnya berfungsi tanpa menetapkan validasi?
juhako
5

Tampaknya, inilah yang Anda cari: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate Tersedia sejak versi 1.7.8.

location / {
    ...
    proxy_pass     the_other_nginx;
    proxy_ssl_certificate  the_certificate.pem;
    ...
}
Nicolas Malbran
sumber
1
Ini salah. Ini memberikan sertifikat klien ke proxy yang akan digunakan untuk permintaan ke backend. Namun yang ditanya, mengatakan bahwa komunikasi ini tidak terenkripsi hanya lokal, sehingga tidak ada pengecekan sertifikat klien. Jawaban jwilkins bekerja dengan baik.
Kenyakorn Ketsombut
@ KenyakornKetsombut Saya yakin Anda salah membaca pertanyaan. Server B tidak memiliki enkripsi (mendengarkan pada 8080) tetapi harus berkomunikasi dengan server A (mendengarkan pada 443, dengan enkripsi). Jadi B perlu mengirim sertifikat klien ke A untuk mengautentikasi. Anda dapat menggunakan proxy_ssl_certificate untuk mencapai itu. jwilkins menjawab, akan meneruskan ke A sertifikat yang diberikan kepada B. Keduanya dapat bekerja tergantung pada apa yang Anda butuhkan.
Nicolas Malbran
Hai Nicolas. Saya mencoba untuk mengatakan: jika Server B tidak menggunakan enkripsi (pada port 8080) tidak menggunakan hal seperti HTTPS / SSL atau bagaimana pun Anda menyebutnya. Sertifikat klien adalah bagian dari SSL, jadi bagian ini tidak dapat dilakukan oleh Server B. B tidak dapat mengirim atau menerima sertifikat klien.
Kenyakorn Ketsombut
1
Saya mendapatkan nginx: [emerg] tidak ada "proxy_ssl_certificate_key" didefinisikan untuk sertifikat "certs / Roro_Client.pem" nginx: file konfigurasi /etc/nginx/nginx.conf gagal ketika saya mencoba ini dengan 1.8.0
Wolfgang Fahl
4

Masalah ini tampaknya sebagian besar bergantung pada versi. Di Ubuntu 14.04 LTS, nginx default adalah yang sudah usang 1.4. Pertama, Anda perlu menginstal versi berbasis PPA

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

menunjukkan cara melakukan ini dengan:

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

Anda harus berakhir dengan:

nginx -v
nginx version: nginx/1.8.0

Konfigurasi dari @ xatr0z jawab https://serverfault.com/a/636455/162693 mengarah ke http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificate tidak berfungsi:

proposal tidak bekerja

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

tidak bekerja di luar kotak dengan 1.8.0. Itu mungkin dimaksudkan sebagai petunjuk saja dan tidak untuk digunakan sebagai file konfigurasi atau tergantung pada versi lain.

Saya menguji dengan server backend berbasis apache2 A dengan SSL dan sertifikat klien yang ditandatangani sendiri diaktifkan. Konfigurasi Apache SSLOptions diatur ke:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

Ini membuat proses debug lebih mudah karena skrip phpinfo () di sisi backend akan menampilkan informasi Server dan Sisi Klien.

Untuk memverifikasi ini saya gunakan:

https: // backend / test / phpinfo

dengan sertifikat SSL yang diinstal di browser dan saya mendapatkan bagian seperti: SSL_SERVER_S_DN_CN untuk sertifikat server dan SSL_CLIENT_S_DN_CN untuk sertifikat klien.

Sebagai permulaan pertama saya menggunakan (mengisi bagian dalam tanda kurung) untuk mengkonfigurasi nginx pada 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;
  }
}

membatalkan bagian khusus Sertifikat Klien SSL hanya untuk memeriksa apakah proxy terbalik itu sendiri berfungsi.

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

Sekarang http: // frontend: 8080 / test / phpinfo.php berfungsi The

SSL_SERVER_S_DN_CN untuk sertifikat server ditampilkan dan SSL_CLIENT_S_DN_CN untuk sertifikat klien belum (belum) ditampilkan

Sekarang setelah berhenti komentar:

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

dan memeriksa / memulai kembali

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 berfungsi dan

SSL_SERVER_S_DN_CN untuk sertifikat server ditampilkan dan SSL_CLIENT_S_DN_CN untuk sertifikat klien ditampilkan

jadi sekarang kami dapat pekerjaan sesuai yang diminta.

Harap perhatikan bug https://trac.nginx.org/nginx/ticket/872#ticket

Wolfgang Fahl
sumber
Anda mungkin ingin berhati-hati dengan masalah negosiasi ulang ruby-forum.com/topic/6875137 yang mungkin merusak pertunjukan
Wolfgang Fahl
1

Ada artikel yang cukup rapi tentang sertifikat klien nginx dan SSL; menggunakan PHP dengan FastCGI sebagai contoh tapi saya pikir Anda dapat mengadaptasinya ke pengaturan proxy terbalik:

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

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

Erik Kaplun
sumber