Posted on

Table of Contents


One critical way to improve privacy outcomes when using a single-hop Virtual Private Network (VPN) is to perform Domain Name System (DNS) advertisement (ad) blocking in tandem with a VPN. This article attemps to improve the privacy posture of a single-hop VPN user by setting up a self-hosted Virtual Private Server (VPS) that funtions both as a VPN gateway and as an ad blocking DNS resolver.

I also want to make clear that when I say "ad blocking," this technical security feature also means blocking DNS-based web traffic to data brokers when web browsers or phone apps want to upload data directly from devices to data brokers. It's not just about preventing ads from displaying. This is particularly important when there is background HTTP/HTTPS traffic occuring from phones and computers-- stuff you never see and is not from visiting a web page. Web browser plugins such as uBlock Origin are great. But they only cover the web browser, not everything else that happens on your phone or computer, like traffic generated from apps or from the operating system.

Virtual Private Server (VPS)

A VPS has exceptionally little privacy since it's running on someone else's hardware. VPS operators have real-time access to data in memory, data at rest, and data in motion (network traffic in and out of the VPS). In other words, VPS's are exceptionally cop-friendly. However, the profit motive of VPS providers is typically selling you a VPS, not profiling you and selling you out to data brokers as is the case with your home Internet Service Provider (ISP.) While hosted services companies do in fact have business relationships with data brokers when using their websites, they probably do not have relationships with data brokers for the general use of their compute and network infrastructure.

Virtual Private Network (VPN)

A VPN is not private at all since it's just moving egress traffic from one ISP to another with no other obfuscation. In real-world practice, a single-hop VPN is as fake as any mainstream web browser's "private browser mode" from a network perspective. Your home ISP is selling all of the data it has about you to data brokers, including your real IP, your VPN IP, your physical location, and the time/date metdata with your VPN useage. Data brokers always win in this situation; they see when you (your VPN IP) visit websites with absolute confirmation from your ISP of what your physical IP and your virtual IP is so they can trivially correlate all the data to know when and where you go on the HTTP web.

The Goal -- Less is more.

Combining a single-hop VPN with adblocking aims to increase the cost of surveillance, and to make safer defaults when using personal phones and computers. The theory here is that a VPN with ad blocking will make it so "less" data brokers will be able to see your website visits or collect data about what your devices are doing, and if and when said data brokers obtain metadata about you, "less" data will be captured by them.

The Bad

  1. A single-hop VPN is still a single-hop VPN. As I've mentioned, your ISPs (home internet, mobile internet, etc) know when you're using a VPN. VPNs are not designed to obfuscate the fact that it's a VPN, as is the case with Tor pluggable transports.

  2. ISPs know your real, physical IP. They know when (time/date) you enable and disable your VPN. They sell all of this data to data brokers, and give it to governments freely. Data brokers can perform easy correlation attacks against other data that they have about you, and other data they will be given from other third-parties in the future.

  3. ISPs know when and where you physically are. Home-based ISPs serve... your home. That address will never change. Mobile service / cellular ISPs track your movements via cell tower triangulation. Especially with 5G, they can pinpoint you down to feet/meters in accuracy, including movement, in real time.

The Good

  1. Using an ad-blocking VPN raises the cost of surveillance by a small, measureable amount.

  2. A DNS ad-blocking Wireguard tunnel is a whole-device security feature. It is not only affecting a web browser. A system-wide Wireguard tunnel will control web browser web requests, app web requests, and operating system (OS) web requests.

  3. If you employ the use of a Wireguard-client config on your home internet router, you'll be able to ad-block for things on your home network that cannot use Wireguard. Smart TVs, IoT systems, etc.

  4. Sharing Wiregaurd profiles with friends and family also helps obfuscate who is doing what, since multiple uers will be sharing the same egress IP.

  5. pi-hole provides a web interface for seeing real-time DNS queries. It allows a user to see what domains are blocked, allows a user to add domains including wildcard domains to a block list, or to safelist domains. This fine grain control also allows users to self-educate about what their devices are doing in near real time.

  6. Mobile network throttling is real. Wireguard protects high-qaulity network streams like from Youtube.

  7. Having a Wireguard server means a user can hand out Wireguard-client profiles to friends and family. Having a Wireguard LAN accross your devices makes it easy to run "local" game servers while allowing remote friends and family to join without exposting game servers to the internet.

  8. Having a Wireguard bastion server gives a user a trusted source IP from which to connect to other inernet-connected servers. This means a user can completely block port 22 on internet-facing servers and simply allow one trusted IP to log in from.

My tech choices

My choice in technologies aims to make it easy (presuming you're comfortable with linux CLI) to setup and manage stuff:

OS: Ubuntu Server 22.04 or 23.10 (because of the built-in firewall app UFW)

VPN: pi-vpn (makes Wireguard easy)

DNS: pi-hole (makes DNS ad blocking easy)

Once setup is complete, a user will have a Wireguard-server (pi-vpn) on the cloud VPS. Free and trustworthy Wireguard-client applications for macOS, Windows, Android, and iOS/iPadOS can all have their own Wireguard profiles. Wireguard-client profiles generated from the Wireguard-server is made easy with pi-vpn. Once a personal device has a valid Wireguard-client profile and is active, all traffic will be tunneled to the user's Wireguard-server (pi-vpn). In addition, the VPS will also have pi-hole, so all DNS requests made from any device with a user's Wireguard profile will get filtered at the DNS layer.

In other words, when a user's laptop's web browser makes a DNS request to, the user's internet will be tunneled to their pi-vpn server where pi-hole also exists. pi-hole will resolve the DNS request, and the user's web browser will then know what IP address to resolve to, and your web browser will load When loading, which uses Google Analytics, all of the other web resources loaded from, including those from Google Analytics, also have to make their own DNS requests, all of which will be resolved by your pi-hole server. However, because Google Analytics is block-listed in pi-hole, the DNS response will deny the request, so Google Analystics will not load in your web browser.

There are also Wi-Fi routers that support Wiregaurd-client profiles. Hardware routers like from GL iNet, custom-flashed routers with OpenWRT, and I believe OPNsense and pfSense both support Wireguard-client configs. This means that you can setup a home router with a Wireguard-client profile, and all internet traffic from all devices in your home will automatically and transparently get ad blocking, even for devices that don't support Wireguard. Unless of course any of your devices or web browsers are already setup to use DoH or DoT, etc.

All legacy DNS (53/UDP) requests will remain secure since they will be Wireguard-tunneled to the pi-vpn/pi-hole server.

Vultr Referal

This is not a sponsored post, I just like Vultr. They are like Linode or Digital Ocean, and similairly priced. If you're interested in trying out Vultr, here is a referal link for $100 when openings a new account: I use their $6 /mo VPS there, including for my own Wireguard + ad blocking VPS that this article is based on.

Ubuntu Deployment Guide

Basic Stuff

When setting up a new Ubuntu Linux system on the internet, it's critical that it's patched and restarted.

sudo apt update && sudo apt dist-upgrade -V && sudo apt autoremove -y && sudo apt autoclean && sudo shutdown -r now

Vultr has my public SSH key, an ED25519 key, but I still need to log in with root at first:

ssh root@

Make a new user:

adduser username

Add the new user to the sudo group:

adduser username sudo

If you don't already have your SSH pubkey in Vultr, you can upload it to your VPS directly from your client:

ssh-copy-id username@

Ordinarily I'd harden SSH a bit, but I'm going to skip that in this post since we're instead going to focus on blocking SSH access.

Change from the root user to your new username:

su username

Setup pi-vpn (Wireguard) and pi-hole

Install pi-vpn first:

curl -L | bash

Setup pi-vpn to operate using your new user, not root or system.

Setup pi-vpn to use Wireguard.

Setup pi-vpn to use any port above 1024 that you'd like. Wireguard will configure UFW automatically to allow this port. The default port works fine.

Setup pi-vpn to use a publicly available DNS server at first, like Quad9. Note: You can later change this by editing Wireguard configs or by reinstalling pi-vpn and setting a custom DNS server.

Now install pi-hole:

curl -sSL | bash

Setup pi-hole to operate on the network interface wg0

Change the randomly-generated yet short password to something better (you have a password manager, right?):

sudo pihole -a -p

Configure the Firewall with UFW

My Ubuntu 23.10 VPS deployed with UFW enabled and allowing port 22 for remote SHH access. Validate this by looking at the UFW rules:

sudo ufw status numbered verbose

You should see IPv4 and IPv6 rules for 22/tcp. Leave those alone for now, we will delete these SSH rules later.

If for some reason you do not have the firewall UFW enabled, and in which case SSH is implicitly allowed, explicitly allow SSH access then enable UFW:

sudo ufw allow 22/tcp

sudo ufw start

Having SSH allowed and blocking all other inbound traffic is essential to safely host your own DNS server and the soon-to-be pi-hole web server.

Find the network interface name on your VPS. Classically this is "eth0" but for Ubuntu virtual machines it's usually something else:

ip a

Here I see "1: lo" (loopback), "2: enp1s0" (virtual machine interface), and "3: wg0" (Wireguard). So enp1s0 is what I need, and we need to configure UFW to allow forwarding traffic from wg0 to enp1s0:

sudo ufw route allow in on wg0 out on enp1s0

Next we need to configure UFW to allow SSH (port 22) traffic from wg0 (Wireguard). This is critical so that we can later delete the inbound rules allowing any port 22 access. SSH access to this server will be allowed only when using the Wireguard tunnel to the system:

sudo ufw allow in on wg0 from any to any port 22 proto tcp

Next we need to configure UFW to allow legacy DNS (port 53) traffic from Wireguard:

sudo ufw allow in on wg0 from any to any port 53 proto udp

We also need to configure UFW to allow in HTTP (port 80) web traffic from Wireguard so that the pi-hole web interface can be accessed when using Wiregaurd:

sudo ufw allow in on wg0 from any to any port 80 proto tcp

Review the UFW rules:

sudo ufw status verbose

Once validated, restart UFW:

sudo ufw reload

Configure Wireguard-client

Check out the Wireguard documentation for setting up client configs from the Wireguard server. For example:

Create a client profile:

pivpn -a

View the new client profile QR code, easy for setting up on a phone:

pivpn -qr

For setting up a Wiregaud-client for a laptop or router, view the config and copy+paste it to a new empty tunnel in Wiregaurd-client:

cat configs/your-client.conf

It's that simple.

After you add your Wireguard-client config to your device(s), edit the Wireguard-client config by changeing the DNS server to your pi-hole IP. Doing it this way makes it so default Wireguard profiles have working DNS. Users can opt-in to using the pi-hole ad blocking feature. If you want default configs to use the custom DNS, you'll simply resinstall pi-vpn and select a custom DNS server, and set the same IP as the pi-vpn server. Note: reinstalling pi-vpn will require issuing new Wireguard-client profiles to folks.


Test your Wireguard-client VPN by activiating it on your first device. Check that your egressing out of the Vultr VPS IP by going to in a web browser.

You should also be able to SSH to your Vultr VPS while using the Wireguard tunnel.

View the pi-hole web interface in a web browser:

Complete the Firewall Config

Delete any premade SSH rules (change the number based on the rule you want to delete):

sudo ufw status numbered verbose

sudo ufw delete 1

sudo ufw reload

Again, the point here is to remove public SSH access to the system (zero trust). No need for fail2ban or any response-based security measures. Wireguard is the only way in. If things mess up somehow, you'll always have terminal access via the Vultr web console.