Skip to content
Frank Denis edited this page Jan 4, 2021 · 31 revisions

Built-in DoH server / Firefox ESNI (Encrypted ClientHello)

In addition to responding to standard DNS queries, dnscrypt-proxy can also act as a DoH server, and respond to local queries sent over that protocol.

In particular, this means that Firefox can be configured to use it, so that it will accept to enable ECH (previously known as ESNI) without bypassing your DNS proxy.

In order to enable this, the first thing you need is a certificate. Since this is just for local usage, you can use that example one or create your own with:

openssl req -x509 -nodes -newkey rsa:2048 -days 5000 -sha256 -keyout \
  localhost.pem -out localhost.pem

During generating a RSA private key, you will be aksed to answer various questions (Country Name, Organization Name, Email Address and so on).

However, these input fields can be empty or left to their default value.

Next, edit the configuration file, look for the local_doh section and uncomment the relevant lines:

[local_doh]
listen_addresses = ['127.0.0.1:3000']
path = "/dns-query"
cert_file = "localhost.pem"
cert_key_file = "localhost.pem"

The path to the localhost.pem file should be set in the cert_file and cert_key_file properties of the dnscrypt-proxy.toml configuration file. Also make sure that localhost.pem is readable by the dnscrypt-proxy user.

Now, dnscrypt-proxy should be restarted. With the settings above, the URL of the local DoH server would be https://127.0.0.1:3000/dns-query. Here is a small exception of the system logs:

[NOTICE] Now listening to https://127.0.0.1:3000/dns-query [DoH]
[INFO] [cloudflare] TLS version: 304 - Protocol: h2 - Cipher suite: 4865
[NOTICE] [cloudflare] OK (DoH) - rtt: 54ms
[NOTICE] Server with the lowest initial latency: cloudflare (rtt: 54ms)
[NOTICE] dnscrypt-proxy is ready - live servers: 1

Serving external queries

It is possible, but not recommended, to configure local_doh to listen to outside queries, for example:

[local_doh]
listen_addresses = ['123.456.789.1:3000']
path = "/dns-query"
cert_file = "fullchain.pem"
cert_key_file = "privkey.pem"

cert_file and cert_key_file can be generated using Let's Encrypt.

How to enable ESNI in Firefox

Firefox and Cloudflare used to be running an experiment called ESNI. ESNI was the name of an obsolete version of ECH (Encrypted ClientHello), a TLS extension to hide the server name in TLS (including HTTPS) connections.

They are both experimenting with ECH, the new revision of the protocol. However, stable versions of Firefox don't support ECH yet, and Cloudflare doesn't support ESNI any longer. Long story short: the SNI encryption experiment currently requires Firefox Nightly.

While this may eventually be a significant privacy improvement, ECH currently has some caveats to be aware of:

  • It is a work-in-progress design and has not yet seen significant (or really any) security analysis.
  • It hasn't been deployed anywhere, besides experiments in Firefox and on Cloudflare servers. Even when using Firefox, ECH will never be used except when connecting to some websites from Cloudflare customers.
  • Enabling ECH will trigger an extra DNS query for every single new hostname, even for hosts that don't support ECH. Every time a query for a host that doesn't support is made, an error will be returned (NXDOMAIN).
  • Enabling ECH in Firefox breaks some websites ("Secure connection failed - SSL_ERROR_NO_CYPHER_OVERLAP" or "SSL_ERROR_MISSING_ESNI_EXTENSION").
  • Keep in mind that ECH is still unfinished. What is available is only a technology preview.

Firefox has a setting to enable ECH (still called ESNI), but for some unexplained reasons, the web browser ignores it unless it was also configured to bypass your DNS settings.

However, dnscrypt-proxy's local DoH server can be configured in Firefox, so that the ECH/ESNI setting will not be ignored.

After having set up the local DoH feature as documented above, open the DoH server full URL (ex: https://127.0.0.1:3000/dns-query) as a regular website with Firefox.

The first time, the web browser will notice that the certificate is self-signed and complain about it. This is expected. Click "Advanced" and "I accept the risks". This is okay, you are only going to connect to your own machine. Please note, that without above step - without "accept the risk", using a DNS server to resolve the IP address of any website will be not working and there will be many TLS handshake error messages in system log files, such as - for example:

dnscrypt-proxy[13628]: http: TLS handshake error from 127.0.0.1:38984: remote error: tls: bad certificate

Next, type about:config in the URL bar, search for trr and make the following changes:

  • Set network.trr.custom_uri and network.trr.uri to https://127.0.0.1:3000/dns-query
  • Set network.trr.mode to 2
  • Set network.security.esni.enabled to true
  • Restart Firefox

You can finally check if the Firefox+Cloudflare ESNI experiment is enabled here (don't pay attention to the "Secure DNS" column, the green mark will only be shown when using Cloudflare).

Note that the actual resolvers don't have to be Cloudflare's, and don't have to use the DoH protocol either. ESNI is perfectly compatible with DNSCrypt and Anonymized DNSCrypt.

In order to revert the changes, set network.trr.mode to 0. Other parameters will then be ignored, so they can be left as-is.

Clone this wiki locally