03 Jul 2019  guides

Setup an Adblocking VPN using WireGuard and NextDNS

WireGuard is the most elegant and popular VPN solution within the tech community, and for good reason. It has very little network overhead, minimal CPU usage, and strong encryption. This is coupled with a relatively tiny codebase compared to heavier protocols such as OpenVPN or IPSec which makes WireGuard highly-performant.

WireGuard uses a peer-based (as opposed to server-client based) architecture; so a “tunnel” in the traditional sense isn’t created — rather packets are encapsulated on the fly.

NextDNS is the “first cloud-based private DNS service that gives you full control over what is allowed and what is blocked on the Internet”, according to their website.

In a nutshell, NextDNS provides a DNS service that:

  • blocks ads, malware, and trackers via dozens of selectable lists
  • encrypts DNS queries with DNS-over-HTTPS (DoH) support
  • provides analytics, stats, and disabling of logs
  • resolves private IPs (and custom domains) via rewrites
  • has user-configurable whitelist/blacklist filtering
  • supports multiple DNS profiles in a single account

Setup WireGuard

WireGuard has official clients for Linux, Windows, macOS, Android, and iOS. The WireGuard server can be setup on a $5 DigitalOcean droplet (Ubuntu 18.04 LTS recommended).

First, ensure you do some housekeeping by updating packages and repositories. I personally use the following command to achieve this:

apt-get update && apt-get upgrade -y; apt-get install curl gnupg zip unzip apt-transport-https dnsutils -y; dpkg-reconfigure tzdata

Once updating is done, we can now install WireGuard. Since I’m using Ubuntu 18.04 this guide will be focused on the steps required for that particular Linux distribution.

The following command will install the WireGuard sources and WireGuard itself in one go:

sudo apt-get install software-properties-common; sudo add-apt-repository ppa:wireguard/wireguard; sudo apt-get install wireguard -y

Once the installation is complete, the next step is to generate the public and private keys of the server.

Generate Keys

For the purposes of this article, head over to wireguardconfig.com and you’ll be presented with a web GUI that will allow you to configure your preferred parameters and generate all the WireGuard configuration settings that are needed.

The Number of Clients can be changed to the number of devices you’ll be using. You can set this higher than the number of actual devices so as to have spare configuration files handy. Ten (10) is a good number to start with if you’re unsure.

The Endpoint (Optional) field is the IP address of your server. If you’re paranoid, you can set it to something like 40.50.60.70:51820 and then simply change that to your server’s IP address after you save the configuration, so as to not allow the website to capture the actual address. Of note, the entire process happens client-side, and you can even download the webpage using HTTrack, open the saved page while you’re offline and the generation process will still work.

Checking the box Use Pre-Shared Keys (Enhanced Security) is a good idea since this adds another layer of security to the peering configuration.

When those values are set, go ahead and hit Generate Config and scroll down to see the output for the server and each endpoint (based on the number of endpoints you selected).

In a nutshell, each endpoint’s config will have the server’s public key and their private key, and conversely the server’s config will have all the endpoints as peers and have their private keys in it’s larger configuration file. Pre-shared keys are of course mapped individually.

You can also download a zip archive with all the conf files, either for individual distribution to clients or for safekeeping.

Configure WireGuard

Next, create and edit the default WireGuard configuration file with the following command:

nano /etc/wireguard/wg0.conf

Paste your Server configuration that was previously generated from wireguardconfig.com, with an example below that has three (3) endpoints:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = +XXXXXXXXXXXXxxxxxxxxxxxxXXXXXXXXXXXXXXXxxx=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = uM5m7Zqnzzqvnh+BUBRlv5kNo3JaU/4Ce8mSzkLU+y4=
PresharedKey = BntkwN7x3UNZw61842/K3G+QzB/VSgJm8mGmRjBL+GA=
AllowedIPs = 10.0.0.2/32

[Peer]
PublicKey = DVQuMIud8ui6FU/65BgMwfwmkoYT0Vqx0aRs54FaCk0=
PresharedKey = 7kkYXcDWP8Ts8iIfTBC2s29gT9pXaMuMiQXmOieGz+A=
AllowedIPs = 10.0.0.3/32

[Peer]
PublicKey = XQtUISA7jHId7zJxmmmi5pI1xZ1DMvWhFt4CgNb03i8=
PresharedKey = gOzor+sbYJE95iF2y4KgbdwX2mxIf+gOQguVPxrdrVI=
AllowedIPs = 10.0.0.4/32

In some cases, you may have to replace eth0 in the PostUp and PostDown (Lines 5 and 6) with your interface name if it’s different. It usually won’t be, but to find the name of your network interface on the server, run the command:

ip -o -4 route show to default | awk '{print $5}'

Next, for security reasons, change the permissions for both the wg0.conf and privatekey file with the following command:

chmod 600 /etc/wireguard/{privatekey,wg0.conf}

Since we’re using port 51820 which is WireGuard’s default, you’ll also need to allow UDP inbound connections on that port in your server’s firewall. I recommend doing this both in DigitalOcean via their droplet firewall config, and also using ufw locally on the server (in case DO has an infrastructure failure).

For reference, the ufw commands are:

ufw allow 51820/udp
ufw allow ssh
ufw enable

We also need to set WireGuard to start on boot. To do that run:

sudo systemctl enable [email protected]

Next, we need to enable NAT forwarding. To do so, run the following the command:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf; sudo sysctl -p

Finally, bring up the WireGuard interface on the server with the command:

sudo wg-quick up wg0

You can show the status of the tunnel by running sudo wg show wg0 if you like.

Setup Client Endpoints

Downloading WireGuard for your individual operating system is outside the scope of this guide, as you can get the correct downloads on the WireGuard homepage.

Where for each client you’ll need to specify a conf file, simply paste the contents of one of your endpoint configuration files that was previously generated by wireguardconfig.com, and connect to the tunnel. Head over to a site such as IP Addy to verify your IP address matches that of your server.

Setup NextDNS

First, ensure you’re connected to the WireGuard VPN tunnel. This is important since NextDNS will bind it’s configuration to your IP address, effectively handling (and filtering) all DNS traffic that arrives from the WireGuard server’s IP.

Once you’re connected to WireGuard, head over to nextdns.io and create a free account.

After logging in you’ll be in the Setup tab. You’ll notice that “Currently Linked IP” is shown as the IP of your VPN server, which represents the IP address that will be associated with your NextDNS configuration. NextDNS will provide the DNS IP addresses for you to use, as well as instructions for advanced configuration and devices.

You don’t need to configure any other interface on your local machine to use these addresses, as NextDNS adblocking will work once you’re connected to the VPN (i.e. since that IP address is authorized to use NextDNS).

All that’s needed at this point is to configure the WireGuard clients to use the provided NextDNS IP addresses for DNS individually. On a client machine, edit the WireGuard .conf file and add a DNS option under the [Interface] section, replacing the DNS IP addresses with the ones specified in your NextDNS dashboard. For example:

[Interface]
PrivateKey = XXxxXXxxXXXXxxXXxxXXXXxxXXxxXXXXxxXXxxXX
Address = 10.0.0.2/24
DNS = 45.90.28.100, 45.90.30.100 # <- Change these IP addresses

Where 45.90.28.100 and 45.90.30.100 are replaced with the addresses provided to you by NextDNS. Now, all tunneled traffic will benefit from the adblocking settings that you’ve configured within the NextDNS dashboard. This has a few benefits such as:

  • simplifying adblocking across all devices via a single IP address and ruleset
  • reducing computing needs for adblocking by making CPU-heavy browser addons redundant
  • enabling faster browsing since adblocking rulesets aren’t parallel processed in-browser while rendering pages
  • enabling zero configuration since any device that connects to the VPN will automatically have adblocking enabled

Resources