Setting up a VPN

Easy setup

Like VLANs, VPNs are something I’ve made enough use of to become comfortable with, but I’ve never actually had to set one up on my own. Fortunately the UDM comes with out-of-the-box support for VPNs.

In this instance I actually found the Unifi documentation for setting up a VPN sufficient. YouTube also has plenty of videos of folks going over the specifics step by step. I’m honestly surprised it was that straightforward!

Additionally, I’ve scripted a cronjob to update my DNS records whenever my ISP provides me with a new IP address.

#!/usr/bin/python3
import random
import requests
import os

DIGITAL_OCEAN_ACCESS_TOKEN = os.environ["DIGITAL_OCEAN_ACCESS_TOKEN"]
PRIMARY_DOMAIN = os.environ["PRIMARY_DOMAIN"]
VPN_SUBDOMAIN = os.environ["VPN_SUBDOMAIN"]
LAST_KNOWN_IP = "last-known-ip"

# Get the current IP
current_ip = requests.get(random.choice([
    "https://ifconfig.me",
    "https://api.ipify.org",
    "https://ipinfo.io/ip",
    "https://icanhazip.com",
    "https://ipecho.net/plain",
])).text.strip()

# Only proceed if the IP has changed
last_known_ip = open(LAST_KNOWN_IP).read().strip()
if current_ip != last_known_ip:

    # Connect to Digital Ocean
    session = requests.Session()
    session.headers.update({
        "Authorization": f"Bearer {DIGITAL_OCEAN_ACCESS_TOKEN}"
    })

    # Update the appropriate DNS record
    get_response = session.get(f"https://api.digitalocean.com/v2/domains/{PRIMARY_DOMAIN}/records/")
    for record in get_response.json()["domain_records"]:
        if record["type"] == "A" and record["name"] == VPN_SUBDOMAIN:
            put_response = session.put(f"https://api.digitalocean.com/v2/domains/{PRIMARY_DOMAIN}/records/{record['id']}", data={
                "data": current_ip,
            })
            if put_response.status_code != 200:
                raise Exception(f"Attempt to update dynamic DNS failed: {put_response.content}")
            break

    # Update the last known IP
    with open(LAST_KNOWN_IP, "w") as f:
        f.write(current_ip)

Hiccup 1: Connectivity while inside home wifi

I’d love to be able to have my phone’s VPN settings always enabled. That way I can be connected to my home network whether I’m at home on my wifi or out and about on my mobile data or someone else’s wifi. The setting in Android is fairly simple: Always-on VPN.

However, I quickly discovered that this doesn’t work if I’m connected to my home wifi. Looking this up in Unifi’s community forums or on Reddit’s /r/networking both provide some context. Things I might try:

As time constraints are still upon me, I’ll be going with the third option for now, but I’ve created a low priority issue in GitLab to investigate hairpin NAT when there’s time.

Hiccup 2: Pixel connectivity issues

For some reason I haven’t been able to isolate, my Pixel 3a would randomly disconnect from my VPN, but my MacBook can maintain a solid connection without issue. A quick google shows that others have been experiencing this issue for some time and that it may well be specific to the Pixel phone.

It’s fortunate for me then that the release of Android 11 has resolved the issue for my phone, though I see this resolution hasn’t been universal. I’ll put more effort into digging around if it comes up again, but consider the issue moot for the time being.