I feel compelled to write about something I just found out yesterday. It was about a service that CloudFlare proudly touted as an innovation on web security technology — Keyless SSL. It allows CloudFlare, as a CDN provider, to “securely” serve content for the origin, with the origin’s own TLS certificate, but without requiring the origin to give up its private key. At first I was pleasantly surprised. If something can really be done it will with no doubt boost the security and even redefine how CDNs work today. Not a lot of information can be found about this new service on CloudFlare’s home page, since it’s only open to enterprise customers and costs a lot (5 grand a month), but Google always knows what I’m looking for. After some Googling around I quickly landed on one of CloudFlare’s blog posts which reveals the technical details behind their Keyless SSL service, which can be found here.
To be clear, it was a beautifully written blog post. It had one of the most accessible explanation of how TLS works in my recent memory, and it also did a great job explaining how their new service works on top of TLS. What they did is actually really cool from a technical perspective, and it’s good that they did everything under the audit of a security firm. CloudFlare is a great company — I use their service for the CDN of my very own blog, so I’m by no means attacking CloudFlare. I just feel compelled to raise my concern over this new service they provide, after reading their blog post explaining the details.
I encourage any interested reader to read the CloudFlare blog post first. It’s a little long, but if you are already familiar with TLS you can just skip to the very end. Even if you know nothing about TLS, reading this blog post is probably the best chance for you to actually understand what it is all about. In a nutshell, what Keyless SSL does is that it decouples the encryption and authentication part of the SSL/TLS protocol, so that CloudFlare’s servers handle the encryption part, and the authentication part (usually only happens during the very beginning of a connection, or handshake) is left to the origin server, which keeps the private key. For this architecture to work, they proposed modifications to the nginx webserver as well as the OpenSSL library, and these changes (as far as I know) have already been incorporated into the respective open-source projects. Now the origin needs to run a special “key server”, logically independent from the origin server that serves other web content, and that key server establishes a two-way-authenticated TLS connection with CloudFlare so that CloudFlare, and only CloudFlare, can get the key server to sign important handshake messages/parameters that are crucial to establish individual TLS connections with the clients. You can view the key server as the origin’s delegate to CloudFlare, so it can “sign off” handshake messages on behalf of the origin to CloudFlare, and then CloudFlare can use the signed messages to continue the supposedly origin-authenticated TLS handshake with a remote client.
So far, so good. This is indeed an innovation. TLS over CloudFlare’s service is arguably safer because the origin now never needs to give up its TLS private key. This is exactly what CloudFlare argues (and truly believes, I believe). However, as some users already pointed out under the comments following the blog post, there is a catch — CloudFlare knows the session keys to all TLS connections established via CloudFlare, and therefore these connections are not really “encrypted” from CloudFlare’s perspective: it can read the clear texts. Someone from CloudFlare dismissed this concern as a mere trust issue: you shouldn’t run your business on a third-party infrastructure if you don’t feel comfortable that that third-party is able to read your data. Well, to be fair, this is actually somehow required for CloudFlare to do their business: CloudFlare offers some cool feature called page rules, which means you can set up different caching rules for different URL patterns to get the best performance. Because of the way how HTTP over TLS works, it’s necessary for CloudFlare to be able to decrypt a TLS connection to see what the URL is and do the URL matching work. So, if you want to use CloudFlare’s feature, you need to give up at least the session key to CloudFlare, and they just came up with brilliant way for you to do that without exposing the long-term private key, which is something much more sensitive.
I totally understand CloudFlare’s position, but I oppose nevertheless. The reason is not that CloudFlare will be able to read the content of my TLS connection (they already can, and I trust them enough so that I don’t really care), but because it breaks one of the most fundamental security guarantees TLS provides. Before CloudFlare’s Keyless SSL extension was added to nginx and OpenSSL, whenever a TLS connection is successfully established, it is a authenticated and confidential connection. What it means is that you can be confident that the person on the other side is really who they claimed they are, and only you and them can read the content being sent over the connection. What it also means is that any third parties can’t know about the content of the conversation that’s happening over TLS. After all it is this very guarantee of TLS that enabled us to do so many sensitive things over the untrusted Internet, such as reading private emails, entering credit card numbers, banking, accessing medical records, and much more. We feel comfortable when that green padlock shows up in the address bar, because we can rest assured that the underlying math and engineering makes it almost impossible for even the most powerful adversary to learn what we are talking over the web. I argue that CloudFlare’s Keyless SSL and their extension to open-source projects like OpenSSL and nginx breaks this guarantee.
Before Keyless SSL, when a client establishes a TLS connection via CloudFlare, it will see either CloudFlare’s certificate, or an certificate provided the origin but now whose private key CloudFlare also have access to. Either is fine: the client will know that 1. the content is served through a third-party and not directly from the origin, or 2. the content is served directly from someone with the origin’s private key. In TLS’s world, whoever has Bob’s private key is Bob. That is to say, when you give up your private key to somebody, you explicitly authorized that person to act fully on your behalf. This is why the private key is so important, and great care should be taken when handling it. This is also the very reason that CloudFlare launched the Keyless SSL service, so that the risk of having the private key exposed can be kept to minimum. But CloudFlare’s Keyless SSL extension opened a dangerous door: now a TLS connections can be established with someone who actually doesn’t have the private key of the certificate it presented. A direct implication is that the client can no longer be sure that only the person with the private key can learn about the conversation, because it is now possible to learn the session key without the private key, and in my opinion this is contrary to the design of the TLS protocol.
What’s even more dangerous is the way it makes security “look” better. A business (a very incompetent one, in this case…) may think it’s totally safe to use CloudFlare to serve the most sensitive data because CloudFlare doesn’t have the private key, but actually they are exposing their customers to a third party that they (the customers) don’t even know exist.
I really think that CloudFlare’s Keyless SSL and their extensions to the SSL/TLS protocol are dangerous and unnecessary, and they undermine the strong security guarantees provided by the “vanilla” versions of the protocol, making it weaker. The key server in this case is a clear vulnerability that doesn’t have to exist, and it’s against TLS’s original designers’ will to physically decouple the private key and the session key. I believe the Internet is safer when we have the one simple and strong guarantee that the original TLS provides: only you and whoever have that private key can read this conversation. No, not a CloudFlare that doesn’t have your private key. Let’s don’t have security broken (again) with another quest for convenience.