The Go programming language has the distinct advantage of compiling into a binary, which means I can compile for a particular target OS, bring my compiled binary onto my machine and it “just works”. Except when it doesn’t. In this case, it didn’t as we made HTTPS calls. The handshake between the two servers was failing, with the obtuse statement of ‘remote error: handshake failure‘. To the Go team’s credit, apparently all they get back from the server is that the handshake failed. No further detail, nothing to help track down root cause. I’ve spent two days in curl and openssl, trying to figure out why a GET which worked in curl didn’t work from either our Go code or via an openssl invocation.
Takeaways:
* openssl gives much more information about the SSL handshake than does curl, even with -v
* I have a greater appreciation of Java’s ability to work in enterprise (i.e. legacy) systems. Never really had to worry about this in Java.
* Go finally did the job, when given enough information about TLS settings. We got to stay away from ciphers, thankfully, though did a brief exposure to the number of cyphers in existence, as we investigated that potential path.
I’ll end up posting a snippet somewhere in our corporate environment about how to make 2-way SSL handshake actually work there, given what we discovered. Turns out, Go makes some assumptions that just don’t hold true in certain environments. Thankfully, I broke the case before ending up in Wireshark land. openssl s_client did the job… Corporate doesn’t really like sniffers being deployed on the network….