We are going to cover a lot of ground here.

And, we are going to break it into two parts.

Part one will be getting Ubuntu 16.04.x running as a DNS server running Pi-Hole (DNS sinkhole).

Part two will be getting Ubuntu 16.04.x running using CloudFlare as the DNS provider via the DNS Proxy.


You can setup, or have, a machine running Ubuntu 16.04.x and you can SSH into it (it will make life easier).

You have an active/working internet connection.

You have a static IP address

You know how to configure DNS on Windows/Linux/Mac.

If you cannot SSH into your Ubuntu 16.04.x server, please follow this how-to (http://ubuntuhandbook.org/index.php/2016/04/enable-ssh-ubuntu-16-04-lts/)

For this example, my network is setup as:

  • address
  • netmask
  • gateway
  • dns

NOTE: To use the system right now, you will need to point the local system to for DNS.  At that point, the proxy will pick up the request and forward it to and over HTTPS.

NOTE: We will be changing the script that starts the service when we install Pi-Hole to make sure we listen on a different port than 53 for DNS... and so we can loop-back to ourselves for proxy.

Part 1: Installing, configuring and using Pi-Hole

  1. Make sure your machine is up-to-date by running "sudo apt-get update && sudo apt-get upgrade".
  2. Then, just to make sure, let's throw in a reboot with "sudo reboot".
  3. Log back in.
  4. Type "cd ~" to move to your home directory.
  5. We need to download the Pi-Hole project from GitHub.  We'll do this with "git clone --depth 1 https://github.com/pi-hole/pi-hole.git Pi-hole".
  6. Now that we have the installer, we need to run it.  It is in the directory ./Pi-hole/automated\ install/.  So we need to go there with "cd Pi-Hole/automated\ install/"
  7. The installer is a bash script, so we need to run it that way.  We do that by running "sudo bash basic-install.sh".  You'll see the script run like this (see image below).
  8. When prompted with questions, just hit [ENTER].  The defaults are just fine for now (see images below).
  9. At the end of the install you will see the "Installation Complete!" message (see image below).  Write down your password... you will need this.
  10. We'll navigate to (my IP address in this example) and we should see the non-logged in interface (see image below).

  11. Click on the login menu item (on the left) and enter the password you were given at the end of the Pi-Hole install.

  12. You should now see a configurable Pi-Hole screen (see image below).

At this point, you could simply point any/all network clients to this VM/PC and it would resolve DNS for them.

REVIEW: What we've got so far...

So far, we've installed Pi-Hole on an Ubuntu 16.04.x server and have all of it's services running.

At this point, it will respond to DNS inqueries on port 53 and ask it's upstream providers (Google, as I configured in the script) for the information... if it does not have an entry already.

It could be used as it sits right now as a DNS sinkhole.

But... let's protect our traffic with DNS over HTTPS!!

Part 2: Installing CloudFlare DNS Proxy

  1. Make sure your machine is up-to-date by running "sudo apt-get update && sudo apt-get upgrade".
  2. Then, just to make sure, let's throw in a reboot with "sudo reboot".
  3. Log back in.
  4. Type "cd ~" to move to your home directory.
  5. Now we're going to download the binary to our system with "wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.tgz".  Check the current package here and adjust the name as necessary.
  6. We're going to make a directory to put it all in.  Type "mkdir argo-tunnel".
  7. We're going to uncompress/extract the files into our new directory with "tar -xvzf cloudflared-stable-linux-amd64.tgz -C ./argo-tunnel" (once again, check the filename to make sure you are using the current version).
  8. We're going to clean up after ourselves and remove the download with "rm cloudflared-stable-linux-amd64.tgz".
  9. We're going to swith to the argo-tunnel directory with "cd argo-tunnel" and then check the version of the app with "./cloudflared --version".  You sould see something like this (see image below).
    If screen is not installed (and I cannot imagine why this is) can install it with "sudo apt-get install screen".
  10. We're going to run "screen" so we can run an app in the background.  We do this by just typing "screen".  (Note:  You can use CTRL+A+D to exit your screen session)

  11. Now we will start the cloudflare dns proxy by typing "sudo ./cloudflared proxy-dns --port 54 --upstream --upstream".  Note: we will be listening on port 54 (vs DNS port 53 for this proxy).

  12. When running, you should see something like this (see image below).

  13. Now use CTRL+A+D to get back to our main session.  (You can use "screen -r" to list current screen sessions (if more than one) and "screen -r [pid number]" to re-attach to sessions.)

  14. So, we now have it installed and we know it works...

  15. We need to install the DNS Proxy as a service.  We need to edit the file "/etc/systemd/system/dnsproxy.service" to do this.  We do this with nano (as sudo).

  16. The initial file is empty.  You need to add this (below) and then save it:  (Note:  I'm using the account 'sysadmin' for my example.  Replace this in your service script as necessary)
    Description=CloudFlare DNS over HTTPS Proxy
    After=network.target network-online.target

    ExecStart=/home/sysadmin/argo-tunnel/cloudflared proxy-dns --port 54 --upstream --upstream


  17. We need to enable our new service.  We can do that with "sudo systemctl enable dnsproxy.service".  Now it will start on boot and restart if it crashes.

  18. Now, we have a DNS Proxy listening on and a service that will start/restart for us.

  19. We need to point our dnsmasq service to the CloudFlare service (not available during the install script of Pi-Hole).  We do that with "sudo nano /etc/dnsmasq.d/01-pihole.conf".

  20. Comment out the DNS server lines (probably Google's and and add "server=".  Save the file.
    This makes Pi-Hole look to on port 54 for DNS resolution.

  21. We need to remove our DNS settings from another file.  We need to edit the file "setupVars.conf".  We do that with "sudo nano /etc/pihole/setupVars.conf".  Commend out the "PIHOLE_DNS..." lines and save the file.

  22. Restart the dnsmasq service with "sudo systemctl restart dnsmasq.service" and Pi-Hole will now send queries through CloudFlare.

  23. You should also notice that within the web GUI the DNS options have changed and nothing shows now (see image below).

  24. Now, let's reboot and test it out!!

  25. Since DNS is pointing toward the CloudFlare DNS Proxy, we should be able to ping www.google.com.  It works (see image below).

  26. But... how do we know it went through Pi-Hole for that...  well, let's go someplace weird and check the logs.  Let's ping www.playstation.com and then let's check the Pi-Hole logs for that (see images below).
    IT WORKS!!!

I hope you found this helpful.

If so, share it and give me some credit.

As for helping me out...

Thank you to Scott Helme (https://scotthelme.co.uk/securing-dns-across-all-of-my-devices-with-pihole-dns-over-https-1-1-1-1/) for his Raspberry Pi version of this.

Thank you to the folks at CloudFlare.

Thank you to the folks at Ubuntu.