-
Notifications
You must be signed in to change notification settings - Fork 1k
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.
Instead of directly reaching a server, that is one of the public resolvers, 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 DNS recursive resolver, the only server that can decrypt it.
The DNS resolver 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 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.
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.
A wildcard can also be used as a relay (via=["*"]
). In that case, the proxy will automatically choose the relays, selecting them by trying to avoid relays and servers to be on the same network.
Relaying is currently incompatible with cisco
, as this resolver doesn't correctly implement DNSCrypt yet, and doesn't support large queries.
For each server, a random relay from the set is chosen when servers are ranked, and then holds for a period. The cycle period is cert_refresh_delay. Per request relay randomization is too hard to measure the route quality, that may break the lb_strategy
quality.
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.
Anonymization requires the ability to send large (fragmented) UDP packets.
If you are seeing the incompatible with anonymization
or couldn't be reached anonymously
messages 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 a relay operated by the same entity as the server it relays to, would defeat the purpose of anonymization. Below, there is an explanation about how to avoid such a situation.
When using wildcards, dnscrypt-proxy
tries to choose relays so that they are not on the same network as the servers they relay to. However, this is very likely to be suboptimal from a performance and privacy perspective. A manual selection is always preferred.
You may also leverage disabled_server_names
to prevent servers operated by entities used by relays from being used. Here is an illustration of such configuration.
In the following example, we have two servers, cs-fr
and bcn-dnscrypt
, that can also act as relays. We disable them as servers, and enable them as relays.
The relevant parts of the dnscrypt-proxy.toml
file would be as follows:
# Here, `server_names` is empty or commented out, so that all servers
# matching filters can be used
#server_names = ['scaleway-fr', 'google', 'yandex', 'cloudflare']
# Server names to disable, because we use them as relays
disabled_server_names = ['cs-fr', 'bcn-dnscrypt']
# Filters
dnscrypt_servers = true
doh_servers = false
# Anonymized DNS section.
# -----------------------
[anonymized_dns]
routes = [
{ server_name='*', via=['anon-cs-fr', 'anon-bcn'] }
]
skip_incompatible = true
With the above configuration, there is no possibility to use a server and a relay operated by the same entities, which is very important from a privacy point of view. Also, the skip_incompatible
option skips resolvers incompatible with anonymization instead of using them directly (cf. the example-dnscrypt-proxy.toml
file) when set to true
.
After applying above changes, restart the dnscrypt-proxy
service and check the logs and/or status - there should be the following information:
[NOTICE] Anonymized DNS: routing everything via [anon-cs-fr anon-bcn]
In somecases if you want to run dnscrypt-proxy as a non-root user you'll get the error "[FATAL] listen udp 0.0.0.0:53: bind: permission denied"
to solve this problem you can run the following command and allow dnscrypt to have access to a low level port :
sudo setcap cap_net_bind_service=+ep $(which dnscrypt-proxy)
- Home
- Installation
- Configuration
- Checking that your DNS traffic is encrypted
- Automatic Updates
- Server sources
- Combining blocklists
- Public Blocklist and other configuration files
- Building from source
- Run your own DNSCrypt server in under 10 minutes
- DNS stamps specifications
- Windows Tips
- dnscrypt-proxy in the media
- Planned Features