57

I try to configure an Nginx server as a reverse proxy so the https requests it receives from clients are forwarded to the upstream server via https as well.

Here's the configuration that I use:

http {

    # enable reverse proxy
    proxy_redirect              off;
    proxy_set_header            Host            $http_host;
    proxy_set_header            X-Real-IP       $remote_addr;
    proxy_set_header            X-Forwared-For  $proxy_add_x_forwarded_for;

    upstream streaming_example_com 
    {
          server WEBSERVER_IP:443; 
    }

    server 
    {
        listen      443 default ssl;
        server_name streaming.example.com;
        access_log  /tmp/nginx_reverse_access.log;
        error_log   /tmp/nginx_reverse_error.log;
        root        /usr/local/nginx/html;
        index       index.html;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_certificate /etc/nginx/ssl/example.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;
        ssl_verify_client off;
        ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;


        location /
        {
            proxy_pass  https://streaming_example_com;
        }
    }
}

Anyway, when I try to access a file using reverse proxy this is the error I get in reverse proxy logs:

2014/03/20 12:09:07 [error] 4113079#0: *1 SSL_do_handshake() failed (SSL: error:1408E0F4:SSL routines:SSL3_GET_MESSAGE:unexpected message) while SSL handshaking to upstream, client: 192.168.1.2, server: streaming.example.com, request: "GET /publishers/0/645/_teaser.jpg HTTP/1.1", upstream: "https://MYSERVER.COM:443/publishers/0/645/_teaser.jpg", host: "streaming.example.com"

Any idea what I am doing wrong?

3
  • Did you try without using upstream module by directly putting the WEBSERVER_IP in the proxy_pass directive to see if you get the same error ?
    – Benoit
    Commented Mar 20, 2014 at 11:34
  • No, I didn't try this but as explained below the option proxy_ssl_session_reuse off; made it work as expected.
    – Alex Flo
    Commented Mar 28, 2014 at 5:52
  • 11
    Please remove SSLv3 from supported protocols. It's not secure and you should not use it: ssl_protocols SSLv3
    – user220703
    Commented Jul 1, 2015 at 8:16

3 Answers 3

43

I found what was the error, I needed to add proxy_ssl_session_reuse off;

2
  • 1
    Thank you. For those out there who might still have issues after using this config, remember to use https instead of just http at the beginning of the URL given as a parameter in proxy_pass. Otherwise, nginx won't encrypt the traffic sent to upstream and you'll still get the same error message. Commented May 14, 2019 at 17:21
  • According to the doc, only if you see the errors “SSL3_GET_FINISHED:digest check failed” appear in the logs, then try disabling session reuse. nginx.org/en/docs/http/… The better approach is to turn off SSLv3 protocl via ssl_protocols directive.
    – Devy
    Commented Apr 6, 2020 at 18:21
35

In my case, I was trying to reverse proxy a website behind Cloudflare. I got the same error in /var/log/nginx/error.log. I tried many solutions and this one worked for me:

proxy_ssl_server_name on;

See nginx documentation:

Enables or disables passing of the server name through TLS Server Name Indication extension (SNI, RFC 6066) when establishing a connection with the proxied HTTPS server.

If a server terminates the TLS connection first with a server-global TLS certificate, it can look at the HTTP Host header to figure out which user/application should receive the HTTP request. But if the server serves domains with different TLS certificates (what all CDNs like Cloudflare do), the server needs to know which TLS private-key to use for TLS termination. Therefore it needs to look at the unencrypted TLS SNI header, as the HTTP Host header is still encrypted.

1
  • Thanks. This was same issue I had - my situation was two droplets on Digital Ocean, one which hosted the main domain and a second a subdomain. The main domain droplet was running Nginx and reverse proxying a specific path to the subdomain, which was running Caddy instead. Setting proxy_ssl_server_name on; resolved the various issues SSL_do_handshake() failed and no live upstreams while connecting to upstream on the Nginx server. Commented Jan 21, 2021 at 22:52
9

This fully solved the issue for me:

location / {
    proxy_pass https://server2.example.com;
    proxy_set_header Host $host;
    proxy_ssl_name $host;
    proxy_ssl_server_name on;
    proxy_ssl_session_reuse off;
    ...
}

I also had to add proxy_ssl_name in order to make sure that nginx knew what name to pass to the upstream https server.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .