dns/dnscrypt-proxy is an awesome piece of of software that encrypts your DNS traffic using elliptic-curve cryptography. It sends and receives all external queries over port 443 instead of the unencrypted port 53 that is vulnerable to many attack methods.
dnscrypt-proxy is not a DNS cache however, which means incoming queries will not be cached and every single DNS lookup will require a re-query to the upstream resolver. Thus, the recommended way of running dnscrypt-proxy is to place it in front of a local DNS cache. For this we will use dns/unbound.
Mind you, dns/unbound exists both in the ports tree and as a part of base world. It's most probably already on your system unless you have defined WITHOUT_UNBOUND= yes in /etc/src.conf for running your own buildworld. Ports and world usually have the same unbound version so this is mostly a trivial matter, with the exception being that unbound from world uses /var/unbound/, while unbound from ports uses /usr/local/etc/unbound/. My personal opinion is that /var/unbound/ is the more correct location because DNSSEC does key modifications and file ownership is unbound:unbound.
Installation:
Start your DNS jail (I am skipping setup, administration, etc. of jails as this is a separate subject) and install needed packages:
Download Some Files:
Configure unbound:
My DNS jail's IP is 192.168.2.97/32 and I have assigned the 192.168.2.96/28 subnet to all the jails I am running on the system. This information is so that you can make sense of the below configuration file.
Other optional settings:
Initial DNSSEC Test (not using dnscrypt-proxy yet):
Modify dns-jail/etc/rc.conf as
Then,
Go to the bottom of your var/unbound/unbound.conF, disable the "Google Public DNS" entry and enable the line below that (dnscrypt-proxy). Be aware that:
Final Considerations:
Now go and figure out how to run dnscrypt-proxy on your mobile devices.
dnscrypt-proxy is not a DNS cache however, which means incoming queries will not be cached and every single DNS lookup will require a re-query to the upstream resolver. Thus, the recommended way of running dnscrypt-proxy is to place it in front of a local DNS cache. For this we will use dns/unbound.
Mind you, dns/unbound exists both in the ports tree and as a part of base world. It's most probably already on your system unless you have defined WITHOUT_UNBOUND= yes in /etc/src.conf for running your own buildworld. Ports and world usually have the same unbound version so this is mostly a trivial matter, with the exception being that unbound from world uses /var/unbound/, while unbound from ports uses /usr/local/etc/unbound/. My personal opinion is that /var/unbound/ is the more correct location because DNSSEC does key modifications and file ownership is unbound:unbound.
Installation:
Start your DNS jail (I am skipping setup, administration, etc. of jails as this is a separate subject) and install needed packages:
# pkg -j dns-jail install dns/dnscrypt-proxy
. This should pull in: ports-mgmt/pkg, security/libsodium and dns/dnscrypt-proxy. Repeat the above for dns/unbound if you have decided to use this from ports. At this stage, your jail's /etc/resolv.conf should use your normal DNS IP as nameserver.Download Some Files:
- Rename this to /var/unbound/root.hints: ftp://FTP.INTERNIC.NET/domain/named.cache.
- Use this to select which resolver you will use and also check which resolvers have DNSSEC enabled: https://github.com/jedisct1/dnscrypt-proxy/blob/master/dnscrypt-resolvers.csv.
- For DNSSEC validation, you must obtain an initial trust anchor. The unbound-anchor(8)() tool does this for you.
# jexec dns-jail unbound-anchor -a "/var/unbound/root.key"
. This should place the initial anchor in the jail's var/unbound folder.
Configure unbound:
My DNS jail's IP is 192.168.2.97/32 and I have assigned the 192.168.2.96/28 subnet to all the jails I am running on the system. This information is so that you can make sense of the below configuration file.
Code:
server:
logfile: "/var/log/unbound.log"
verbosity: 1
chroot: ""
pidfile: "/var/run/unbound.pid"
port: 53 # port to answer queries from
do-ip4: yes # Enable IPv4, "yes" or "no".
do-ip6: no # Enable IPv6, "yes" or "no".
do-udp: yes # Enable UDP, "yes" or "no".
do-tcp: yes
hide-identity: yes
hide-version: yes
rrset-roundrobin: yes
minimal-responses: no
use-caps-for-id: yes
cache-min-ttl: 60
prefetch: yes
prefetch-key: yes
num-threads: 1 # 1 is enough for not heavy loaded server
# client ips that are allowed to query to this server.
access-control: 192.168.1.0/24 allow
access-control: 192.168.2.96/28 allow
access-control: 127.0.0.0/24 allow
# Enforce privacy of these addresses.
private-address: 192.168.1.0/24
private-address: 192.168.2.96/28
root-hints: "/var/unbound/root.hints"
# You need these to turn on DNSSEC validation
auto-trust-anchor-file: "/var/unbound/root.key"
module-config: "validator iterator"
# You need this as no for dnscrypt-proxy to work
do-not-query-localhost: no
# Yoyo.org anti-ad server listing with script in dns/root/ad_servers.sh
include: "/var/unbound/ad_servers"
forward-zone:
name: "."
forward-addr: 8.8.8.8 # Google Public DNS
# forward-addr: 192.168.2.97@9053 # dnscrypt-proxy
Other optional settings:
Code:
# enable remote-control
remote-control:
control-enable: yes
control-interface: 127.0.0.1
# Optional Hardening knobs:
harden-glue: yes
harden-dnssec-stripped: yes
harden-short-bufsize: yes
harden-large-queries: yes
Initial DNSSEC Test (not using dnscrypt-proxy yet):
Modify dns-jail/etc/rc.conf as
Code:
local_unbound_enable="YES"
## (if from ports, use) unbound_enable="YES"
dnscrypt_proxy_enable="YES"
dnscrypt_proxy_resolver="dnscrypt.eu-nl"
dnscrypt_proxy_flags="-a 127.0.0.1:9053"
# echo "nameserver 127.0.0.1" > dns-jail/etc/resolv.conf
(Set the jail's nameserver.)# echo "nameserver 192.168.2.97" > /etc/resolv.conf
(Set the host's nameserver.)- Finally,
$ drill -D 00f.net
should give you a pretty output like below, confirming a functioning DNSSEC setup.
Code:;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 36553 ;; flags: qr rd ra ad ; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 0 ;; QUESTION SECTION: ;; 00f.net. IN A ;; ANSWER SECTION: 00f.net. 28729 IN A 91.121.49.42 00f.net. 28729 IN RRSIG A 7 2 43200 20141129042510 20141101042510 36242 00f.net. KlyemNGKMi5qIUEnUw/BsJ02W2vMjb5gb/LNOy/3s9vF4NEm4SR5cIG0xjKr/0mNCYcp3+roPaWS6lNRu2WAfZxlXm7VLoGO4guQSLD+nlkFnIqMPZAknIYnC7eWW5eaxOVAhgpdKqDfSvSX/4QZ+ddenCkYVrX4B729QhV4jRE=
Go to the bottom of your var/unbound/unbound.conF, disable the "Google Public DNS" entry and enable the line below that (dnscrypt-proxy). Be aware that:
- You can change the port that dnscrypt-proxy listens on (in this case 9053) as long as you don't set it to 53 (which is what unbound is listening on).
- In unbound.conf, you must set "forward-addr as the jail's IP, because setting it as 127.0.0.1@9053" does not work.
- When this HowTo was written, dnscrypt-proxy had a problem starting up as a service from etc/rc.conf when DNSSEC was enabled. This now seems solved, and specifying the dnscrypt_proxy_resolver flag separately enables the jail to start resolving upon startup.
From the host,
$ drill -D 00f.net
should now give you same as previously.Final Considerations:
- While dnscrypt-proxy will encrypt all traffic through port 443, port 53 is still used by unbound to fetch and refresh the trust-anchor file.
- Set the nameserver in all the your jails' etc/resolv.conf to the DNS jail's IP. Alternatively you may choose to force redirection of all port 53 traffic to the DNS jail through settings in pf.conf.
Now go and figure out how to run dnscrypt-proxy on your mobile devices.
Last edited: