42

I'm unfortunately not much of a system administrator and have come upon a problem that has me banging my head against the wall.

The short story is that I'm running Nginx on EC2 (Ubuntu 14.04.4 LTS) to (a) host my company's marketing site (https://example.com, which incidentally is Wordpress) and (b) serve as a reverse proxy to our Rails app running on Heroku (https:// app.example.com), for certain paths. We use the same SSL certificate for both example.com and app.example.com. All of this has worked great for 8-10 months, but I recently switched from Heroku's paid SSL addon to the new free SSL offering, and now our reverse proxy is broken.

In checking the Nginx error logs, I see the following:

SSL_do_handshake() failed (SSL: error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: ipaddress1, server: example.com, request: "GET /proxiedpath/proxiedpage HTTP/1.1", upstream: "https:// ipaddress2:443/proxiedpath/proxiedpage", host: "example.com"

I've tried to search around for some additional guidance - I've upgraded Nginx (1.10.1) and OpenSSL (1.0.2h) with no luck. I suspected the issue might be due to Heroku's use of SNI in the new free SSL feature (https://devcenter.heroku.com/articles/ssl-beta), but haven't been able to determine why this might be a problem.

A few additional points on my exploration to this point:

  • When I switched to the new free Heroku SSL, I changed our app.example.com DNS record to point to app.example.com.herokudns.com, as instructed by the docs. The application can be accessed normally through app.example.com and when I run an nslookup on app.example.com and app.example.com.herokudns.com, I get the same IP address back. However...

  • I cannot access the application through either the IP address returned from nslookup or app.example.com.herokudns.com. I suspect this is normal and expected but don't know enough to say exactly why this is. And...

  • The IP address returned from the nslookup is NOT the same as the IP address referenced in the log's error message above ("ipaddress2"). In fact, "ipaddress2" is not consistent throughout the logs - it seems to change regularly. Again I don't know enough to know what I don't know... load balancing on Heroku's side?

And finally, my Nginx reverse proxy is configured as follows in nginx.conf:

http {

    client_max_body_size 500M;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    server_names_hash_bucket_size 64;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";

    server {

        listen 443 default_server;
        server_name example.com;

        root /usr/share/nginx/html;
        index index.php index.html index.htm;

        ssl on;
        ssl_certificate mycompanycert.crt;
        ssl_certificate_key mycompanykey.key;

        ssl_session_timeout 5m;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
        ssl_prefer_server_ciphers on;

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;

        location / {
            try_files $uri $uri/ /index.php?q=$uri&$args;
        }

        location ^~ /proxiedpath/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto https;
            proxy_pass https://app.example.com/proxiedpath/;
        }

    }

}

Any help is greatly appreciated - thanks very much!

Bart
  • 1,341
  • 1
  • 9
  • 8
  • Are your 2 sites hosted on the same server? Can you show us `app.mycompany.com`'s config? Because if they are on the same server then you could `return 301 https://app.mycompany.com/proxiedpath/;` and have nginx handle the request using `app.mycompany.com` server name with the same certificate. – Keenan Lawrence Jul 14 '16 at 13:49
  • Unfortunately they're completely separate - the proxy server is setup on AWS (where I have full control of the config) and the application server is hosted on Heroku (where I have relatively little control or even insight to the config). It worked prior to this change though, so I know it must be a fairly small thing. – Bart Jul 14 '16 at 15:17
  • Also, wanted to add - it's important to us for SEO reasons that these pages appear on mycompany.com as opposed to on app.mycompany.com, where they're actually being served from. – Bart Jul 14 '16 at 17:13
  • This is a rather rare message (maybe I don't do enough proxying): ***"SSL_do_handshake() failed (SSL: error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client..."***. I would center my searches around the reverse proxy, which I believe is Nginx. Also, if you provide real information, we might be able to help you better. I can't run any tests against `example.com` ( `mycompany.com` is a real website; `example.com` is reserved by IANA for the purpose). – jww Jul 14 '16 at 17:58
  • Your config does not specify `proxy_ssl_protocols`, `proxy_ssl_ciphers` etc –  Jul 14 '16 at 22:20

4 Answers4

90

I was able to solve this today and wanted to post the solution in case others run into the same issue.

It turns out that the problem was related to SNI after all. I found this ticket on nginx.org:

https://trac.nginx.org/nginx/ticket/229

Which led me to the proxy_ssl_server_name directive:

http://nginx.org/r/proxy_ssl_server_name

By setting to "on" in your config, you'll be able to proxy to upstream hosts using SNI.

Thanks to all who commented with suggestions!

Bart
  • 1,341
  • 1
  • 9
  • 8
  • It's the same as http://stackoverflow.com/questions/25329941/nginx-caching-proxy-fails-with-ssl23-get-server-hellosslv3-alert-handshake-fail/25330027#25330027 The only thing is that you should also enforce TLS1.0 or above, otherwise SNI won't be used. – Nikolay Dimitrov Apr 27 '17 at 03:13
  • 4
    Thanks for this answer. I thought finding this answer would be easy but google didn't think so – Nikhil Sahu Jul 04 '17 at 12:39
  • 3
    The specific OpenSSL error surfaced by nginx logs in this case is `SSL: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:SSL alert number 40`, that `alert number 40` is the critical part and translates to `this is probably a SNI host and the handshake didn't attempt SNI`, see [this](https://github.com/openssl/openssl/issues/7147) for more. `proxy_ssl_server_name on` should get you going. – evilSnobu Apr 04 '19 at 14:29
  • 2
    you saved my day. added `proxy_ssl_server_name on` and it worked for me ! Thank you – Gineesh Nov 29 '20 at 07:36
  • 3
    God bless you dear... you saved me! – Mojtaba Rezaeian Mar 18 '21 at 08:08
  • worked just perfectly, I was getting crazy since this never happened to me before – Miguel Trevino Sep 10 '21 at 19:42
  • I've spent week trying to pass the host via headers, god bless you – Evgeniy Chekan Mar 13 '23 at 11:27
13

As a note for others a related condition that Heroku imposes is that the HOST field must match the custom domain name.

So in addition to proxy_ssl_server_name you may also want to set a line like:

proxy_set_header Host mycustomdomain.com;

Of course this only applies if the host field incoming into the sever is different from the domain that your server resides in.

The specific error you get is:

SSL certificate error

There is conflicting information between the SSL connection, its certificate and/or the included HTTP requests.

Jason Axelson
  • 4,485
  • 4
  • 48
  • 56
10

Please try by adding proxy_ssl_server_name on

location ^~ /proxiedpath/ {
    proxy_ssl_server_name on;
 }
0

Just wanted to chime in and say after days of banging my head on my desk, I finally got my issue figured out. Wanted to post it here in case it helps others.

My issue was that I only had the server cert and key configured, and after running a test on https://www.ssllabs.com, it reported that the cert chain was incomplete. I changed the server cert to be the complete chain, and my issue is now resolved.

Hope that helps someone else in the same boat.

Mako-Wish
  • 303
  • 2
  • 12