2020 continues the big push for DNS over HTTPS (DoH) and DNS over TLS (DoT), two methods of improving the security and privacy of customers of Internet Service Providers (ISP) by providing additional layer of information obscurity, making your ISP’s job on sniffing and filtering your internet activities just a wee bit harder. You can try to use it to circumcise your ISP’s shady behavior in spoofing and hijacking your DNS queries for displaying ads, blocking access to their business rivals. Hence a disclaimer: DoH and DoT is not a replacement of VPN tunnel. Your ISP knows where you’re going, they just have to try a bit harder to discern what is hosted over a bunch of IPs you’re accessing. The emergence of cloud-based hostings, CDNs and load balancers and firewalls helps the case, as ISPs can’t easily create access filter based on IP addresses as it might block legitimate traffics. Still, if you want to totally obscure your internet activities from your ISP, VPN tunnel is your best bet.
You can directly configure the use of DoH on the recent version of most used desktop internet browser, such as Firefox, or Chrome. Unfortunately, DoH is also supported on Android, starting on version 9
Unfortunately, DoH support on the desktop Operating System side is a bit murky. While the preview version Microsoft Windows 10 has support for DoH baked in, and should see mainstream release in the coming months, Linux and MacOS users will have to settle for 3rd party solution, such as DNSCrypt. This would mean that you will have to configure DoH per-application basis, or in case of linux and MacOS, will require DNSCrypt installation on every single devices on your household.
You can however, create a DoH client that you can task to talk to DoH server, and have the rest of the appliances in your home talk do the DNS query to that particular DoH client. This article will focus on Cloudflared, an opensource DoH client created by Cloudflare, as the backend that will handle the DoH query to Cloudflare
What you’d need is a PC, and old one, preferably with an X86-64 CPU or a Raspberry Pi 3 or 4. Make sure to assign a static IP address to the box.
Go here for downloading cloudflared installation package as well as the installation instruction that suits your environment, mine is an Intel Cherry trail-based mini PC with Ubuntu 20.04 installed. If you’re using a SystemD based linux distribution, It’s a good idea to create a SystemD unit file for cloudflared by doing:
sudo nano /etc/systemd/system/cloudflared.service
Jot down:
[Unit] Description=DNS over HTTPS (DoH) proxy client Wants=network-online.target nss-lookup.target Before=nss-lookup.target [Service] AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE DynamicUser=yes ExecStart=/usr/local/bin/cloudflared proxy-dns [Install] WantedBy=multi-user.target
Save and close the file. To start Cloudflared, do:
sudo systemctl start cloudflared
You should now have cloudflared service waiting for queries at localhost port 53.
surfer@ruby:~$ sudo netstat -plnt Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 129900/cloudflared tcp 0 0 127.0.0.1:43445 0.0.0.0:* LISTEN 129900/cloudflared tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 81451/systemd-resol tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 80975/sshd: /usr/sb tcp6 0 0 :::22 :::* LISTEN 80975/sshd: /usr/sb
Test it out with a domain that you suspected being filtered by your ISP. Here’s reddit through 1.1.1.1 without DoH:
surfer@M5-1910:~$ dig @1.1.1.1 vimeo.com ; <<>> DiG 9.16.1-Ubuntu <<>> @1.1.1.1 vimeo.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49377 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;reddit.com. IN A ;; ANSWER SECTION: reddit.com. 900 IN CNAME internetpositif3.firstmedia.com. internetpositif3.firstmedia.com. 3600 IN A 202.137.1.74 ;; AUTHORITY SECTION: trustpositifkominfo. 900 IN SOA localhost. aduankonten.mail.kominfo.go.id. 2020123102 1000 1000 2592000 900 ;; Query time: 24 msec ;; SERVER: 1.1.1.1#53(1.1.1.1) ;; WHEN: Jum Jan 01 01:28:12 WIB 2021 ;; MSG SIZE rcvd: 194
As you can see, my query was answered and resolved by my ISP, despite the query being directed specifically to Cloudflare’s 1.1.1.1. Here’s the query answered by through cloudflared:
surfer@ruby:~$ sudo dig @127.0.0.1 vimeo.com ; <<>> DiG 9.16.1-Ubuntu <<>> @127.0.0.1 vimeo.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22245 ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;vimeo.com. IN A ;; ANSWER SECTION: vimeo.com. 169 IN A 151.101.192.217 vimeo.com. 169 IN A 151.101.64.217 vimeo.com. 169 IN A 151.101.0.217 vimeo.com. 169 IN A 151.101.128.217 ;; Query time: 372 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Jan 01 07:06:50 WIB 2021 ;; MSG SIZE rcvd: 138
The next part of the setup is to create a local, regular DNS server that will receive and forward DNS queries to cloudflared. Just like my previous post on DNSCrypt, I’ll be using Bind, which is easily installed by doing:
surfer@ruby:~$ sudo apt install bind9
Open up the configuration file:
sudo nano /etc/bind/named.conf.options
Here’s how mine looks:
acl goodclients { 192.168.19.0/24; localhost; }; options { directory "/var/cache/bind"; // If there is a firewall between you and nameservers you want // to talk to, you may need to fix the firewall to allow multiple // ports to talk. See http://www.kb.cert.org/vuls/id/800113 // If your ISP provided one or more IP addresses for stable // nameservers, you probably want to use them as forwarders. // Uncomment the following block, and insert the addresses replacing // the all-0's placeholder. allow-query { goodclients; }; forwarders { 127.0.0.1; }; // forwarders { // 0.0.0.0; // }; //======================================================================== // If BIND logs error messages about the root key being expired, // you will need to update your keys. See https://www.isc.org/bind-keys //======================================================================== dnssec-enable yes; dnssec-validation yes; auth-nxdomain no; # conform to RFC1035 listen-on-v6 { any; }; };
Note that we are setting 127.0.0.1 as the forwarder. Replace 192.168.19.0/24 with your home network subnet, then start Bind with:
sudo systemctl start bind
You should now have Bind active on your default interface
surfer@ruby:~$ sudo netstat -plnt Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 129900/cloudflared tcp 0 0 127.0.0.1:43445 0.0.0.0:* LISTEN 129900/cloudflared tcp 0 0 192.168.19.6:53 0.0.0.0:* LISTEN 129768/named tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 81451/systemd-resol tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 80975/sshd: /usr/sb tcp 0 0 127.0.0.1:953 0.0.0.0:* LISTEN 129768/named tcp6 0 0 fe80::2ce:39ff:fecd::53 :::* LISTEN 129768/named tcp6 0 0 ::1:53 :::* LISTEN 129768/named tcp6 0 0 :::22 :::* LISTEN 80975/sshd: /usr/sb tcp6 0 0 ::1:953 :::* LISTEN 129768/named
Now hop on to one of your workstation and test out your newly christened local DNS server:
surfer@M5-1910:~$ dig @192.168.10.150 reddit.com ; <<>> DiG 9.16.1-Ubuntu <<>> reddit.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35810 ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;reddit.com. IN A ;; ANSWER SECTION: reddit.com. 85 IN A 151.101.193.140 reddit.com. 85 IN A 151.101.65.140 reddit.com. 85 IN A 151.101.1.140 reddit.com. 85 IN A 151.101.129.140 ;; Query time: 0 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) ;; WHEN: Sab Jan 02 08:54:38 WIB 2021 ;; MSG SIZE rcvd: 103
The last step would be reconfiguring the DHCP server setting on your router so that the rest of the devices on your home network uses the new local DNS server. Mine looks like this:
Point the DNS server to IP address of the box and we are done.