I spent a lot of my extra time (late nights) in 2020 and 2021 setting up and configuring a secure home network. I use PiHole and Cloudflared to:

  • ensure the devices on the secure portion of my home network don’t process requests made by advertising, tracking, and analytics software
  • ensure my ISP’s ability to observe the browsing habits of those on my home network is minimized, with DNS-over-HTTP

This has worked well for me for the past few months. Now that things are beginning to open up and I will begin to travel more regularly to work, leisure, etc, I’d like to maintain this level of digital privacy whenever I’m on the go. I’d like to describe my setup for WireGuard VPN and enabling an automatic connection to it when I’m on an unsecure network.

WireGuard enabled on my Pixel 4
WireGuard enabled on my Pixel 4

Before continuing, setting this up requires some experience with:

  • Docker
  • Configuring your router’s DNS and firewall settings
  • Basic networking knowledge

If you are interested, here is the docker-compose.yml configuration for my Pi-Hole and Cloudflared setup:

version: "3.3"

services:
  cloudflared:
    container_name: cloudflared
    restart: unless-stopped
    image: cloudflare/cloudflared:2021.3.6
    command: proxy-dns
    sysctls:
      - net.ipv4.ip_unprivileged_port_start=53
    environment:
      - "TUNNEL_DNS_UPSTREAM=https://dns.google/dns-query,https://1.1.1.1/dns-query,https://1.0.0.1/dns-query"
      - "TUNNEL_DNS_ADDRESS=0.0.0.0"
      - "TUNNEL_DNS_PORT=5053"
      - "TUNNEL_METRICS=0.0.0.0:49312"
    networks:
      priv_lan:
        ipv4_address: 192.168.80.50

  pihole:
    container_name: pihole
    restart: unless-stopped
    image: pihole/pihole:v5.7
    volumes:
      - './config:/etc/pihole/'
    environment: 
      - "TZ=America/New_York"
      - "WEBPASSWORD=[[ asecurep@assw0rd ]]"
      - "ServerIP=192.168.80.51"
      - "DNS1=192.168.80.50#5053"
      - "DNS2=no"
      - "DNSMASQ_LISTENING=all"
      - "ADMIN_EMAIL=[[ youremail@email.com ]]"
      - "INTERFACE=em1"
    hostname: pihole
    networks:
      priv_lan:
        ipv4_address: 192.168.80.51

networks:
  priv_lan:
    external:
      name: priv_lan

Note: I define an unsecure network as any other network besides my home network. This includes my phone providers cellular network, the WiFi network at work, free WiFi networks in stores and around town, etc.

WireGuard VPN

WireGuard is a stateless VPN network that has been gaining popularity in recent years. I chose it because I’m interested in evaluating newer technologies, but you can just as well use other VPN software like, OpenVPN.

I setup WireGuard VPN on a server I have at home running Docker.

Here is my docker-compose.yml configuration:

version: "3.3"

services:
  wireguard:
    container_name: wireguard
    restart: unless-stopped
    image:  linuxserver/wireguard:version-v1.0.20200827
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - SERVERURL=[[ Your home networks public IP address here or URL ]]
      # don't forget to poke a hole open in your router's firewall
      - SERVERPORT=51820
      - PEERS=5
      - PEERDNS=192.168.1.1
      - INTERNAL_SUBNET=192.168.80.1
    hostname: wireguard
    volumes:
      - "./config:/config"
      - "/lib/modules:/lib/modules"
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    networks:
      priv_lan:
        ipv4_address: 192.168.1.10

networks:
  priv_lan:
    external:
      name: priv_lan

Please see this article for more on setting up a WireGuard VPN server. Once you have your server setup, head over to Google Play to download WireGuard’s client for Android. After installing the app, follow the instructions in the referened article to configure and test your setup.

Tasker

Tasker is an Android app that can automate your phone. For example, you can setup rules to turn on “Do Not Disturb” when you walk into work. It’s pretty powerful, though kind of non-intuitive if it’s your first time using the app.

I setup two Tasker rules, one that enables a connection to my WireGuard VPN server when I’m not on my home network, and another that disables the connection when I am connected to my home network.

<?xml version="1.0" encoding="UTF-8"?>
<TaskerData sr="" dvi="1" tv="5.11.14">
   <Profile sr="prof4" ve="2">
      <cdate>1612581779467</cdate>
      <edate>1612582528013</edate>
      <flags>10</flags>
      <id>4</id>
      <mid0>3</mid0>
      <nme>On Home Network</nme>
      <State sr="con0" ve="2">
         <code>160</code>
         <Str sr="arg0" ve="3">[[ SSID of your Home Network goes here ]]</Str>
         <Str sr="arg1" ve="3" />
         <Str sr="arg2" ve="3" />
         <Int sr="arg3" val="2" />
      </State>
   </Profile>
   <Profile sr="prof5" ve="2">
      <cdate>1612581809315</cdate>
      <edate>1612582441995</edate>
      <flags>10</flags>
      <id>5</id>
      <mid0>2</mid0>
      <nme>Leaving Home Network</nme>
      <State sr="con0" ve="2">
         <code>160</code>
         <pin>true</pin>
         <Str sr="arg0" ve="3">[[ SSID of your Home Network goes here ]]</Str>
         <Str sr="arg1" ve="3" />
         <Str sr="arg2" ve="3" />
         <Int sr="arg3" val="0" />
      </State>
   </Profile>
   <Project sr="proj0" ve="2">
      <cdate>1612581411433</cdate>
      <mdate>1612581809315</mdate>
      <name>Base</name>
      <pids>4,5</pids>
      <tids>2,3</tids>
      <Img sr="icon" ve="2">
         <nme>mw_action_home</nme>
      </Img>
   </Project>
   <Task sr="task2">
      <cdate>1612581433049</cdate>
      <edate>1612581540544</edate>
      <id>2</id>
      <nme>Wireguard Up</nme>
      <pri>100</pri>
      <Action sr="act0" ve="7">
         <code>365</code>
         <Bundle sr="arg0">
            <Vals sr="val">
               <net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""/&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES>
               <net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
            </Vals>
         </Bundle>
         <Str sr="arg1" ve="3">WireGuardSetTunnel(true,[[ Name of your WireGuard VPN configuration goes here ]])</Str>
      </Action>
   </Task>
   <Task sr="task3">
      <cdate>1612581433049</cdate>
      <edate>1612581569722</edate>
      <id>3</id>
      <nme>Wireguard Down</nme>
      <pri>100</pri>
      <Action sr="act0" ve="7">
         <code>365</code>
         <Bundle sr="arg0">
            <Vals sr="val">
               <net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""/&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES>
               <net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
            </Vals>
         </Bundle>
         <Str sr="arg1" ve="3">WireGuardSetTunnel(false,[[ Name of your WireGuard VPN configuration goes here ]])</Str>
      </Action>
   </Task>
</TaskerData>

Once setup, you can test your configuration by turning WiFi off (your device should automatically connect to your VPN network). Turning WiFi back on should disable your VPN connection.

Update: A reader noted that you should disable Android battery optimizations for the WireGuard and Tasker app if you have trouble getting this tasker configuration to run automatically. Thanks!

🧇