CFHTTP and SSL issues with CommandBox 5
We recently ran into a puzzling issue with cfhttp
and CommandBox 5. Requests to certain domains, such as trycf.com, would fail with Unknown host: Received fatal alert: handshake_failure
, despite the domain's SSL certificate being valid. I hope this post, which digs into the somewhat unexpected source of them problem, is helpful to anyone else who might encounter the error.
tldr; Try adding the Runwar arg --ssl-eccdisable=false
to your server.json
file to resolve cfhttp
connection issues.
The Issue
While most cfhttp
requests worked as expected, we found our application unable to make requests to certain domains - a problem first, because one of the domains was a geocoding API we used, and second, because we didn't know why it was happening.
We took detours down a few rabbit holes, trying different versions of Java and tweaking a host of JVM args, but nothing worked; everything came back with an SSL handshake error.
Finally, we discovered that when our app had SSL enabled in server.json
, the cfhttp
requests would fail. If we disabled SSL, the requests would be completed successfully.
This, of course, made no sense and was the last place we thought to look. I put together a repro and opened a ticket for the issue: CommandBox-1173.
Update - 06/05/2020: A patch in CommandBox 5.1.1 resolved the issue that lead to this post for Lucee servers, though I believe that servers started with Adobe ColdFusion still experience it.
The Runwar Argument
Brad Wood, wizard of CommandBox that he is, responded to the ticket, asking me to try adding the following Runwar argument: --ssl-eccdisable=false
. Sure enough, with that flag added, the formerly failing cfhttp
requests worked, both with and without SSL enabled.
Here's what the flag looks like in a server.json
file:
{
"runwar":{
"args":"--ssl-eccdisable=false"
}
}
However, there's a bit more to the equation, because the way your application responds to this argument depends on the ColdFusion engine (Adobe, Lucee), the particular version, and the version of Java being used. And the results vary considerably - more on this at the end.
Why the Runwar Argument is Needed
It turns out that earlier versions of Adobe ColdFusion, running via CommandBox, had issues serving SSL certificates,[1] unless they were started with the JVM arg:
-Dcom.sun.net.ssl.enableECC=false
ECC stands for Elliptic Curve Cryptography, but I'm not going to pretend that I understand it any more than that.
The bottom line is that by disabling this ECC option, ColdFusion/CommandBox could serve SSL certificates without issue. Consequently, the flag disabling ECC got baked into CommandBox as a default and is applied when starting a server with SSL enabled. In an earlier version of Runwar that was used with CommandBox 4.8, this flag was only applied to Adobe ColdFusion servers, but because of how things were refactored, it now appears to be used across the board.
None of this mattered all that much, because there were no known negative side effects of passing in this option.
Considerations and Negative Side Effects
It turns out that enabling/disabling the ECC flag impacts not just how your application serves SSL, but also how it interacts with SSL certificates on other websites. For some current SSL certificates[2], disabling ECC renders ColdFusion unable to negotiate an SSL connection when making a cfhttp
request. The flag Brad provided overrides the CommandBox default, so the ECC option remains enabled, and ColdFusion can complete the cfhttp
request successfully.
Unfortunately, you can't just blindly implement --ssl-eccdisable=false
. If you have SSL enabled and are running Adobe ColdFusion 11, this option will prevent your app from loading because of an SSL protocol error. The same holds true for Adobe ColdFusion 2016, if you're running Java 8, though the protocol error is resolved if you're running Java 11.
That said, if you have SSL enabled and you're running any version of Lucee 5 or Adobe ColdFusion 2018, based on my limited testing, you'll likely want to configure your servers with --ssl-eccdisable=false
, to ensure the widest range of successful cfhttp
interactions with SSL certificates.
Compatibility Matrix
The table here should the results of my testing. The Runwar Arg column indicates if the server was started with the --ssl-eccdisable=false
flag. If the SSL connection was valid, I made cfhttp
requests to both https://trycf.com and https://google.com. Hopefully you find this helpful.
That said, there is no substitute for testing your own apps.
Engine | Version | Java | Runwar Arg | SSL Connection | trycf.com | google.com |
---|---|---|---|---|---|---|
Lucee | 5.3.6 | 8 | No | Valid | Failed | 200 OK |
Lucee | 5.3.6 | 11 | Yes | Valid | 200 OK | 200 OK |
Lucee | 5.3.6 | 11 | No | Valid | Failed | Failed |
Lucee | 5.2.9 | 8 | Yes | Valid | 200 OK | 200 OK |
Lucee | 5.2.9 | 8 | No | Valid | Failed | 200 OK |
Lucee | 5.2.9 | 11 | Yes | Valid | 200 OK | 200 OK |
Lucee | 5.2.9 | 11 | No | Valid | Failed | Failed |
Adobe | 2018 | 8 | Yes | Valid | 200 OK | 200 OK |
Adobe | 2018 | 8 | No | Valid | Failed | 200 OK |
Adobe | 2018 | 11 | Yes | Valid | 200 OK | 200 OK |
Adobe | 2018 | 11 | No | Valid | 200 OK | Failed |
Adobe | 2016 | 8 | Yes | Protocol Error | NA | NA |
Adobe | 2016 | 8 | No | Valid | Failed | 200 OK |
Adobe | 2016 | 11 | Yes | Valid | 200 OK | 200 OK |
Adobe | 2016 | 11 | No | Valid | 200 OK | Failed |
Adobe | 11 | 8 | Yes | Protocol Error | NA | NA |
Adobe | 11 | 8 | No | Valid | Failed | 200 OK |
Adobe | 11 | 11 | Yes | Protocol Error | NA | NA |
Adobe | 11 | 11 | No | Protocol Error | NA | NA |
Specific versions used for testing
- Adobe Coldfusion 2018.0.9+318650
- Adobe ColdFusion 2016.0.15+318650
- Adobe ColdFusion 11.0.19+314546
- Lucee 5.3.6+61
- Lucee 5.2.9+31
- Java (OpenJDK) 11_jdk-11.0.6+10
- Java (OpenJDK) 8_jdk8u252-b09.1
Footnotes
For an example of the errors/issue, see this discussion in the CommandBox forums. ↩︎
One commonality in the websites that we were unable to connect to was that their certificates were issued by Cloudflare. For example: https://trycf.com, https://geocoder.ca, and https://jsonplaceholder.typicode.com ↩︎