I have Web servers that run multiple virtual hosts, and I'd like to keep eavesdroppers from telling which virtual host a client is accessing. There's already a TLS extension for solving this problem: encrypted SNI. I see that Cloudflare supports it on its servers, and that Firefox has a setting to enable it on the client. I can't find any documentation of how to enable this on servers of my own, though. How do I do this? (I'm not tied to any particular server stack and will accept any working setup/architecture other than "put it behind Cloudflare".)

  • 1
    ESNI must be supported by the web server software. While it is unclear what server software you are using it is very likely not capable of ESNI since common server software like nginx or apache does not support it yet. – Steffen Ullrich Jul 23 '19 at 15:28

Encrypted Server Name Indication (ESNI) is still an Internet Draft, you will not find it in any major server implementation as it is subject to change. In fact, the draft version implemented by Firefox supports draft-ietf-tls-esni-01 which is incompatible with newer draft versions.

I posted a status of the ecosystem as observed in April 2019 here:

As you can see, OpenSSL, used by Nginx and Apache, do not support it. You could try to build Caddy with a patched Go crypto/tls library (using this PR from tls-tris), but it might not work over time.


For experimentation or educational purposes, you could use esnitool and tris-localserver from tls-tris. Assuming you have an appropriate Go toolchain installed on Linux or macOS, something like this should work:

# Get source code and build stuff
git clone https://github.com/cloudflare/tls-tris -b pwu/esni
cd tls-tris
make build-esnitool
(cd _dev/tris-localserver && ../go.sh build -v -i .)

# Generate ESNI key material, valid for 24 hours (one day)
_dev/esnitool/esnitool -validity=24h -esni-keys-file=esni.pub -esni-private-file=esni.key

It will create two files:

  • esni.pub - a value such as/wFsX6klACQA...AAAA= which you have to configure in DNS. If you would like to configure ESNI for www.example.com, create a TXT record for _esni.www.example.com with that /wFsX6klACQA<snip>AAAA= value. This format conforms to the draft-ietf-tls-esni-01 specification as supported by Firefox and Cloudflare. It does not use the latest draft specification.
  • esni.priv - a private key file, specific to the test implementation.

The test server can be started as follows:

_dev/tris-localserver/tris-localserver -esni-keys=esni.pub -esni-private=esni.priv

Then configure Firefox to enable use ESNI, open about:config and set network.security.esni.enabled to true. You also have to enable DNS-over-HTTPS as well, Firefox instructions can be found on that page. More details about each preference can also be found here: https://bagder.github.io/TRRprefs/

These instructions might work now, but will break in the future as Firefox will likely be updated to support newer draft versions. The esnitool above also hard-codes the permitted cipher suite (AES128-GCM) and key exchange algorithm (X25519). This reflects the parameters that are used by Cloudflare.


ESNI implies TLS 1.3, so the certificate and its embedded host names will be encrypted. With ESNI enabled, and using a secure DNS transport such as DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT), the server name will indeed not be visible on the wire, this can be verified in Wireshark using a filter such as frame contains "wireshark" when visiting wireshark.org.

However, if a single IP only hosts a few domains, then any passive adversary can guess that you are visiting one of those domains. A large operator such as Cloudflare has many more domains where this is not much of an issue.

Since ESNI uses semi-static keys, compromise of the private key means that any eavesdropper can decrypt the encrypted server name. That is why ESNI keys are frequently rotated, and automation is required. Cloudflare has this well-integrated, ESNI keys in DNS and the HTTPS service are regularly updated.

To conclude, ESNI is promising, but requires support from clients (web browsers), DNS servers over a secure transport (DoH/DoT), and web servers. It is still in development and unless you are closely following its development, it is likely not a good idea for you to set it up for things other than experimentation.


The previous very detailed answer inspired to reuse tls-tris to build tiny esni reverse proxy, that actually can terminate TLS 1.3 with ESNI and forward plain traffic to backend of your choice. This allows to easy use ESNI without any modification of web server you are using. The source code and detailed instruction can be found here: esni-rev-proxy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.