0
votes

I have a legacy java web application that makes calls to an external webservice. The provider of that service is turning off TLS1.0 support. So, I am trying to see how the application can continue to work with the service.

The options I have seen are a) use BouncyCastle JCE instead of Java JCE http://boredwookie.net/index.php/blog/how-to-use-bouncy-castle-lightweight-api-s-tlsclient/, which I guess requires code change/ recompile (we don't have the luxury of doing it) or 2) use proxy servers https://www.reddit.com/r/sysadmin/comments/48gzbi/proxy_solution_to_bump_tls_10_connection_to_tls_12/

I have tried nginx proxy - it doesn't seem to handle the switch between TLS1.0 incoming and TLS1.2 that the end server expects.

 server { listen 443 ssl; server_name proxy.mydomain.com;

ssl_certificate D:/apps/openssl/proxy.mydomain.com.cert; ssl_certificate_key D:/apps/openssl/proxy.mydomain.com.private; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP; ssl_prefer_server_ciphers on;

location / { proxy_pass https://fancyssl.hboeck.de/; }

This fails with a 502/ bad gateway error since https://fancyssl.hboeck.de only support TLS1.2 but works with https://www.google.com that supports TLS1.0.

I am doing this on Windows.

1

1 Answers

1
votes

It's not TLSv1.2, it's lack of SNI leading to renegotiation.

First, I set up nginx (1.8.1/Windows) with a config like yours except using my own key&cert and proxying to my own test server. It worked fine, connecting from Java6 requester with TLSv1.0 and to server with TLSv1.2 (and even ECDHE-RSA-AES256GCM-SHA384, one of the 'best' ciphersuites) and returned pages just fine. I tried fancyssl.hboek.de and got 502 like you.

With wireshark I saw that nginx does not send SNI (by default) and at least using the IPv4 address 46.4.40.249 (I don't have IPv6) that server apparently hosts more than one domain because without SNI it provides a different (and expired!) certificate, for *.schokokeks.org, and after the first application data (the request) it sends an encrypted handshake (a renegotiation request -- which nginx does not honor). Testing with openssl s_client confirms that the server with SNI immediately sends the page but without it renegotiates first; repointing nginx to openssl s_server confirms that if the server requests renegotiation, receives no response, and closes nginx treats that as 502.

I would guess that Apache is renegotiating because it realizes the requested Host is not covered by the certificate -- except that it again uses the 'wrong' certificate. I haven't tried to track that part down.

Google does support TLSv1.2 (and ECDHE-RSA-AESGCM) when I connect, but even without SNI doesn't renegotiate, presumably because it's such high volume nothing else runs on www.google.com servers and there's no ambiguity. My test server doesn't have vhosts so didn't need SNI.

The nginx documentation reveals a directive proxy_ssl_server_name which can be set on to enable SNI, and then proxying to this server works.

FYI: several of the statements on that webpage are wrong, although its conclusion (if possible use TLSv1.2 with ECDHE or DHE and AES-GCM) is good. Also, most of your ssl_ciphers string is useless, but you didn't ask about that.


ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP

HIGH is an excellent start.

SEED is useless in a server used (only) by Java/JSSE client, because it's not implemented on the Java side. Even outside of Java it was pretty much used only in South Korea, where it was created as an alternative to DES or IDEA, and even there it is mostly obsoleted by ARIA which is an alternative to AES -- but is not implemented by OpenSSL and hence nginx.

aNULL is probably unneeded because JSSE disables 'anonymous' suites by default, but here it's worth it as defense in depth.

!eNULL does nothing; no eNULL suites are in HIGH, or DEFAULT, or even ALL. You can only get them explicitly or with the bizarre COMPLEMENTOFALL -- which you shouldn't.

!EXPORT !DES !RC4 do nothing; none of them are in HIGH. If instead you started from DEFAULT on older versions of OpenSSL, or from ALL, then they would be good.

!PSK is unneeded; nginx doesn't appear to configure for PSK and JSSE doesn't implement it anyway.

!RSAPSK is ignored because OpenSSL doesn't implement that keyexchange, and if it did those suites are already covered as above.

!aDH !aECDH are covered by !aNULL and thus do nothing.

!EDH-DSS-DES-CBC3-SHA is silly; there's no reason to exclude this one suite when you keep other DHE_DSS and 3DES suites.

!KRB5-DES-CBC3-SHA is ignored because OpenSSL doesn't implement Kerberos, and if it did nginx wouldn't be configured for it plus again it would be silly to exclude one suite while keeping similars.

!SRP is unneeded; like PSK nginx apparently doesn't configure and JSSE doesn't implement.

So: HIGH:!aNULL is all you need.