Ending DNS Hijacking with DNSCrypt
I was at a Marriot hotel last week with my family and I noticed that they were doing DNS hijacking and redirecting all my DNS requests to their own servers.
It would not be a big deal, if wasn't for the fact that I had OpenDNS Family Filter setup on the laptop that the kids were using — and it wasn't working due to the DNS hijacking.
DNSCrypt to the rescue
At first, it was frustrating to see that the filters I had manually configured were not working, but I decided to take this opportunity and take my DNS privacy seriously by leveraging DNSCrypt in there.
If you are not familiar with DNSCrypt, it is a new protocol by Frank Denis and Yecheng Fu, that encrypts and authenticates all DNS traffic — Exactly what I needed to prevent any hotel or ISP from hijacking my connections.
Configuring DNSCrypt
The kids laptop are running the latest version of Ubuntu — 17.10, so in this document I will show the steps I took to get DNSCrypt configured and running there. I will be using the awesome DNSCrypt-proxy v2 by Frank Denis.
First, open your terminal and download and untar latest DNSCrypt-proxy version:
$ cd /opt
$ tar -zxvf dnscrypt-proxy-linux_x86_64–2.0.7.tar.gz
$ mv linux-x86_64 dnscrypt
$ cd dnscrypt
That will download the set the basic files for DNSCrypt-proxy inside /opt/dnscrypt. Once that part is done, you need to run some commands as root (using sudo) to install DNSCrypt:
$ mv example-dnscrypt-proxy.toml dnscrypt-proxy.toml
$ sudo ./dnscrypt-proxy -service install
[2018–03–18 19:00:10] [NOTICE] Source [https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md] loaded
[2018–03–18 19:00:10] [NOTICE] dnscrypt-proxy 2.0.7$ sudo ./dnscrypt-proxy -service start
[2018–03–18 19:00:20] [NOTICE] Source [https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md] loaded
[2018–03–18 19:00:20] [NOTICE] dnscrypt-proxy 2.0.7
[2018–03–18 19:00:20] [NOTICE] Service started
Having done that part, you should have DNSCrypt-proxy running at 127.0.0.1 port 53. You can verify it is working by doing:
$ dig -t A google.com @127.0.0.1
; <<>> DiG 9.10.3-P4-Ubuntu <<>> -t A google.com @127.0.0.1
;google.com. IN A
google.com. 527 IN A 172.217.194.101$ sudo netstat -uanep |grep dnscryp
udp 0 0 127.0.0.1:53 0.0.0.0:* 0 22777 2014/dnscrypt-proxy
All good, but now we need to configure our system to use DNSCrypt-proxy instead of the default resolver at 127.0.0.53 (from systemd). You can do it manually for testing by modifying the /etc/resolv.conf file:
$ echo “nameserver 127.0.0.1” > /etc/resolv.conf
And test that your DNS still works. However, that won't last after a reboot. Ubuntu have messed up with DNS since they added the systemd-resolved, making it more complicated than what it should be. I tried multiple options to stick to only 127.0.0.1 (where dnscrypt-proxy is running), but none of them would stick — or it would be rotated with the DNS server received via DHCP.
At the end, I actually disabled systemd-resolve to avoid any more issues and set 127.0.0.1 as the default nameserver:
$ systemctl stop systemd-resolved
$ systemctl disable systemd-resolved
$ echo “dns-nameservers 127.0.0.1” >> /etc/network/interfaces
That did the tricky and stuck between restarts. If anyone has a better way to fully override the Name server on Ubuntu 17.10, let me know.
Parental Control with DNSCrypt
The final part was to configure OpenDNS with DNSCrypt-proxy. It took me a while to realize that it is called "cisco-familyshield" in the DNSCrypt configuration (not opendns), so that alone will save you some time there.
Unfortunately, OpenDNS and DNSCrypt did not work as expected. I kept getting a timeout error, and after some troubleshooting it seems that their DNSCrypt port was down from the hotel network.
Because of that, I decided to try some other providers. Both AdGuard, Comodo and CleanBrowsing support DNSCrypt, so I tried all of them:
Mar 16 20:01:22 dnscrypt-proxy[1167]: [2018–03–18 20:01:22] [NOTICE] [adguard-dns-family] OK (crypto v1) — rtt: 204ms
Mar 16 20:01:22 dnscrypt-proxy[1167]: [2018–03–18 20:01:22] [NOTICE] [cleanbrowsing-family] OK (crypto v1) — rtt: 12ms
Mar 16 20:01:22 dnscrypt-proxy[1167]: [2018–03–18 20:01:22] [NOTICE] [comodo-02] OK (crypto v1) — rtt: 58ms
Mar 16 20:01:22 dnscrypt-proxy[1167]: [2018–03–18 20:01:22] [NOTICE] Server with the lowest initial latency: cleanbrowsing-family (rtt: 12ms)
For some reason, having all 3 together also did not work as well. I still have to research what happened, but it seems that on a NXDOMAIN, it was trying a secondary server. Plus, the comodo-02 wasn't restricting adult content via DNSCrypt — still have to understand why.
To avoid wasting more time, I decided to stick with just 1. I chose CleanBrowsing as it had the better performance of the 3 and it fared very well on my comparison between providers.
The DNSCrypt-proxy configuration is very simpple and you can set a specific provider by adding a "server_names" in the /opt/dnscrypt/dnscrypt-proxy.toml configuration file:
server_names = [‘cleanbrowsing-family’]
Once that is done, you need to restart DNSCrypt and verify it is working by trying to do a DNS lookup of an adult site:
$ /opt/dnscrypt/dnscrypt-proxy -service restart
$ dig por[n[hub dot com
por[n]hub.com. 22 IN SOA cleanbrowsing.rpz.noc.org. accesspolicy.rpz.noc.org. 1 7200 900 1209600 86400
;; Query time: 18 msec
And that's pretty much it. It feels harder than what it should have been, specially due to the issues with the Ubuntu DNS resolver. I envy the time back in the day when only editing /etc/resolv.conf would have been enough.
Thanks Marriot for your DNS hijacking. You made me paranoid enough to learn and setup DNSCrypt-proxy.
