Exactly a month ago I posted “Taking Control”. This is part One of that guide. If you haven’t read the introductory post I highly recommend you do. It will give you an excellent reason why one would go through all this work.

Big Scary Disclaimer: Information contained in this guide may be lacking or incomplete. You should not base your decisions solely on the information contained herein. You should not attempt to perform ANY of the suggestions in this guide if you do not have a good understanding of how the Internet works. While this guide contains known working configurations as of the date of publication, you can very easily break your Internet connection or worse, open your devices up to attack and abuse if proper security measures are not taken and said services and configurations are not kept up-to-date. Sample firewall rules may or may not be included and should not be used by themselves but modified and appended to your existing firewall configuration to work for your specific use cases. You also should review over your ISP’s acceptable use policy and other applicable terms and conditions you agreed to when you signed up for your Internet service before attempting any of the suggestions in this guide. Depending on your situation, you could face termination of service if your ISP prohibits and punishes subscribers that engage in circumventing their network management techniques, or operating services not permitted under Acceptable Use and Terms of Service policies/agreements . In some jurisdictions it may be illegal for you to use any of the methods contained in this guide. If you are unsure, please review your local, state, and federal laws or speak with a lawyer who may be able to advise you further. By continuing to follow this guide you take full responsibility for the consequences that may arise through the use of these tips. I may not be held liable for any damages that occur through the use of this guide.

So one of the first questions you’ll run into is “Where do I start?” From my personal experience I like to start at the very bottom of the stack and go up. Like building a house, it’s important to have a solid foundation on which to build on. If your foundation is full of cracks and holes then no matter how impressive your house is, it’s going to come crumbling down.


One of the key components of the net, The Domain Name System or D.N.S. for short is responsible for converting easy to remember host names into IP addresses that allow your computer to communicate with other computers on the Internet. By default, residential and SOHO routers go out to your ISP which runs it’s own DNS resolution services. A majority of the time if your having problems connecting on the Internet for people to recommend changing these default values since ISP DNS servers have a reputation for being unreliable, slow, and in extreme cases can be used to block, censor, and track your every move on the web in part because these services operate in plain text. This means that without having to do any extra work your ISP can easily see your requests for Google, Youtube, and yes.. your preferred porn site.

Cloudflare and quite recently Google have begun the task of implementing encryption on top of the protocol but are facing extreme opposition from Government and ISP entities who rely on DNS sniffing to censor and otherwise monitor their users. Cloudflare offers DNS over HTTPS (DoH) which simply moves the resolution of hostnames off of port 53 and onto the web where TLS encryption is able to encrypt and protect DNS queries from unwanted monitoring and modification as that information is routed through the Internet and back to your computer. For the average user these services are perfect for speeding up a slow Internet connection.

On the other hand, you are now giving Google and Cloudflare the ability to track and monitor you. Google claims to flush all but the ISP and Location information from DNS queries they receive on their public resolvers within 24 to 48 hours and Cloudflare claims to delete all records except for telemetry data (eg: total number of queries, type, etc) within 24 hours. While this is significantly better than most ISPs DNS policies who can retain your DNS information for undisclosed amounts of time. For example: Charter Spectrum states that they maintain collected information for as long as you are a customer of their service which they may share with 3rd parties in anonymised format.
For some customers this could mean DNS information from the day you moved into your house 10 years ago. Even if you used a public resolver like Google or Cloudflare, these services have historically operated in plain text for your ISP to see and collect for decades. Yikes! Other ISPs may use similar wording in their privacy policies too so it’s a good idea to lookup your specific ISP’s policies to estimate just how much information these companies might have about you.

In order to completely shield yourself from unwanted monitoring you can opt to run your own DNS resolution service ether locally on your network or through your own servers out on the Internet, more on that later. Since the whole point is to evade the prying eyes of our ISP it’s important that this DNS server does not accidentally leak our DNS queries out on the Internet where our ISP may see it. It’s very important that we choose an option that best fits our goals. There are three methods that I have used in the past that have worked for me.

Use a Secured Resolver

If having really fast DNS resolutions is your goal, you are going to want to choose a provider who has established DNS servers that provides at least one of the newer DNS encrypted methods. Cloudflare offers their own DNS-Over-HTTPS tunnel through their Argo Tunnel service. This gives you an encrypted tunnel into the closest Cloudflare data center to you where all your DNS resolutions will be sent over HTTPS. As of 5/20/2019 I have not made use of any of the DoT clients available and so I cannot give a recommendation for any of them. By using Cloudflare I was able to see DNS resolutions times fall to single digit values of 8 ms and lower from servers inside data centers, residential DNS resolution times fell down towards ~28 ms. Cloudflare offers a very easy to follow guide for installing their DoH Cloudflared client which can be found HERE. One thing I will recommend you do is to append to your startup command is the –address command switch with the device’s local network ip address.

This allows your device to listen for DNS requests on the local network and can point every device on your network to the system which will forward all queries over HTTPS. Once you have the client installed and running you should configure DHCP on your router to tell all your devices to use the local IP address of the device running the cloudflared service instead of manually having to enter in that information on every device in your house.

Using Root Hints

If you don’t wish to rely on public dns resolvers, the next step up would be to configure your DNS servers to have a root hint. The root hints allow you to resolve any domain by using the Root Internet servers. Before going this route however, it is important to note that if you are running the DNS server out of your house, this will not be able to hide your DNS queries from your ISP since the root servers are not configured to make use of encrypted DNS responses so all resolutions will be made in the clear. This option works best if you have a reasonable level of trust with your ISP or you have a server sitting in a data center that respects your privacy and doesn’t store DNS logs indefinitely.

This method of DNS resolution is also, usually, the slowest because your server is having to recursively go through the entire DNS chain to find the authoritative DNS server for the domain you are trying to resolve.

An easy way to think about it: Say you wanted to talk to someone but don’t know their phone number and we don’t know their address. The Phone Book would be the root DNS servers. For the sake of example, we look up the phone number of a mutual friend using their address in the phone book, call them, and ask for the other person’s phone number. They would act as the authorative dns server for the other person.

The whole point of this example is to exaggerate the time it takes to do a full recursive look up. Because we have to do multiple queries, the time it takes to resolve one address raises significantly and depending on the latency between you and the root server you could see some queries time out.


Software: Bind9, Ubuntu Server LTS (or whatever distro you are comfortable with)

First thing you are going to want to do is update the root hints file that is typically supplied by the package maintainer. On Ubuntu 18.04 LTS I’ve noticed that this file does not get updated and is lacking a few changes. Inspecting mine shows a last modified date of February 17, 2016 which is now over 3 years old! While resolutions still work, it’s something that should concern you due to the importance of the service.

Since the root hints file does not change all that frequently, you don’t need to worry about updating it all that frequently but I would suggest doing it at least once a month or every 6 months just to keep things pointing properly.

For quickly updating the file you can use the script below to update the db.root file in bind.

# /root/.scripts/updateRootHints.sh


# Fetch latest Root Hints from Internic
/usr/bin/wget http://www.internic.net/domain/named.root -O /etc/bind/db.root

# Restart the DNS server so that the new root hints can take effect
/bin/systemctl restart bind9

Bind by default already has an entry in named.conf.default-zones for the “.” zone as a root hint pointing to db.root so you should be able to simply restart bind and the new root hints will take effect immediately.

Using Root Zone

Instead of going back to the root servers in order to resolve ip addresses, you can maintain your own local copy which allows your DNS server to contact the authoritative servers without having to recursively query the root server for this information. Your server can now make 1 DNS query to answer dns requests, just like if we were using a public dns resolver. The time it takes for your system to contact the authoritative servers will be heavily dependent on what sites your resolving and who they use to provide their lookup services from. If your server is in the United States and the DNS services for a domain is in China, you should expect to see some sort of delay.

Just like using the Root hints method, this does not prevent your ISP from seeing your queries since you still need to resolve the record from the authoritative domain servers, just the information on how to get to them is closer. This method also requires the most maintenance as you need to maintain a consistently updated record of the root zones in order to ensure that your resolutions don’t break or worse, reference old servers that have been changed. Another downside is while you aren’t going out to the root servers to resolve domains, you still need to make a DNS request out in order to lookup the host’s IP address from, so this method also does not save you from your ISP by itself.


Software: Bind9, Ubuntu Server LTS (or whatever distro you are comfortable with)

For the sake of time, this guide assumes you already know how to install stuff on your server.

In order to configure Bind to act like a root name server we will need to tell it about the root zone.

I like to keep my zone definitions in their own separate files that I include into the bind configuration. If you know what your doing, feel free to stray from this and do your own thing. If not, just follow along.

# /etc/bind/named.conf.iana

zone "." {
         type slave;
         file "/var/bind/root.db";
         notify no;
         masters {

The above file is sourced from an ISC Slideshow found here on slide number 8.

While the slideshow says this method does not provide DNSSEC, I am able to point PiHole to a DNS server running this configuration and still achieve SECURE DNSSEC resolutions. I assume this is because PiHole is now doing the work of validating queries. If you will not be doing DNSSEC validations from another device, you can fairly easily follow the rest of the guide from the ISC slideshow that contains the additional lines needed to provide validation.

In order to ensure that our root zone file is consistently up-to-date, I chose to write my own script that runs every night at midnight and pulls the file from IANA directly from their website.

# Crontab
0 0 * * * /root/.scripts/updateRootDNS.sh >> /dev/null 2>&1
# /root/.scripts/updateRootDNS.sh


# Fetch latest Root Zone from Internic
/usr/bin/wget http://www.internic.net/domain/root.zone -O /etc/bind/db.root

# Restart the DNS server so that the new root zone can take effect
/bin/systemctl restart bind9

**NOTE If your server does not use Systemd please adjust the script above to use the init system of your choosing.

This tells Bind to use the root.db file in /etc/bind as the slave zone for the “.” zone. This zone must be configured as a slave in order for things to work properly. Configuring it as a root hint will actually cause bind to fail to start.

Now we will modify our named.conf.options file in order to allow recursive lookups

# /etc/bind/named.conf.options
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.

         //forwarders {

        // 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-validation auto;
        dnssec-enable yes;
        dnssec-lookaside auto;

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { ::1; };

listen-on { any; };
allow-recursion { any; };


Some things you should absolutely change depending on your environment is the listen-on and allow-recursion lines.

This configuration would allow any system from any address to query our server and recursively resolve any address (an open resolver). This configuration is not recommended and is actually frowned upon for systems publicly accessible on the Internet as this would allow hackers to abuse your system in order to launch DNS amplification attacks using your server. Unless your provider or you have systems in place to detect and drop spoofed packets you should change this to something less open or run your own VPN service and only allow lookups from your VPN addresses.

If you do however wish to run a open resolver and understand the risks of doing so, you should hide your Bind versioning info (there is info around on the web) and append an rate limit on the number of queries that can be requested within a short period of time. I actually utilize OpenNIC’s recommended firewall rules for running Tier 2 DNS servers.

iptables -A INPUT -p udp -m string --hex-string "|00000000000103697363036f726700|" --algo bm --to 65535 --dport 53 -j DROP
iptables -A INPUT -p udp -m string --hex-string "|0000000000010472697065036e6574|" --algo bm --to 65535 --dport 53 -j DROP
iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --set --name dnsanyquery
iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 60 --hitcount 4 -j DROP
iptables -A INPUT -p udp -m hashlimit --hashlimit-srcmask 24 --hashlimit-mode srcip --hashlimit-upto 30/m --hashlimit-burst 10 --hashlimit-name DNSTHROTTLE --dport 53 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 53 -j DROP
iptables -A OUTPUT -p udp --source-port 53 -m string --algo kmp --from 30 --to 31 --hex-string "|8105|" -j DROP
ip6tables -A INPUT -p udp -m string --hex-string "|00000000000103697363036f726700|" --algo bm --to 65535 --dport 53 -j DROP
ip6tables -A INPUT -p udp -m string --hex-string "|0000000000010472697065036e6574|" --algo bm --to 65535 --dport 53 -j DROP
ip6tables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --set --name dnsanyquery
ip6tables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 60 --hitcount 4 -j DROP
ip6tables -A INPUT -p udp -m hashlimit --hashlimit-srcmask 24 --hashlimit-mode srcip --hashlimit-upto 30/m --hashlimit-burst 10 --hashlimit-name DNSTHROTTLE --dport 53 -j ACCEPT
ip6tables -A INPUT -p udp -m udp --dport 53 -j DROP

There is a lot going on in this rule set so please view OpenNIC’s documentation which explains what each rule does in detail. While I haven’t had any issues so far with this rule list, it is still possible for someone to abuse your server. You should not rely solely on the rules above to prevent attacks on your DNS server and should be combined in your existing firewall rules after you have verified that the rules above work for your use cases.

Next we need to tell Bind not to use the root.db file as a root hint anymore. On stock bind installations the named.conf.default-zones file includes a hint record for the “.” zone. Because we have overwritten this with the official root zone file this will cause bind to fail to start. You can safely remove this entire zone line since we will be using the file we created above in order to tell bind about the “.” zone.

Lastly, inside named.conf we will add a new include line which will point to our IANA configuration with the root “.” zone slave record.

include "/etc/bind/named.conf.iana";

Once this change has been added you may reload/restart bind. In order to make sure everything is working properly, You should open two sessions: One to monitor the DNS packets going in and out of the system and another to test that resolutions on the system are working as they should.

tcpdump -i eth0 port 53 

and we will simply use dig (from the dnsutils package)

dig google.com @

In your tcpdump window you should see DNS queries go out to the authoritative DNS servers for Google. There should be no communications made to the root DNS servers or any other forward resolvers (,,,, etc..). You should only see your A record request.

Once you have ensured your DNS server is running properly you can safely point your clients to your DNS server and have working DNS resolutions. Depending on the location of the server you may see a decrease in the time it takes to load pages on the Internet.

It is recommended that you configure caching on the server in order to keep resolution times at a minimum if you don’t want to get stuck waiting for your DNS server to perform the lookup every time you go to resolve a hostname. DNS lookups come with their own TTL specified by the upstream server. For most sites this is usually somewhere around 300 seconds (5 minutes). I like to bump this up to at least an hour, that way I’m only going back out to resolve the address a few handful of times instead of after every 5 minutes.

Hopefully this has helped you take back some control over your DNS resolutions and if your one of the many users who still use the public resolvers over port 53 unencrypted maybe this has opened your eyes to the complexity that sits underneath all those fancy user interfaces that have magically brought the web to you 😉 or maybe I’ve made you think twice about what websites you decide to just visit randomly when you think nobody can see 😛

If there is anything you feel I left out or would like explained better, feel free to leave a comment or reach out to me on social media and I’ll try my best to explain it better.

In the next post I will be focusing on securing this a step further by creating a private VPN through which we can pass all sorts of traffic over in a very secure manner.


21 Year old System/Network Administrator. Tech enthusiast, Net Neutrality Activist, Privacy Advocate, Supporter of end-to-end encryption, Fluffy Internet Fox

Leave a Reply

Your email address will not be published. Required fields are marked *