18.3.4 + Erlang TLS1.2 [+ IIS] Issues

There is a bug in Erlang when establishing connection to servers with specific SSL/TLS configurations, more commonly IIS servers it appears…

Links:

Noticed the behaviour when attempting to access Microsofts Graph API which is likely running on IIS…kind of explains the behaviour…

I cannot connect to the Graph API without using the 18.3 Erlang release, everything above that up to 19.2 just closes the connection before the handshake can finish…

Can test this using Poison and a simple GET to a Microsoft domain:

HTTPoison.get!("https://graph.microsoft.io/en-us/docs")

The HTTPoison readme mentions broken ssl in Erlang 19 - and suggests:

HTTPoison.get!("https://graph.microsoft.io/en-us/docs", [], [ ssl: [{:versions, [:'tlsv1.2']}] ])

This does not always seem to help…

Anyone else experience this?
Am not too familiar with the underlying TLS implementation in Erlang, and it is a bit over my head to try and fix myself…

This should be reported to Erlang devs to look into, however not sure if I can effectively articulate it.
Any help much appreciated!

1 Like

As far as I can tell the server chokes on the ClientHello message if the TLS version in the record layer doesn’t match the version in the client version field. This is a known area of compatibility issues (see RFC 5246, Appendix E).

If this is indeed the issue, then the workaround of selecting TLSv1.2 as the desired version should work. At least the server should not unceremoniously close the TCP connection (assuming it is configured to support TLSv1.2), though it might still fail with a handshake error. If you have a reproducible example of a connection that fails even when the version is constrained, can you share the details?

As the RFC mentions, there is no easy answer for universal interoperability. It may take several handshake attempts to connect to a ‘broken’ server. HTTPoison does not perform these retries for you, so you’d have to add some logic to your app to try and recover from failed requests.

2 Likes

Thanks for the response!

Worked around the problem by making the HTTP post with HTTPoison and not using the underlying HTTP methods in this OAuth2 library

They both use hackney so figure passing the [ssl: [{:versions, [:'tlsv1.2']}]] as a request option should solve it - but stills gets messed up when making a call using the OAuth2 lib

OAuth2.Client.get_token(.....,  [ssl: [{:versions, [:'tlsv1.2']}]]) 

Building my HTTPoison.post!/4 manually with the correct params+body+headers, and including [ssl: [{:versions, [:'tlsv1.2']}]] as an option appears to work consistently…

The URI I am experiencing problems with is https://login.microsoftonline.com/common/oauth2/token when completing the OAuth flow, and exchanging the access code for an access token.

Might be able to make some fixes to the OAuth library to fix this.

Considering this solved, is working now using Erlang 19.2 rather than <18.3.4 - by manually making post request with HTTPoison

Hackney expects SSL options to be passed in the :ssl_options key. See https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request-5

Try this:
OAuth2.Client.get_token(..., [ssl_options: [versions: [:'tlsv1.2']]])

1 Like

I’ve had a similar issue with the Microsoft Outlook servers https://github.com/Vagabond/gen_smtp/issues/114 The Outlook servers close the connection as soon as an SSL request is sent before a subsequent TLS request. However, the Google Email servers didn’t seem to have this problem. The problem with erlang ssl is that during the tls connection setup it first (incorrectly) sends an SSL request and then tries to send a TLS request. The fix for this is to always pass [{:versions, [:'tlsv1.2']}] as an option while doing ssl connections.

That was it!
Was using the HTTPoison ssl options key ssl instead of the correct hackney option key, ssl_options, Duh.

Thanks for the help!

1 Like

It looks like the issue has been resolved in OTP 20. So the workaround to force the connection to use TLS 1.2 should no longer be needed.

From the release notes:

OTP-13820    Application(s): ssl

             *** HIGHLIGHT ***

             TLS-1.2 clients will now always send hello messages on
             its own format, as opposed to earlier versions that
             will send the hello on the lowest supported version,
             this is a change supported by the latest RFC.

             This will make interoperability with some newer servers
             smoother. Potentially, but unlikely, this could cause a
             problem with older servers if they do not adhere to the
             RFC and ignore unknown extensions.
2 Likes