Support dropping ESNI records for blocked domains

When combining Pi-Hole with pixelserv-tls , the encrypted blocked connections can be answered by an HTTPS server instead of being completely dropped ( BLOCKINGMODE=IP ).

The way this works is that pixelsrv-tls generates a certificate dynamically that will match the Server Name sent in the SNI extension, which should end up passing verification by the client (if the CA used to generate such certificates is trusted).

With ESNI (Encrypted Server Name Indication) that is now getting tested by CloudFlare and Mozilla, the client sends the server name encrypted so pixelsrv would be unable to generate a matching certificate.

While the connection will ultimately be blocked, the browser will attempt to establish such connections until it ultimately fails.

What would be great is if for blocked domains, there could be an option to also block the corresponding ESNI record. Right now this could mean answering with NXDOMAIN to _esni.blocked.domain.

It might be safe enough to enable by default when responding with an IP (BLOCKINGMODE=IP or IP-NODATA-AAAA)

Dropping all ESNI records with a regex is not an option as that would impact non-blocked domains.

While this is obviously the very beginning of this spec, I anticipate browser support to pick up soon. Both Firefox and Safari have preliminary implementations. And since CloudFlare supports basically 10% of internet traffic, I'm sure there are some commonly blocked domains already supporting this.

Original GitHub issue

@DL6ER, I've also read the GitHub discussion

For now, this can still be disabled in the browser, however this may change in the future.

What worries me more is the usage of ESNI in devices you cannot control, such as built in telemetry, chromecast, …

I think that it would be very wise to anticipate this new spec will be implemented sooner or later and already have a defense against it.

@mathieuh
Unfortunately, I'm NOT smart enough to make a case for this to be implemented in dnsmasq. I would suggest to propose this enhancement to Simon Kelley.

@DL6ER to avoid a possible conflict with the changes made to dnsmasq in pihole-FTL, your input for this request may (will?) be required...

It's unlikely to impossible that dnsmasq makes a change that pihole-FTL could not incorporate.

I agree, but I also see that this should be done inside dnsmasq instead of having to add another hack in pihole-FTL. Implementing regex blocking was one thing, but adding this would have to be done in an even deeper region of the dnamsq cache code which is something I really don't like to do.

1 Like

This thread is ageing a bit now, but I wanted to bump it now that both Firefox and Chrome's DoH trials are well underway and the protocol is becoming more normal.

I support this request from the original post entirely:

Use case

  • Like most people here, I run Pi-Hole locally on my LAN using Port 53.
  • When I take my laptop out of the network then the filtering stops working, because the local Pi-Hole instance is no longer available.
  • To fix this, I host my Pi-Hole instance in the cloud so I can access it from anywhere.
  • To avoid sending unencrypted DNS queries, my cloud-based Pi-Hole listens on DNS-over-HTTPS and this is where I point my browser.

Problem with Pi-Hole's current approach to ESNI

  • When ESNI is enabled in the browser, the browser makes TXT queries through Pi-Hole in the format: _esni.blocked.domain
  • Pi-Hole does not filter these queries, even for blocked domains, which can end up allowing the browser to access ESNI-enabled domains which should be blocked.
  • This is a significant proportion of filtered domains, as in theory it is any which are using Cloudflare.

pihole v5 blockes also TXT records, so blacklisting blocked.domain should suffice.

If your firewall allows it, you could use the daily updated (updates if changed) IPv4 and IPv6 lists to block port 443 for specific (DOH) IP' addresses.
https://discourse.pi-hole.net/t/doh-dns-over-https-ip-block-list-s/30393

Remember to add it as wildcard blacklist entry.
Blocking blocked.domain exactly will not block _esni.blocked.domain.

This is useful for manually-added domains but I guess the reason for the feature request is that it would also be useful for Pi-Hole or dnsmasq automatically filter queries to _esni.* for any domains which are on the Gravity lists.

I don't think you would want these queries to be answered at all, regardless of the blocking mode.

It is necessary to implement an exception in FTL to achieve this as dnsmasq provided feature could serve this purpose. Fortunately, compared to when this feature request was raised initially (2018), the rewrite done for FTL v5.0 allows us to implement this efficiently and even fairly straightforward.

So I went along and implemented it. We now reply to all _esni.X requests with NXDOMAIN given X is blocked for any reason (exact or regex blacklist or due to a gravity list match). The reply type will always be NXDOMAIN regardless of the configured blocking mode.

Please test it carefully! Run

pihole checkout ftl new/block_esni

to get the version of FTL containing this new feature. Note that, while the new _esni blocking defaults to being enabled, however, it may be disabled by setting

BLOCK_ESNI=false

in /etc/pihole/pihole-FTL.conf. I don't think there is any reason for why it would need to be disabled, however, it certainly won't hurt.

1 Like

Awaiting test results from you guys.

2 Likes

Fantastic! Thanks :smile:

I will test this today and report back.

I need to do more testing of course, but this seems to be working fine using the following instructions:

Currently I am deploying using the pihole/pihole:beta-v5.0 Docker container and ran the above command inside the container using docker exec.

Working example:

Thanks again for working on this :slight_smile: Looking forward to the v5.0 stable release.

1 Like

This feature has been merged and will be part of Pi-hole v5.0. Please go back to the regular beta using

pihole checkout ftl release/v5.0
2 Likes

Note to self: If people ask why gravity is blocking a domain not on their blocklist (_esni)...

Also, support team, this is a new configuration flag setting to look at.

1 Like

When enabling DEBUG_QUERIES=true, FTL will log:

[2020-04-28 18:19:27.867 9504] Blocking _esni.doubleclick.net as doubleclick.net is gravity blocked
1 Like

Great :+1: thanks.

And just to confirm, I've been running this since you pushed the test branch 8 days ago and it's worked perfectly and given me no problems in that time.

Closing to release the assigned votes.

Re-opening this as this may lead to a change?...

They rename it from Encrypted SNI ( ESNI ) to Encrypted ClientHello ( ECH ).

First, ESNI -> ECHO

Then, ECHO -> ECH