With the recent invention of WireGuard, a critical piece of my plan for an elegant home network has fallen into place. WireGuard is FOSS used for VPN networking, with many advantages over existing VPN solutions, chief among them being:

  • Tiny code base
  • Easy to configure - SSH-like authentication scheme using public-key crytography
  • FAST - Compared to IPsec or OpenVPN, it blows them out of the water in nearly every regard
  • Minimal overhead

WireGuard was meant to be the glue in this elegant home network; it’s to seamlessly interconnect my home network and cloud network under one privately addressable subnet, 10.45.0.0/16. Users in my home network, for instance, would be able to connect to my DigitalOcean DNS server at 10.45.10.1. Traffic would flow from their device, though to my router, and finally across WireGuard interface wg0 to its destination.

Getting Started

First was a matter of getting WireGuard installed on my router. I’m using an EdgeRouter Lite, luckily for myself the creator of WireGuard has already created a package for this. With that stroke of luck, the usual hard part - Getting new networking software onto old devices - was a piece of cake. Configuring WireGuard was done using the CLI, using vyatta’s default configuration system, so no one-off-hard-to-track configuration changes had to be made. I generated a public / private key for my router, added my DigitalOcean server as a peer, and away I went. Below is the relevant snipped from my vyatta config, minus the necessary firewall rule to open port 48484 to my router.

wireguard wg0 {
         address 10.45.9.1/24
         listen-port 48484
         mtu 1420
         peer <public key> {
             allowed-ips 10.45.9.2/32
         }
         peer <public key> {
             allowed-ips 10.45.10.1/32
             endpoint worobetz.ca:48484
         }
         private-key /config/auth/privatekey
         route-allowed-ips true
     }

The first peer would be my mobile phone, for connecting to my home network while on the move. The second is my DigitalOcean server, which is itself a WireGuard “server”. By specifying the endpoint, we say that my router should be the one to initialize the connection.

Value-Add Services

Getting the tunneling sorted is all well and good, but now it’s time to make this connection more interesting. I wanted to add an ad-blocking DNS server so that any devices connected to my home network would get network-level ad and telemetry service blocking. Pi-hole is exactly what we need for this purpose.

Pi-hole provides ad blocking via some simple DNS trickery. When a client, for example, your phone, asks the server for some DNS address, it checks the address against a blacklist. If the address is on the blacklist, respond by saying it doesn’t exist. Blacklists are maintained by the community, and have to be updated regularly. Blacklists not only block ad servers, but also any known addresses that are used for the collection of telemetry data. My goal was run Pi-hole on my DigitalOcean server, rather than in my home network, so that I wouldn’t have to maintain a running server in my home. I also didn’t want to run an open DNS resolver (which could be misused by malicious actors in DNS reflection attacks), so I had to be able to lock down access to pi-hole over the public internet.

Enter WireGuard. By having the encrypted tunnel to my server already set up, it was simple to configure the server to only respond to DNS on its wg0 interface. There’s also a web interface component used by pi-hole that shows query logs, client statistics, and so on so I also had to configure my pre-existing nginx server to only respond to requests to http://pi.hole if the request came from my private network. The relevant nginx configuration is below.

server {
    if ($host = worobetz.ca) {
        return 301 https://$host$request_uri;
    }

    listen 10.45.10.1:80;
    server_name pi.hole;
    root /var/www/pi.hole;
    index index.php;

    allow 10.45.0.0/16;
    deny all;

    location / {
        expires max;
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }
}

Getting pi-hole running is easy - It’s a simple curl | sudo bash type installation, which (unless inspecting the script first) is bad practice but fine for my needs. There’s an ncurses installer where you specify your upsteam DNS servers (1.1.1.1, 1.0.0.1), interfaces to listen in on (wg0), and whether or not to install the web interface (yes). I did have to play around with the install a bit to make it so that it used nginx as its web server instead of the default lighttpd but that was a relatively trivial matter.

Once pi-hole was running, I was good to go! I updated my router’s DHCP service to set my clients DNS server to 10.45.10.1 and I was all set.

Overview

All the services are in place, what does it get me in terms of real-world value?

  • I have a secure, fast VPN connection from anywhere in the world back to my home network
  • While connected to my home network (whether it’s Wi-Fi, Ethernet, or VPN), all DNS requests from all devices are filtered (and blackholed, if necessary)
  • I have a cool new web dashboard accessable at http://pi.hole to see my home networks DNS stats / traffic
  • I have a secure tunnel to my cloud environment in case I ever want to set up additional services there

I hope you’ve enjoyed reading, and if you feel inspired, perhaps have an idea for a similar project of your own.