opennssl s_client shows wrong cert: browser shows

2019-09-14 19:41发布

问题:

We have 2 domains pointing to the same public AWS ELB and behind that ELB we have nginx, which will redirect requests to the correct server.

When we hit sub.domainA.com in the Browser (Chrome/Safari/etc), everything works, but when we use tools like openssl, we get a cert error:

openssl s_client -host sub.domainA.com -port 443 -prexit -showcerts

CONNECTED(00000003)
depth=0 /OU=Domain Control Validated/CN=*.domainB.com
verify error:num=20:unable to get local issuer certificate
verify return:1

For some reason, domainA is using domainB certs and I have no idea why.

I'm almost 100% sure the issue is with our nginx config (and more specifically, not having a default server block)

Here is our nginx config:

worker_processes  auto;

error_log  /var/log/nginx/error.log;
error_log  /var/log/nginx/error.log warn;
error_log  /var/log/nginx/error.log notice;
error_log  /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

http {
    include       /usr/local/openresty/nginx/conf/mime.types;
    default_type  application/octet-stream;
...
    #
    # DomainB
    #

    server {
        ssl on;
        ssl_certificate /etc/nginx/domainB.crt;
        ssl_certificate_key /etc/nginx/domainB.key;

        listen 8080;

        server_name *.domainB.com;

        access_log  /var/log/nginx/access.log  logstash_json;

        error_page 497 301 =200 https://$host$request_uri;

        set $target_web "web.domainB_internal.com:80";
        location / {
            keepalive_timeout  180;
            resolver 10.10.0.2 valid=30s;
            proxy_set_header Host $host;
            proxy_pass http://$target_web;
            proxy_set_header X-Unique-ID $request_id;
        }
    }

    #
    # DomainA
    #
    server {
        ssl on;
        ssl_certificate /etc/nginx/domainA.crt;
        ssl_certificate_key /etc/nginx/domainA.key;


        listen 8080;
        server_name *.domainA.com;

        access_log  /var/log/nginx/access.log  logstash_json;

        error_page 497 301 =200 https://$host$request_uri;

        set $target_web "web.domainA_internal.com:80";

        location / {
            keepalive_timeout  180;
            resolver 10.10.0.2 valid=30s;
            proxy_set_header Host $host;
            proxy_pass http://$target_web;
            proxy_set_header X-Unique-ID $request_id;
        }
    }
}

It shouldn't even be falling in the domainB block at all! Yet we see it when using "openssl s_client", but not in the browser.

Any ideas why we see domainB at all when using "openssl s_client -host sub.domainA.com"?

Very similar to Openssl shows a different server certificate while browser shows correctly

Very helpful website: https://tech.mendix.com/linux/2014/10/29/nginx-certs-sni/

回答1:

You need to specify the servername option in your openssl command.

From the openssl s_client docs:

-servername name

Set the TLS SNI (Server Name Indication) extension in the ClientHello message.

So try something like

openssl s_client -connect sub.domainA.com:443 -showcerts -servername sub.domainA.com


标签: nginx