ESNICheck is a Python module (with a web application frontend at esnicheck.com) that checks if a hostname supports the Encrypted Server Name Indication (ESNI
), an extension to TLSv1.3
that encrypts the SNI
field. This module checks if a hostname supports ESNI
by checking for TLSv1.3
support and verifying the ESNI
key published on its _esni
TXT
record. It supports drafts 01 and 02 of the ESNI
RFC.
The assumption as of this release is that if a hostname supports the TLSv1.3
protocol, publishes a valid ESNI
key (for versions 01 and 02 of the draft; the current versions supported by Firefox and CloudFlare), then that hostname supports ESNI
. The current version of the module does not try to establish a connection with the server using the encrypted_server_name
field in the ClientHello
to further confirm ESNI
support but there are plans to add it in a future release.
If you are not familiar with ESNI
, please start by reading this simple introduction from EFF or the post by CloudFlare.
There is no easy (automated) way to check for ESNI
support other than connecting to a website with Mozilla Firefox and looking at the sni=encrypted
string in the logs (HAR
), or observing the traffic using Wireshark (encrypted_server_name
). CloudFlare's ESNI Checker checks if your browser supports ESNI
when connecting to cloudflare.com
, however, it does not allow you to check if other websites support ESNI
.
This module provides an easy way to check for ESNI
support with the hope that this service will encourage the adoption of ESNI
, helping increase the privacy of users on the internet.
- Check for
TLSv1.3
support - Check for
_esni
DNS record and validity ofESNIKeys
- Establish a connection with
ESNI
(encrypted_server_name
extension inClientHello
)
Python 3.7+
and the dnspython
module (used for the DNS lookup).
To install, clone the repository and run the usual setup.py install
command.
>>> from esnicheck.check import ESNICheck
>>> host = ESNICheck("cloudflare.com")
>>> host.has_esni()
True
>>> host.has_tls13()
(True, 'TLSv1.3')
>>> host.has_dns()
(True, None, {'ESNIKeys': '/wH+dd/xACQAHQAgdy5Lv+M2t7kpbSzeytiOxYCW10CGZ8Pk8ZersvVMdlwAAhMBAQQAAAAAXqnOsAAAAABesbewAAA=', 'version': 'FF 01', 'checksum': 'FE 75 DF F1', 'keys [0]': 'x25519', 'keys_value [0]': '00 20 77 2E 4B BF E3 36 B7 B9 29 6D 2C DE CA D8 8E C5 80 96 D7 40 86 67 C3 E4 F1 97 AB B2 F5 4C', 'cipher_suites': 'TLS_AES_128_GCM_SHA256', 'padded_length': 260, 'not_before': datetime.datetime(2020, 4, 29, 19, 0), 'not_after': datetime.datetime(2020, 5, 5, 19, 0), 'extensions': '00 00'})
For more detailed instructions, run help(esnicheck.check)
.
The version of this module deployed at esnicheck.com is a Flask frontend (see app.py
) and also has a very basic API:
$ curl -X POST -H "Content-Type: application/json" -d '{"q":"cloudflare.com"}' https://esnicheck.com/check
{"has_esni":true}