2 Guys, 1 Failing HTTPS Request From A Virtual Minecraft Computer With No Error Messages
It's in the title.
# The Context
My friend and I were playing modded Minecraft hosted on a dedicated server he owns and we started getting into ComputerCraft (CC), a mod that adds computers into Minecraft which can be programmed using Lua. More specifically, the CC:Tweaked fork which is more actively developed and includes a few more features. CC has a networking API which can execute real life HTTP requests which is super cool for merging real life interactions with your Minecraft world.
# The Problem
My friend hosts GitLab on the same server as Minecraft was running on so I was thinking it would be cool to link it up to ComputerCraft so we would have somewhere to store all of our scripts. However, this is where the problem began, none of the requests would get through to GitLab. In fact, none of the HTTP requests got through to the server at all while any other domain worked fine. The only message that CC output was “Request failed”. The subsequent, problem-solving, extravaganza was not really how we expected our entire Saturday morning would play out.
# The Search
At first I thought the problem was ComputerCraft’s configuration because HTTP requests on local IP addresses are disabled by default. If GitLab is hosted on the same server, then it could be resolving the IP address to a local one and blocking the request. I had the same problem when testing my web-based CC todo program. Unfortunately, removing 127.0.0.1 from the blacklist and restarting the server didn’t help and neither did removing all of the black listed IPs.
Next, we considered that it was possible ComputerCraft didn’t support HTTPS because it wasn’t mentioned in the documentation and the server is setup to only accept HTTPS. However, we debunked this through testing and I later confirmed from the source code that the correct protocol is chosen based on the URL. Local IPv6 addresses were included in the default IP blacklist which gave us the idea to try looking into that. My friend started testing wget and realised that the first connection attempt to the server fails and falls back to IPv4. He looked into it and found that he had actually configured the server’s IPv6 address incorrectly. While it was a pleasantly unexpected way to find and resolve this problem, ComputerCraft still refused to connect so it must be something else. Just in case, we tested IPv6 addresses and CC supported it fine.
To get more info, I hopped into a single player world and tried to connect and the request failed yet again - this gave us the knowledge that it wasn’t because the request was coming in locally that the problem happened. Next, I fired up Postman to send a basic HTTP GET request to the server and that worked just fine. After that, I tried using wget, which is apparently also a powershell command, and the request… failed. So it turns out for some unusual reason that powershell’s wget command only uses the less secure TLS v1.0 protocol by default which is not enabled on the server. A variable must be set to enable the more recent 1.2 and 1.3 versions of TLS which allowed the request through successfully. Insert some joke here about Microsoft, backwards-compatibility and security. My friend tried to temporarily enable TLS v1.0 because I thought that maybe ComputerCraft also had the same problem but we couldn’t get it to work and there were more secure solutions to attempt first.
At this point it was obvious that we were going to have to dig a little deeper. It would have been incredibly helpful if we actually had a clue as to what the error was caused by, reminding me that I should probably also be putting in more helpful error messages into my programs. I tried scouring CC’s source code for anything related to TLS or SSL but my findings weren’t as helpful as I would have hoped. I discovered that it uses the Netty framework for sending requests which made me look into whether that supported more recent versions of TLS. As far as I could tell, it was up to Java itself to support it and we were running Java 1.8 so TLS v1.2 should be supported. I was tempted to compile CC from source and debug from there but the idea of going through the hassle of setting up a Java build pipeline put me off. Then I remembered Wireshark! The packet sniffer that I already had installed from what I can only remember to be technical shenanigans similar to this occasion.
Wireshark can’t filter packets by process so I just filtered packets to ones from and to the dedicated server. I requested something from CC in the single player world and sure enough, I could see the packets! There I confirmed that it was indeed using TLS v1.2 so the TLS version being an issue was debunked. Wireshark also showed one of the packets reporting an error “Handshake Failed”. We finally had something else to go off, even if I couldn’t find any more info from the packets.
So next off, trying to find out why a handshake can fail… it was something to do with SSL. I wondered if it was something to do with the certificate not being trusted. After some thinking my friend gave me a list of ciphers that his server supports from the nginx config so I looked into the packets to find where the client reports its supported cipher suites. Wireshark helpfully translates raw packet data into meaningful information and there it was. CC’s requests only supports AES128 encryption while the server was setup to only support AES256.
# The Fix
After a little research into whether AES128 was insecure compared to AES256 (they are practically both impossible to guess), my friend set his nginx configuration to the one on https://cipherli.st/ to allow the server to accept AES128 encryption and all of our in-game requests were happily successful.
The problem turned out to not quite be as complicated as we had first imagined and finding where to look was a much bigger hurdle than actually solving the problem itself. If anything had just reported to us that the request failed because of unsupported ciphers then this story wouldn’t have existed. I sat back in relief and laughed as I speculated that we are most likely the only people to have ever, and probably will ever, run into a problem where a Minecraft computer won’t connect to the server its running on because its SSL configuration is set slightly too strictly and have just about the combined know-how to break it down and solve it without error messages. Guiness World Records hit me up.