NGINX SSL Reverse Proxy Vérifier SSL en amont

Aug 18 2020

J'ai configuré NGINX en tant que proxy inverse pour héberger plusieurs sites Web en utilisant une seule adresse IP. J'ai un certificat Lets Encrypt sur le proxy et un autre certificat Lets Encrypt sur le serveur en amont. Fondamentalement, j'ai besoin de NGINX pour transférer le trafic vers le serveur en amont et vérifier que le serveur en amont possède un certificat TLS valide. Si je désactive proxy_ssl_verify, cela fonctionnera. Si je vais https://app.local.example.comsur mon réseau interne, l'application fonctionne bien.

Diagramme de réseau :

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

Fichier de configuration du proxy inverse 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
        }
}

Voici le message d'erreur que j'obtiens.

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

Version d'OpenSSL :OpenSSL 1.1.1f 31 Mar 2020

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

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

Sortie deopenssl 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)

Réponses

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

Votre serveur n'est pas correctement configuré. Au lieu d'envoyer un certificat feuille (app.local.example.com) et un certificat intermédiaire, il envoie uniquement le certificat feuille. En raison du certificat intermédiaire manquant, aucun chemin de confiance ne peut être créé vers l'ancre de confiance locale, ce qui signifie que la validation du certificat échoue avec "unable to get local issuer certificate" . Les navigateurs contournent souvent ces problèmes en obtenant le certificat intermédiaire manquant ailleurs, mais les autres piles TLS ne proposent généralement pas de telles solutions.

Une fois que vous avez correctement configuré le serveur, vous devriez voir ce qui suit dans openssl s_client. Une fois cela fait, nginx devrait fonctionner aussi.

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

J'ai changé la ssl_certificatevaleur de cert.pemà fullchain.pemsur le serveur en amont.

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;

Voici un lien vers les fichiers de configuration NGINX que j'ai utilisés