How does nginx verify certificates (proxy_ssl_verify)?

Consider nginx's parameters proxy_ssl_verify and proxy_ssl_trusted_certificate that are used to secure the communication to an upstream server.

# downstream server: nginx.conf

stream {
  server {
    # ...

    proxy_ssl on;
    proxy_ssl_verify on;

    proxy_ssl_trusted_certificate /etc/nginx/ssl/upstream.example.com/chain.pem;
    proxy_ssl_verify_depth 2;

  }
}

I was under the impression that, for proxy_ssl on, nginx would verify the certificate sent by the upstream server (upstream.example.com) against the proxy_ssl_trusted_certificate.

However, I've encountered a problem where nginx can't establish a secure connection to the upstream server and reports an upstream SSL certificate verify error: (2:unable to get issuer certificate) while SSL handshaking to upstream, while verifying the certificate with openssl does work.

# fullchain.pem: certificate sent by the upstream server
# chain.pem: CA certificate for `proxy_ssl_trusted_certificate`

# openssl verify -CAfile chain.pem fullchain.pem
fullchain.pem: OK

This made me wonder how nginx actually does the verification. Is there a way to reproduce this in isolation in order to debug why the error would occur?

Documentation

https://nginx.org/en/docs/http/ngx_http_proxy_module.html

proxy_ssl_verify on | off;

Enables or disables verification of the proxied HTTPS server certificate.

proxy_ssl_verify_depth number;

Sets the verification depth in the proxied HTTPS server certificates chain.

proxy_ssl_trusted_certificate file;

pecifies a file with trusted CA certificates in the PEM format used to verify the certificate of the proxied HTTPS server.


As the documentation says, proxy_ssl_trusted_certificate expects the CA certificate(s) to be used to verify the upstream server's TLS certificate. You seem to have provided that upstream server's TLS certificate chain. Provide the CA certificate(s) instead.