Here are notes for setting up DNSCrypt on Arch Linux, using pdnsd as a DNS cache, assuming the use of NetworkManager. I needed it one day since the network I was using blocked traffic to external DNS servers (parental controls), and the DNS server provided had an outdated entry for hmmt.co. (My dad then pointed out to me I could have just hard-coded the necessary IP address in /etc/hosts
, oops.)
For the whole process, useful commands to test with are:
nslookup hmmt.co
will tell you the IP used and the server from which it came.dig www.hmmt.co
gives much more detailed information to this effect. (Frombind-tools
.)dig @127.0.0.1 www.hmmt.co
lets you query a specific DNS server (in this case 127.0.0.1).drill @127.0.0.1 www.hmmt.co
behaves similarly.
First, pacman -S pdnsd dnscrypt-proxy
(with sudo
ostensibly, but I’ll leave that out here and henceforth).
Run systemctl edit dnscrypt-proxy.socket
and fill in override.conf
with
[Socket]
ListenStream=
ListenDatagram=
ListenStream=127.0.0.1:40
ListenDatagram=127.0.0.1:40
Optionally, one can also specify which server which DNS serve to use with systemctl edit dnscrypt-proxy.service
. For example for cs-uswest I write
[Service]
ExecStart=
ExecStart=/usr/bin/dnscrypt-proxy \
-R cs-uswest
The empty ExecStart=
is necessary, since otherwise systemctl
will complain about multiple ExecStart commands.
This thus configures dnscrypt-proxy
to listen on 127.0.0.1, port 40.
Now we configure pdnsd
to listen on port 53 (default) for cache, and relay cache misses to dnscrypt-proxy
. This is accomplished by using the following for /etc/pdnsd.conf
:
global {
perm_cache = 1024;
cache_dir = "/var/cache/pdnsd";
run_as = "pdnsd";
server_ip = 127.0.0.1;
status_ctl = on;
query_method = udp_tcp;
min_ttl = 15m; # Retain cached entries at least 15 minutes.
max_ttl = 1w; # One week.
timeout = 10; # Global timeout option (10 seconds).
neg_domain_pol = on;
udpbufsize = 1024; # Upper limit on the size of UDP messages.
}
server {
label = "dnscrypt-proxy";
ip = 127.0.0.1;
port = 40;
timeout = 4;
proxy_only = on;
}
source {
owner = localhost;
file = "/etc/hosts";
}
Now it remains to change the DNS server from whatever default is used into 127.0.0.1. For NetworkManager users, it is necessary to edit /etc/NetworkManager/NetworkManager.conf
to prevent it from overriding this file:
[main]
...
dns=none
This will cause resolv.conf
to be written as an empty file by NetworkManager: in this case, the default 127.0.0.1 is used as the nameserver, which is what we want.
Needless to say, one finishes with
systemctl enable dnscrypt-proxy
systemctl start dnscrypt-proxy
systemctl enable pdnsd
systemctl start pdnsd