NGINX SSL Reverse Proxy Verifikasi Upstream SSL

Aug 18 2020

Saya memiliki pengaturan NGINX sebagai proxy terbalik untuk meng-host beberapa situs web hanya dengan menggunakan satu alamat IP. Saya memiliki sertifikat Lets Encrypt di proxy dan sertifikat Lets Encrypt yang berbeda di server upstream. Pada dasarnya, saya memerlukan NGINX untuk meneruskan lalu lintas ke server hulu dan memverifikasi bahwa server hulu memiliki sertifikat TLS yang valid. Jika saya menonaktifkan proxy_ssl_verify, itu akan berhasil. Jika saya masuk ke https://app.local.example.comjaringan internal saya, aplikasi berfungsi dengan baik.

Diagram jaringan:

https://app.example.com --> NGINX Reverse Proxy --> https://app.local.example.com (Local IP Address)

File Konfigurasi Proxy Terbalik NGINX:

server {
    listen 80;
    rewrite ^ https://$host$request_uri? permanent;
}

server {
        server_name app.example.com;

        listen                                  443 ssl;

        ssl_certificate                         /etc/letsencrypt/live/app.example.com/cert.pem;
        ssl_certificate_key                     /etc/letsencrypt/live/app.example.com/privkey.pem;
        ssl_trusted_certificate                 /etc/letsencrypt/live/app.example.com/chain.pem;

        location / {

                proxy_redirect off;
                proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Ssl on; proxy_set_header X-Forwarded-Protocol $scheme;
                proxy_set_header X-Forwarded-HTTPS on;

                proxy_ssl_session_reuse        off;
                proxy_ssl_name                 app.local.example.com

                proxy_ssl_verify               on;
                proxy_ssl_verify_depth         2; # I've tried 1,2,3,4
                proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; 
                            
                proxy_pass                     https://app.local.example.com
        }
}

Inilah pesan kesalahan yang saya dapatkan.

[error] 1087#1087: *2 upstream SSL certificate verify error: (20:unable to get local issuer certificate) while SSL handshaking to upstream, client: [Client IP], server: app.example.com, request: "GET / HTTP/1.1", upstream: "https://192.168.1.5:443/", host: "app.local.example.com", referrer: "https://app.example.com/">

Versi OpenSSL: OpenSSL 1.1.1f 31 Mar 2020

nginx -v: nginx version: nginx/1.18.0 (Ubuntu)

kucing / etc / issue: Ubuntu 20.04.1 LTS \n \l

Output dari openssl s_client -connect app.local.example.com:443

CONNECTED(00000003)
depth=0 CN = app.local.example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = app.local.example.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:CN = app.local.example.com
   i:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFeDCCBGCgAwIBAgISA8NkbZ6wz2EnKcedXujKT9AmMA0GCSqGSIb3DQEBCwUA
...
-----END CERTIFICATE-----
...
SSL-Session:
    Protocol  : TLSv1.3
    ...
    Verify return code: 21 (unable to verify the first certificate)

Jawaban

2 SteffenUllrich Aug 18 2020 at 02:42
Certificate chain
 0 s:CN = app.local.example.com
   i:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3

Server Anda tidak dikonfigurasi dengan benar. Alih-alih mengirim sertifikat daun (app.local.example.com) dan sertifikat perantara, ia hanya mengirim sertifikat daun. Karena sertifikat perantara hilang, tidak ada jalur kepercayaan yang dapat dibuat ke jangkar kepercayaan lokal, yang berarti validasi sertifikat gagal dengan "tidak bisa mendapatkan sertifikat penerbit lokal" . Browser sering kali mengatasi masalah seperti itu dengan mendapatkan sertifikat perantara yang hilang dari tempat lain, tetapi tumpukan TLS lain biasanya tidak melakukan penyelesaian seperti itu.

Setelah Anda mengkonfigurasi server dengan benar, Anda akan melihat yang berikut ini di openssl s_client. Setelah ini selesai, nginx juga akan berfungsi.

Certificate chain
 0 s:CN = app.local.example.com
   i:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
 1 s:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
MarcWoodyard Aug 18 2020 at 13:17

Saya mengubah ssl_certificatenilai dari cert.pemmenjadi fullchain.pemdi server hulu.

ssl_certificate         /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/app.example.com/chain.pem;

Berikut tautan ke file konfigurasi NGINX yang saya gunakan