Keyless SSL

Security

A TLS deployment pattern where a CDN edge terminates TLS for a site without ever holding its private key: the key stays on a key server the customer runs, and the edge sends it only the one private-key operation each full handshake needs.

Also known as TLS handshake proxying.

12 min read Updated Aug 30, 2026

Full Explanation

Keyless SSL is a TLS deployment pattern. A CDN’s edge server terminates encrypted connections for your hostnames. The private key never leaves infrastructure you control. The edge runs every step of the handshake except the one that needs the key. It asks a key server you operate to perform that step. Three things it is not.

It is not “keyless” in the sense of having no key. The key exists and is used on every full handshake. The CDN simply never holds it.

It is not a change to the protocol the browser speaks. The visitor negotiates an ordinary TLS session with the edge, and the split happens behind it. So no client support is needed (2015 analysis).

And it is not privacy from the CDN. The edge derives the session keys itself (Cloudflare), so it reads your plaintext and could serve content your origin never sent. What you keep is custody of the long-term key, not confidentiality from the edge.

Controlling only where a CDN keeps your key is a different product again. That product is Cloudflare’s Geo Key Manager, where Cloudflare still holds the key.

Cloudflare announced Keyless SSL, styled Keyless SSL™, on 18 September 2014 (announcement). The technique’s generic name in the literature is TLS handshake proxying. RFC 9345 files it under remote signing mechanisms, noting that they incur per-transaction latency (RFC 9345 sections 1 and 3.2).

How it works

A full TLS handshake uses the certificate’s private key exactly once (Cloudflare). In an RSA key exchange, the server decrypts the premaster secret that the client encrypted to the certificate. In an ECDHE key exchange, the server signs its ephemeral key-exchange parameters together with the client and server randoms. Keyless SSL moves that single operation off the edge, and nothing else.

  1. The client opens a normal handshake with the edge, which answers with ServerHello and your certificate.
  2. At the private-key step, the edge sends a decrypt-or-sign request to your key server. The request carries the encrypted premaster secret, or the randoms and parameters to be signed, plus an identifier for the certificate. It travels over a mutually authenticated (mTLS) connection, on TCP port 2407 by default.
  3. The key server performs the operation and returns only the result. The key itself never crosses the wire.
  4. The edge derives the session keys, completes the handshake, and serves the traffic. Once the handshake is done, the key server is not involved again for that session (Cloudflare).

Two things hold the cost of that detour to one round trip per new session, rather than one per request.

First, the edge keeps persistent connections to the key server, so a new visitor does not also pay to set that connection up.

Second, resumed sessions need no private-key operation at all. This applies to session tickets and session IDs alike. So only a cold, unresumed session reaches the key server.

Key servers are stateless, so you can run several. Cloudflare recommends at least two behind a load balancer, with health checks on the keyless port. Or you can advertise one address by anycast from several locations, so the edge reaches the nearest one (docs).

Nothing in the design forces the key server to sit on your premises. It can equally be run by the CDN in a hardened location, or by a third party for compliance reasons (2015 analysis). So the question to ask of any deployment is who holds the key, not where the box is.

Why it matters for a CDN

To terminate TLS for your hostname, an edge must be able to complete handshakes for it. The usual price of admission is giving the CDN your private key.

RFC 9345 states the risk plainly: termination services sit in locations such as remote data centres and CDNs where it may be difficult to detect compromises of private key material.

For regulated customers, that is frequently a hard blocker rather than a preference. Cloudflare’s own framing is that for regulatory reasons, many organizations cannot share their private keys (learning centre). The bankers who asked it for this in 2012 told it that in the United States, a lost SSL key is a critical security event reportable to the Federal Reserve (2014 announcement).

Keyless SSL removes the blocker. The customer keeps custody and still gets edge termination, caching, and DDoS absorption in front of its origin.

The cost is measured, not theoretical. In the 2015 experiment, run on a low-traffic site through Cloudflare’s control panel, a client in Dublin fetched from a site in San Francisco. Straight to the origin, the handshake took 497 ms. With the key uploaded to a London edge, it took 64 ms. With the handshake proxied from London back to a key server in San Francisco, it took 395 ms (Stebila and Sullivan, 2015).

Keyless SSL was slower than surrendering the key, but far faster than no CDN, and the cost was paid only on a cold session. You are trading key custody for a new availability dependency and a slower first handshake. Deploy it for the hostnames whose keys genuinely carry that constraint, rather than as a default TLS posture.

What CDNs do

  • Cloudflare ships the named product. Keyless SSL is an Enterprise-only paid add-on. You must supply your own certificate from a certificate authority: Cloudflare issues none for use with it. Every Keyless hostname must be proxied (docs).
  • The key server is yours to run. Its source is published as gokeyless (repo). It installs from Cloudflare’s package repository as a .deb or .rpm. The docs list Ubuntu 20.04, 22.04 and 24.04; Debian 11, 12 and 13; RHEL 8 and 9; CentOS 8 and Stream 9; and Amazon Linux 2 and 2023, tested on amd64 and arm (docs). Keys live in a directory as PEM or DER .key files, or in an HSM addressed by a PKCS#11 URI (docs). They can also live in Azure Key Vault and Managed HSM, or Google Cloud KMS: gokeyless reaches those through the services’ own APIs rather than PKCS#11. It exposes Prometheus metrics on port 2406 by default.
  • Enrolment is automatic. Configure the key server with its hostname, zone ID, and an API credential. On first start with those set, it generates its own key and certificate signing request. It receives back the certificate it presents to Cloudflare for mutual TLS. The legacy Origin CA Service Key stops working for this on 30 September 2026 (docs).
  • Two ways to reach it. Cloudflare’s preferred setup carries edge-to-key-server traffic over a Cloudflare Tunnel. This avoids exposing the key server to the public Internet (docs). The public-DNS alternative needs an A or AAAA record that cannot be proxied. So it publishes the key server’s IP address (docs).
  • Delegated credentials as an optimisation. If your certificate carries the DelegationUsage extension, Cloudflare periodically has the key server sign a short-lived credential. Cloudflare then uses that credential at the edge for clients supporting RFC 9345, so those handshakes complete without reaching back (docs). Cloudflare’s credentials become invalid within 24 hours; RFC 9345 caps validity at 7 days absent an application profile. Cloudflare is explicit that this is a performance optimisation for Keyless SSL, not a replacement for it, because clients have to be updated to support it (2019 announcement). Note what moves: the edge then holds a short-lived signing key of its own.
  • Beyond Cloudflare, check before you assume. Akamai filed a patent application in 2013 on terminating SSL connections without locally-accessible private keys. The 2015 analysis records that it had no deployed system at that time (paper, section I-B). Treat any other vendor’s equivalent as something to confirm in its current documentation, rather than as industry parity.

Watch out for

  • The key server becomes a hard dependency for new connections. If the edge cannot reach it, a full handshake cannot complete. So new visitors fail, while cached content sits ready at the edge. Cloudflare says as much: the network between your key server and its network may not be reliable, which could prevent new TLS connections. Cloudflare recommends a high-availability deployment for that reason (docs). Established and resumed sessions are unaffected.
  • Latency on a cold session. The first, unresumed handshake pays the edge-to-key-server round trip. Cloudflare puts this at as much as a second if the key server is on the other side of the world (docs). Resumption and placing key servers near the traffic remove most of that, but never all of it.
  • The key server is a cryptographic oracle. It will perform private-key operations for anyone who can reach it. Cloudflare’s mitigations are mutual TLS with client certificates from its own internal CA, X.509 Extended Key Usage restrictions on those certificates, a connection cipher suite restricted to two ECDHE AEAD suites, and customer firewall rules limiting inbound traffic to Cloudflare address space (details). Constant-size responses close the length side channel. But the 2015 analysis is firm: RSA key transport still requires the standard timing-side-channel protections against Bleichenbacher’s attack in the key server’s decryption path (paper, section IV-D).
  • The trust boundary does not move as far as it sounds. The edge still terminates the session. So it holds the session keys, sees your plaintext, and could serve content the origin never sent. The 2015 threat model explicitly excludes a still-authorised edge that collects user data or serves other content. What Keyless SSL buys is different: a compromised edge loses the ability to impersonate you the moment the key server stops answering.
  • RSA key exchange is the weaker choice here, twice over. Under ECDHE, the key server only signs, and recorded traffic stays safe if the key later leaks. Under RSA key exchange, it returns the premaster secret itself. So a leaked key retroactively opens recorded sessions, and the remote oracle is a decryption oracle rather than a signing one. The 2015 analysis adds a subtler gap: signed Diffie-Hellman meets every security goal of handshake proxying, while RSA key transport misses uniqueness of the key-server session. This is because the key server sees only the ClientKeyExchange message, and an attacker can replay it (paper, section IV-C).
  • TLS version. Cloudflare’s docs state that TLS 1.3 is not supported for Keyless SSL (docs). So full handshakes on those hostnames land on TLS 1.2 and earlier. That is also where the decrypt-or-sign split above lives, since TLS 1.3 removed static RSA key exchange and leaves one signature as the only use of the certificate key (RFC 8446 section 1.2). Delegated credentials sit on the other side of that line: RFC 9345 defines them for (D)TLS 1.3 or later only, and forbids their use in earlier versions.
  • Delegated credentials are not yet a general answer. Cloudflare’s docs say very few clients support them. Only a handful of certificate authorities will issue certificates carrying the extension. The docs name DigiCert as one that works, and Firefox 77 and later as supporting clients (docs). A credential also cannot be revoked without revoking the certificate (RFC 9345 section 3).
  • Two certificates, one common mistake. The edge certificate carries your site hostnames. The key server’s authentication certificate carries the key server hostname. Cloudflare calls confusing the two the most common setup error. It warns against adding the key server hostname to the edge certificate’s subject alternative names: that leaks an internal hostname into Certificate Transparency logs, and is not required (docs).
  • gokeyless is published, not open source. Its own README states that the license for the project is not “open source” as described in the Open Source Definition (repo). Treat it as source-available when your review process asks.

Best practice

  • Treat key-server availability as site availability. Run at least two key servers behind a load balancer, with health checks on the keyless TCP port (2407 by default). Or advertise one address by anycast from several locations.
  • Prefer the Cloudflare Tunnel setup, so the key server needs no public listener. If you must use public DNS, generate a long random hostname (the docs use openssl rand -hex 24). Accept that the record cannot be proxied, so it exposes the key server’s IP address.
  • Restrict inbound connections to the CDN’s published address ranges. Cloudflare’s docs point at its IP details API for the current IPv4 and IPv6 lists.
  • Put key servers in the regions that serve the traffic. Leave TLS session resumption enabled, so only cold sessions ever pay the round trip.
  • Prefer ECDSA certificates with ECDHE. The remote operation is then a signature, never a decryption. This preserves forward secrecy and keeps the per-handshake work small. Cloudflare’s published openssl figures put P-256 ECDSA at about 9,500 signatures per second, against about 1,000 for RSA 2048 on the same machine: a 9.5x saving on the private-key operation (benchmark).
  • Keep the private key in an HSM over PKCS#11, or in a managed key service, rather than as a plaintext .key file. If you do use files, the docs specify 400 permissions owned by the keyless user. Keep every key present on every key server.
  • Scrape the key server’s metrics endpoint, not just the site. It exports request duration by operation type, failed connections, and the expiry timestamp of the key server’s own authentication certificate.
  • Migrate key server enrolment to an API token before 30 September 2026, when Origin CA Service Keys stop working for enrolment and certificate refresh. Use gokeyless 1.18.0 or later, with a token scoped Zone > SSL and Certificates > Edit.
  • Where clients support them, let delegated credentials carry the handshakes. Keep the key server running anyway: the credentials are signed through it, and expire within a day.

Examples

# Keyless SSL handshake flow (text diagram)
#
# Client          CDN Edge         Key Server (Customer)
#   |---ClientHello--->|                    |
#   |<--ServerHello----|                    |
#   |<--Certificate----|                    |
#   |---KeyExchange--->|                    |
#   |                  |---Sign request---->|
#   |                  |<--Signature--------|  (private key op)
#   |<--Finished-------|                    |
#   |---Finished------>|                    |
#   |<====Encrypted data flows============>|

# Install Cloudflare's open-source key server (gokeyless)
git clone https://github.com/cloudflare/gokeyless.git
cd gokeyless && make

# Key server configuration
# /etc/keyless/gokeyless.yaml
private_key_dirs:
  - /etc/keyless/keys
metrics_addr: localhost:2408

# Deploy key server with private key
cp your-private-key.pem /etc/keyless/keys/
systemctl start gokeyless

# Verify key server is responding
curl -s http://localhost:2408/metrics | grep keyless
# keyless_sign_requests_total 42
# keyless_sign_request_duration_seconds{quantile="0.5"} 0.002

# TLS session resumption avoids key server round trip
openssl s_client -connect example.com:443 \
  -sess_out /tmp/tls_session
openssl s_client -connect example.com:443 \
  -sess_in /tmp/tls_session
# Second connection: "Reused, TLSv1.3" (no key server hit)

Frequently Asked Questions

A TLS deployment pattern where a CDN edge terminates TLS for a site without ever holding its private key: the key stays on a key server the customer runs, and the edge sends it only the one private-key operation each full handshake needs.

# Keyless SSL handshake flow (text diagram)
#
# Client          CDN Edge         Key Server (Customer)
#   |---ClientHello--->|                    |
#   |<--ServerHello----|                    |
#   |<--Certificate----|                    |
#   |---KeyExchange--->|                    |
#   |                  |---Sign request---->|
#   |                  |<--Signature--------|  (private key op)
#   |<--Finished-------|                    |
#   |---Finished------>|                    |
#   |<====Encrypted data flows============>|

# Install Cloudflare's open-source key server (gokeyless)
git clone https://github.com/cloudflare/gokeyless.git
cd gokeyless && make

# Key server configuration
# /etc/keyless/gokeyless.yaml
private_key_dirs:
  - /etc/keyless/keys
metrics_addr: localhost:2408

# Deploy key server with private key
cp your-private-key.pem /etc/keyless/keys/
systemctl start gokeyless

# Verify key server is responding
curl -s http://localhost:2408/metrics | grep keyless
# keyless_sign_requests_total 42
# keyless_sign_request_duration_seconds{quantile="0.5"} 0.002

# TLS session resumption avoids key server round trip
openssl s_client -connect example.com:443 \
  -sess_out /tmp/tls_session
openssl s_client -connect example.com:443 \
  -sess_in /tmp/tls_session
# Second connection: "Reused, TLSv1.3" (no key server hit)

Yes. Keyless SSL is also known as TLS handshake proxying. A TLS deployment pattern where a CDN edge terminates TLS for a site without ever holding its private key: the key stays on a key server the customer runs, and the edge sends it only the one private-key operation each full handshake needs.

Related CDN concepts include: