SSL client hello sent when using TLS transport

579 views
Skip to first unread message

israelchen

unread,
Jan 10, 2015, 5:21:33 PM1/10/15
to golan...@googlegroups.com
Hi,

I am attempting to use go as a client for my Azure hosted SSL-enabled WebAPI. While I can call the WebAPI from pretty much anywhere (browsers, .NET, python clients),
a go client always fail with the following error: Get https://api.test.com:443: WSARecv tcp 192.168.1.5:14861: An existing connection was forcibly closed by the remote host.

my test client is very basic (please note that api.test.com is not a real address):

    ...

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }

    client := &http.Client{Transport: tr}

    resp, err := client.Get("https://api.test.com:443/")

    if err != nil {
        panic(err)
    }

    ...

using Wireshark on Windows, I believe that i've narrowed the problem down to the type of "client hello" packet that is sent and server response to it.

When using a browser/.NET/python client:

    52  3.943110000 192.168.1.5 137.117.9.212   TLSv1.2 268 Client Hello (dissector shows this as TLS v1.2)

    response ->

    57  2.888174000 137.117.9.212   192.168.1.5 TLSv1.2 191 Server Hello, Change Cipher Spec, Encrypted Handshake Message

When using the GO client:

    19  5.207428000 192.168.1.5 137.117.9.212   SSL 199 Client Hello (dissector shows this as TLS v1.0)

    response ->

    12  1.299626000 137.117.9.212   192.168.1.5 TCP 60  443→15179 [RST, ACK] Seq=1 Ack=122 Win=0 Len=0 (note that this is a RESET, ACK response)

Any clue as to what could be the issue? I understand that it may be that Azure LB/servers are rejecteing non TLS v1.2 packets
but is it possible to change that in go?

Thanks in advance,

--israelchen

N.B. go is awesome!

minux

unread,
Jan 10, 2015, 5:46:27 PM1/10/15
to israelchen, golang-nuts
On Sat, Jan 10, 2015 at 5:21 PM, israelchen <chis...@gmail.com> wrote:
Hi,

I am attempting to use go as a client for my Azure hosted SSL-enabled WebAPI. While I can call the WebAPI from pretty much anywhere (browsers, .NET, python clients),
a go client always fail with the following error: Get https://api.test.com:443: WSARecv tcp 192.168.1.5:14861: An existing connection was forcibly closed by the remote host.

my test client is very basic (please note that api.test.com is not a real address):

    ...

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }

    client := &http.Client{Transport: tr}

    resp, err := client.Get("https://api.test.com:443/")

    if err != nil {
        panic(err)
    }

    ...

using Wireshark on Windows, I believe that i've narrowed the problem down to the type of "client hello" packet that is sent and server response to it.

When using a browser/.NET/python client:

    52  3.943110000 192.168.1.5 137.117.9.212   TLSv1.2 268 Client Hello (dissector shows this as TLS v1.2)

    response ->

    57  2.888174000 137.117.9.212   192.168.1.5 TLSv1.2 191 Server Hello, Change Cipher Spec, Encrypted Handshake Message

When using the GO client:

    19  5.207428000 192.168.1.5 137.117.9.212   SSL 199 Client Hello (dissector shows this as TLS v1.0)
If you didn't set crypto/tls.Config.MaxVersion, then the default version sent in a client hello message
should be the maximum version supported by the package, which is 1.2.

However, there are two versions in the TLS clienthello handshake message, one is the TLS record
version, which the package hardcodes to TLS 1.0 for compatibility issues (see http://golang.org/src/crypto/tls/conn.go#L727),
and the other is the version in the message itself, which is 1.2.

It seems that your server reject the TLS 1.0 in the TLS record header, which i think it's incorrect.
it should read the version in the client hello message.

israelchen

unread,
Jan 10, 2015, 6:55:35 PM1/10/15
to golan...@googlegroups.com, chis...@gmail.com
Hi,

Thanks for your help.

The "inconsistency" between the handshake message version and the TLS record version was indeed the issue.
I've initially tried to set both Min, Max version in tls.Config to VersionTLS12 but it didn't work (wire output was the same as above).

When i reduced both the minimum and maximum versions to VersionTLS10, it worked. Wire output shows both the TLS record and handshake version as TLS 1.0.
VersionTLS11 works as well.

While I agree that the server should not automatically reject the handshake, the behavior does seem odd on the GO side as well, isn't?


--israelchen

minux

unread,
Jan 10, 2015, 7:01:42 PM1/10/15
to israelchen, golang-nuts
On Sat, Jan 10, 2015 at 6:55 PM, israelchen <chis...@gmail.com> wrote:
The "inconsistency" between the handshake message version and the TLS record version was indeed the issue.
I've initially tried to set both Min, Max version in tls.Config to VersionTLS12 but it didn't work (wire output was the same as above).

When i reduced both the minimum and maximum versions to VersionTLS10, it worked. Wire output shows both the TLS record and handshake version as TLS 1.0.
VersionTLS11 works as well.

While I agree that the server should not automatically reject the handshake, the behavior does seem odd on the GO side as well, isn't?
No, as the code comment showed, it's for compatibility with some (broken?) TLS servers in the wild.

israelchen

unread,
Jan 10, 2015, 7:12:06 PM1/10/15
to golan...@googlegroups.com, chis...@gmail.com
Oh, now I understand. I saw the code comment but I thought it applies to the default Min/Max version of 0 while I changed it to 771 (VersionTLS12).
Thanks anyways- you solved my problem.

--israelchen
Reply all
Reply to author
Forward
0 new messages