NGINX SSL Reverse Proxy ตรวจสอบ Upstream SSL

Aug 18 2020

ฉันมีการตั้งค่า NGINX เป็นพร็อกซีย้อนกลับเพื่อโฮสต์เว็บไซต์หลายแห่งโดยใช้ที่อยู่ IP เดียว ฉันมีใบรับรอง Lets Encrypt บนพร็อกซีและใบรับรอง Lets Encrypt อื่นบนเซิร์ฟเวอร์อัปสตรีม โดยทั่วไปฉันต้องใช้ NGINX เพื่อส่งต่อการรับส่งข้อมูลไปยังเซิร์ฟเวอร์ต้นน้ำและตรวจสอบว่าเซิร์ฟเวอร์ต้นน้ำมีใบรับรอง TLS ที่ถูกต้อง ถ้าฉันปิดการใช้งานproxy_ssl_verifyมันจะใช้งานได้ หากฉันไปhttps://app.local.example.comที่เครือข่ายภายในของฉันแอปจะทำงานได้ดี

แผนภาพเครือข่าย:

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

ไฟล์การกำหนดค่า NGINX Reverse Proxy:

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

นี่คือข้อความแสดงข้อผิดพลาดที่ฉันได้รับ

[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/">

OpenSSL เวอร์ชัน: OpenSSL 1.1.1f 31 Mar 2020

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

แมว / etc / issue: Ubuntu 20.04.1 LTS \n \l

ผลลัพธ์ของ 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)

คำตอบ

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

เซิร์ฟเวอร์ของคุณไม่ได้รับการกำหนดค่าอย่างเหมาะสม แทนที่จะส่งใบรับรองใบ (app.local.example.com) และใบรับรองระดับกลางจะส่งเฉพาะใบรับรองใบ เพราะใบรับรองระดับกลางหายไปเส้นทางความไว้วางใจไม่สามารถสร้างขึ้นมาเพื่อยึดความไว้วางใจในท้องถิ่นซึ่งหมายถึงการตรวจสอบใบรับรองล้มเหลวด้วย"ไม่สามารถที่จะได้รับการรับรองจาก บริษัท ผู้ออกหลักทรัพย์ท้องถิ่น" เบราว์เซอร์มักจะแก้ปัญหาดังกล่าวด้วยการรับใบรับรองระดับกลางที่หายไปจากที่อื่น แต่กองซ้อน TLS อื่น ๆ มักจะไม่แก้ปัญหาดังกล่าว

เมื่อคุณกำหนดค่าเซิร์ฟเวอร์อย่างถูกต้องแล้วคุณจะเห็นสิ่งต่อไปนี้ในopenssl s_client. เมื่อเสร็จแล้ว nginx ก็ควรใช้งานได้เช่นกัน

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

ฉันเปลี่ยนssl_certificateค่าจากcert.pemเป็นfullchain.pemบนเซิร์ฟเวอร์ต้นน้ำ

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;

นี่คือลิงค์ไปยังไฟล์กำหนดค่า NGINX ที่ฉันใช้