Skip to content
szemley edited this page Dec 31, 2020 · 22 revisions

Anonymized DNS

[List of public Anonymized DNS relays]

DNS encryption was a huge step towards making DNS more secure, preventing intermediaries from recording and tampering with DNS traffic.

However, one still has to trust non-logging DNS servers for actually doing what they pretend to do. They obviously see the decrypted traffic, but also client IP addresses.

In order to prevent this, using DNS over Tor or over proxies (HTTP, SOCKS) has become quite common. However, this is slow and unreliable as these mechanisms were not designed to relay DNS traffic.

Anonymized DNS prevents servers from learning anything about client IP addresses, by using intermediate relays dedicated to forwarding encrypted DNS data.

How does it work?

Instead of directly reaching a server, an Anonymized DNS client encrypts the query for the final server, but sends it to a relay.

The relay doesn't know the secret key, and cannot learn anything about the content of the query. It can only blindly forward the query to the actual DNS server, the only server that can decrypt it.

The DNS server itself receives a connection from the relay, not from the actual client. So the only IP address it knows about is the IP of the relay, making it impossible to map queries to clients

Anonymized DNSCrypt

Anonymized DNS can be implemented on top of all existing encrypted protocols, but DNSCrypt is by far the simplest and most efficient instantiation.

It only adds a header with a constant sequence followed by routing information (server IP+port) to unmodified DNSCrypt queries. Implementing it on top of an existing DNSCrypt implementation is trivial.

The overhead is minimal. Unlike DoH where headers may still reveal a lot of information about the client's identity, Anonymized DNSCrypt, by design, doesn't allow passing any information at all besides the strict minimum required for routing.

For relay operators, Anonymized DNSCrypt is less of a commitment than running a Tor node. Queries can only be relayed over UDP, they need to match a very strict format, amplification is impossible, and loops are prevented. Relays can essentially be only used for encrypted DNS traffic.

Configuring anoymized DNS in dnscrypt-proxy

This requires a fairly recent version of dnscrypt-proxy. Support for Anonymized DNSCrypt was introduced in version 2.0.29.

Anonymization only works with DNSCrypt servers. If you need to use DoH servers, you still have to use Tor, or SOCKS proxies instead.

Enabling both DoH and DNSCrypt servers in your configuration is totally fine, but DoH traffic will not be anonymized.

The configuration file includes an [anonymized_dns] defining a set of "routes". A route describes how to reach a server via a relay.

[anonymized_dns]
routes = [
    { server_name='example-server-1', via=['anon-example-1', 'anon-example-2'] }
]

The snippet above defines a route. It tells the proxy that instead of connecting to example-server-1 directly, it should connect to either anon-example-1 or anon-example-2 instead, and these will securely forward the queries to example-server-1.

example-server-1 will only see the IP addresses of anon-example-1 or anon-example-2. Your own IP address cannot be transmitted to example-server-1. And anon-example-1 and anon-example-2 will only see encrypted content, that they can't decrypt, because only example-server-1 knows the decryption key.

But what is example-server-1 exactly?

example-server-1 is the name of any DNSCrypt server. Likely one of the servers configured in the server_names parameters.

What are anon-example-1 and anon-example-2?

These are relays. A list of relays can be found in the relays.md file that is automatically downloaded by default along with other server lists.

So, neither the servers nor dnscrypt-proxy chooses what relays will be used to reach a server. You are in control.

You probably want relays and the servers they relay to to be operated by different entities. If you want to minimized latency, choose relays and servers that are close from a network perspective. If you feel paranoid, choose relays and servers in different countries. You decide.

As many routes as needed can be defined. And each server can use a different set of relays:

[anonymized_dns]
routes = [
    { server_name='example-server-1', via=['anon-example-1', 'anon-example-2'] },
    { server_name='example-server-2', via=['anon-example-3'] },
    { server_name='example-server-3', via=['anon-example-1'] }
]

Relay names can also be replaced with DNS stamps (sdns://...), IPs and ports (ip:port) or hostnames and ports ('host:port). If a resolver also acts as a relay, it's possible to use its regular stamp instead of the relay stamp.

A wildcard (*) can be used instead of a server name in order to apply a set of relays to all servers. Only use this if you have server_names defined, with a small set of servers that don't overlap with relays.

Caveats

Relaying is currently incompatible with cisco, as this resolver doesn't implement DNSCrypt v2 yet, and doesn't support large queries.

For each server, a random relay from the set is chosen when the proxy starts, and the same relay will be used until the proxy is restarted. Relay randomization and failover will be implemented in future versions.

Protocol

The Anonymized DNSCrypt extension was designed to only relay encrypted DNS data. As a result, its overhead is very low, including on relays that don't need to perform any additional encryption.

Like DNSCrypt, this is an open specification: Anonymized DNSCrypt specification

Encrypted DNS Server can be used to quickly set up a relay on a Linux or BSD machine.

All combinations seem to be "incompatible with anonymization"

Anonymization requires the ability to send large (fragmented) UDP packets.

If you are seeing the incompatible with anonymization message even with compatible resolvers, it is likely that your router was mistakenly configured to block UDP fragments. You need to disable this option, that breaks the UDP protocol without any security benefits.

Using servers and relays operated by different entities

While all available DNSCrypt servers are in use (by default server_names option is commented out) with anonymization ("DNS Anonymization is only compatible with servers supporting the DNSCrypt protocol") it's possible that such server will use its own relay (e.g. bcn-dnscrypt server and anon-bcn relay) if - for example - User will choose this relay for anonymization. That's what should be avoided.

There is an important statement made above: "You probably want relays and the servers they relay to, to be operated by different entities (...)" (please see "Configuring anoymized DNS in dnscrypt-proxy" subsection). It's a key information for a privacy oriented Users. So, how above goal can be achieved using Anonymized DNS?

It's relatively simple, because of disabled_server_names option - found in dnscrypt-proxy.toml file - used to define, declare server names to avoid, even if they match all criteria (vide require_{dnssec,log,nofilter} options).

CONFIGURATION:

At the beginning, User has to choose - for example - two servers, which also offer anonymized relays. Let's take for example: cs-fr and bcn-dnscrypt. Because both servers will not be used anyway, these Anonymized DNS relays can be used: anon-cs-fr and anon-bcn. (NOTE: if it's about relays number, it seems, that two is a good choice; probably three is the biggest, suggested value; more info needed!).

Below is an example configuration with exceptions from dnscrypt-proxy.toml file. Please note, that DoH protocol is disabled so only DNSCrypt-capable servers are used.

# Servers from the "public-resolvers" source.
# (NOTE: this option must be commented out!)
# -------------------------------------------
#server_names = ['scaleway-fr', 'google', 'yandex', 'cloudflare']

# Server names to avoid even if
# they match all criteria.
# -----------------------------
disabled_server_names = ['cs-fr', 'bcn-dnscrypt']

# Require servers.
# ----------------
dnscrypt_servers = true
doh_servers = false

# Load-balancing strategy (determine which
# server will be selected for every query).
# -----------------------------------------
lb_strategy = 'random'

# Anonymized DNS section.
# -----------------------
skip_incompatible = true

[anonymized_dns]

routes = [
   { server_name='*', via=['anon-cs-fr', 'anon-bcn'] }
]

The most important thing: with above configuration, there is no possibility to use server and relay operated by the same entities, which is very important from a privacy point of view. Also, skip_incompatible option responsible for: "skip resolvers incompatible with anonymization instead of using them directly" (please see example-dnscrypt-proxy.toml file) is set to true.

Additionaly, load balancing strategy (please see lb_strategy description) has been set to random - by default, it is commented out (DNSCrypt-Proxy ver. 2.0.44). It's a good solution/strategy, due to the large number of DNSCrypt servers available and because they will be choosed randomly. Every DNS query, will go thru one of the many different resolvers. So, it also improves privacy, because DNS queries are spread across multiple providers/servers (which may provide additional protection).

After applying above changes, restart DNSCrypt-Proxy service and check log and/or status - there should be the following information:

[NOTICE] Anonymized DNS: routing everything via [anon-cs-fr anon-bcn]

Of course, beyond any doubt, there are some facts to consider. For example, User has to decide whether it's better to spread DNS queries between multiple different servers, however often with no informations about its DNS traffic situation etc. If such traffic is relative small, then it's harder to, let say, "hide" in queries stream. Summarizing: with a resolver, that doesn't get a lot of traffic, Users can lost a lot of anonymity, privacy.

Generally, such providers may provide smaller privacy/protection, because of less traffic to "hide in". If, for example, User is the only user of such server then DNS queries are practically obvious for so-called "observer". On the other hand, using multiple providers means that no single provider can see all DNS traffic (none of them should have entire DNS activity).

The situation seems to be completely different in the case of the bigger DNS servers/providers where User can "hide" more "preciselly". But now, here comes the question: do you trust them? Anyway, there are so many aspects that require closer look etc., but it's not the intention of this post.

(The described configuration has been tested and verified.)

Clone this wiki locally