NGINX ssl upstream verify fail

meso_2600 picture meso_2600 · Jun 29, 2017 · Viewed 7.1k times · Source

[UPDATE]

This has been raised a a bug with NGINX support.

I have used default config file from the NGINX website (but without two way auth) in order to load balance between four upstream app servers over SSL with the the proxy_ssl_verify set to on. Yes, All upstream servers have valid certificates with CN matching their hostnames, and CA has been placed on the NGINX server with proper permissions and set in the nginx.conf file. Here are my findings (removed the rest of the config as it is not relevant):

  1. OK - Works with proxy_ssl_verify off:

    stream {
          upstream upstream_appsrv{
              server serverA.domain.com:443;
          }
          server {
              listen     8443;
              proxy_pass https://upstream_appsrv;
                (...)
              proxy_ssl  off;
              proxy_ssl_verify off;
          }
    }
    
  2. NOT OK - As soon as I set proxy_ssl_verify on + proxy_ssl on:

    stream {
        upstream upstream_appsrv{
            server serverA.domain.com:443;
        }
        server {
            listen     8443;
            proxy_pass https://upstream_appsrv;
            (...)
            proxy_ssl  on;
            proxy_ssl_verify on;
        }
    }
    

NGINX started throwing errors about upstream SSL certificate not matching the backend:2 upstream SSL certificate does not match "serverB.domain.com" while SSL handshaking to upstream...Lets change some things and go to the third step.

  1. OK! - Now everything works fine:

    stream {
            upstream serverA.domain.com{
                server serverA.domain.com:443;
            }
            server {
                listen     8443;
                proxy_pass https://serverA.domain.com;
                (...)
                proxy_ssl  on;
                proxy_ssl_verify on;
            }
    }
    

Turns out, that not only the server definition has to match the CN used in the certificate on the upstream server (obviously) but also the upstream upstream_appsrv needs to match the CN! Ok so next step, lets add another upstream server:

  1. NOT OK...

    stream {
            upstream serverA.domain.com{
                server serverB.domain.com:443;
            }
            server {
                listen     8443;
                proxy_pass https://serverA.domain.com;
                (...)
                proxy_ssl  on;
                proxy_ssl_verify on;
            }
    }
    

As soon as NGINX connects to the serverB we start seeing same errors again... Even though serverB has got proper CN set matching it's hostname (and is using same CA as serverA) it turns out that NGINX tries to match the CN against the upstream definition. And that's the issue I am trying to resolve.

Answer