Nginx – SSL proxying on nginx — different behavior in different clients

nginxreverse-proxyssl

I'm running an SSL-required web service and planning to switch hosting providers. To avoid downtime for our users while DNS caches clear, I'm planning to proxy requests from our old server to the new one for a few days. Both the old and new site are running nginx and openssl.

I have a setup that appears to work perfectly in Chrome and Firefox, but fails in Safari and curl.

The proxy config section in my old server's nginx (1.6.2) config is pretty simple:

upstream droplet {
    server zin.droplets.gimlet.us:443;
}

server {
    listen   80;
        listen   443 ssl;
        server_name demo.gimlet.us;
#   proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#   proxy_ssl_session_reuse off;
    proxy_set_header Host       $host;
    location / {
        proxy_pass https://droplet;
    }
    error_log /tmp/proxy_error.log;
    access_log /tmp/proxy_access.log;
}

(changing proxy_ssl_protocols and proxy_ssl_session_reuse doesn't seem to make a difference)

Interestingly, the requests from Safari and curl don't generate log entries in my /tmp logs. However, in the main error.log, I get an entry like:

2014/11/21 17:02:08 [alert] 2937#0: worker process 13634 exited on signal 11

The output from curl -v suggests a good SSL handshake happens and then something goes awry:

$ curl -v https://demo.gimlet.us/favicon.ico
* About to connect() to demo.gimlet.us port 443 (#0)
*   Trying 74.50.48.201...
* connected
* Connected to demo.gimlet.us (74.50.48.201) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
*    subject: description=e08NImA1P8R1ukwA; C=US; ST=Wisconsin; L=Madison; O=Nathanael Vack; CN=*.gimlet.us; emailAddress=postmaster@gimlet.us
*    start date: 2014-04-10 16:59:37 GMT
*    expire date: 2016-04-11 09:29:37 GMT
*    subjectAltName: demo.gimlet.us matched
*    issuer: C=IL; O=StartCom Ltd.; OU=Secure Digital Certificate Signing; CN=StartCom Class 2 Primary Intermediate Server CA
*    SSL certificate verify ok.
> GET /favicon.ico HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8z zlib/1.2.5
> Host: demo.gimlet.us
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host demo.gimlet.us left intact
curl: (52) Empty reply from server
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):

Also notably, doing

$ curl http://demo.gimlet.us/favicon.ico

works fine.

I feel like I'm missing something very basic here. Any suggestions as to where I can look for more ideas?

Best Answer

Noting that SSL seemed to work with other domains on the same server, I added more SSL configuration directives. This one:

ssl_session_cache shared:SSL:10m;

cured the segfaults.

I believe this ticket is the underlying issue; nginx blames OpenSSL.

The effective nginx-level fix (and what I'm doing now that I know what's up) is to do your nginx-wide SSL configuration in the http context rather than repeating it in a bunch of server contexts.

Related Topic