VPN
Overview & Architecture
This document describes the modern, high-performance WireGuard VPN service running on the internal infrastructure server ul (10.0.0.3) with full IPv4 and IPv6 dual-stack pass-through from the edge router danknasty (OpenBSD pf).
Network Topology
+-----------------------------------------------------------------------------------------+
| Internet / WAN |
+-----------------------------------------------------------------------------------------+
│ │
IPv4 UDP Port 51820 IPv6 UDP Port 51820
│ │
▼ ▼
+-----------------------------------------------------------------------------------------+
| danknasty (OpenBSD Router & Gateway) |
| WAN IPv4: 71.25.179.69 |
| WAN IPv6: 2603:3001:626:9d80::/64 |
| LAN: 10.0.0.1 / fd77:7777:5010::1 |
| |
| PF Inbound Rules: |
| pass in quick on $ext inet proto udp from any to any port 51820 rdr-to 10.0.0.3 |
| pass in quick on $ext inet6 proto udp from any to $ul_gu port 51820 |
| rdr-to $ul_ula port 51820 |
| |
| Static Route for VPN IPv6 Subnet: |
| route add -inet6 fd77:7777:5010:7700::/64 fd77:7777:5010:0:1337:f1ac:d00d:337 |
+-----------------------------------------------------------------------------------------+
│ │
└───────────────────┬───────────────────┘
│
▼
+-----------------------------------------------------------------------------------------+
| ul.drheck.dev (VPN Server) |
| IPv4: 10.0.0.3 | IPv6: fd77:7777:5010:0:1337:f1ac:d00d:337 |
| WireGuard Interface: wg0 |
| IPv4 Address: 10.77.0.1/24 | IPv6 Address: fd77:7777:5010:7700::1/64 |
| |
| - Full Dual-Stack In-Kernel WireGuard Tunneling (ChaCha20-Poly1305, Curve25519) |
| - Dual-Stack IPv4 & IPv6 Forwarding & MASQUERADE NAT for outgoing client traffic |
+-----------------------------------------------------------------------------------------+
│ │
┌───────────────┴───────────────┐ ┌───────────────┴───────────────┐
▼ ▼ ▼ ▼
10.0.0.0/24 LAN Hosts WAN IPv4 via danknasty fd77:7777:5010::/64 ULA WAN IPv6 via danknasty
Server Configuration
Parameters & Endpoints
ul.drheck.dev (10.0.0.3)
Edge Router
danknasty.drheck.dev (10.0.0.1)
Public IPv4 Endpoint
71.25.179.69:51820
Public IPv6 Endpoint
[2603:3001:626:9d80:1337:f1ac:d00d:337]:51820
FQDN Endpoint
vpn.drheck.dev:51820 (or ul.drheck.dev:51820)
Protocol & Port
UDP 51820 (IPv4 and IPv6)
VPN IPv4 Subnet
10.77.0.0/24 (Server: 10.77.0.1)
VPN IPv6 Subnet
fd77:7777:5010:7700::/64 (Server: fd77:7777:5010:7700::1)
DNS Resolvers
10.0.0.1, fd77:7777:5010::1 (Unbound on danknasty)
Server Public Key
ubh+z69hcWcUKgHl3LVfm54sYkDZAaocIKNN5zlsZWA=
Router (danknasty) PF & Route Configuration
Tracked in /home/luke/git/router_config/pf.conf:
# Ports
wireguard = "51820"
# IPv4 Inbound
pass in quick on $ext inet proto udp from any to any port $wireguard rdr-to $ul_ipv4
# IPv6 Inbound
pass in quick on $ext inet6 proto udp from any to $ul_gu port $wireguard rdr-to $ul_ula port $wireguard
IPv6 routing in /home/luke/git/router_config/hostname.em1:
!route add -inet6 fd77:7777:5010:7700::/64 fd77:7777:5010:0:1337:f1ac:d00d:337
DNS Access Control in /home/luke/git/router_config/unbound.conf:
access-control: 10.77.0.0/24 allow
access-control: fd77:7777:5010:7700::/64 allow
Server (ul) Interface Configuration: /etc/wireguard/wg0.conf
[Interface]
Address = 10.77.0.1/24, fd77:7777:5010:7700::1/64
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# Dual-stack packet forwarding and NAT masquerade
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -s 10.77.0.0/24 -o eth77 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -s fd77:7777:5010:7700::/64 -o eth77 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -s 10.77.0.0/24 -o eth77 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -s fd77:7777:5010:7700::/64 -o eth77 -j MASQUERADE
# Peer entry template
[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY>
AllowedIPs = 10.77.0.X/32, fd77:7777:5010:7700::X/128
Client Management Utilities
Management scripts are installed in /home/luke/bin/ on ul:
1. Adding Clients (wg-addclient)
# Syntax: wg-addclient <device-name> [optional_ip_octet]
# IP is automatically assigned to the next available address if omitted:
wg-addclient macbook
wg-addclient iphone
# Or manually specify an IP octet if preferred:
wg-addclient custom-device 10
This utility:
/etc/wireguard/clients/<name>.conf.
Injects the peer into /etc/wireguard/wg0.conf and live kernel interface dynamically.
Renders an ASCII QR code in the terminal for instant mobile setup.
2. Listing Active Clients (wg-listclients)
wg-listclients
Prints all configured clients, their assigned IP addresses, and their WireGuard public keys.
3. Revoking / Removing Clients (wg-delclient)
# Syntax: wg-delclient <device-name>
wg-delclient macbook
This utility:
sudo wg set wg0 peer <pubkey> remove), severing all active sessions.
Removes the [Peer] block from /etc/wireguard/wg0.conf.
Deletes the stored configuration file /etc/wireguard/clients/<name>.conf.
To display a QR code for mobile devices:
sudo qrencode -t ansiutf8 < /etc/wireguard/clients/<name>.conf
Client Setup Instructions (All Platforms)
1. Apple macOS & iOS
Setup via Mobile / QR Code (iOS)
ul, run sudo qrencode -t ansiutf8 < /etc/wireguard/clients/<client-name>.conf and scan the terminal screen.
Name the tunnel drheck and toggle to connect.
Setup via Desktop App (macOS)
.conf file from /etc/wireguard/clients/<name>.conf to your Mac.
Open WireGuard, click Import tunnel(s) from file, and select the .conf file.
Click Activate.
2. Linux (systemd-networkd / NetworkManager / wg-quick)
Method A: wg-quick
wireguard-tools:
sudo pacman -S wireguard-tools
Debian/Ubuntu: sudo apt install wireguard-tools
Fedora: sudo dnf install wireguard-tools
Save your configuration as /etc/wireguard/drheck.conf:
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.77.0.X/24, fd77:7777:5010:7700::X/64
DNS = 10.0.0.1, fd77:7777:5010::1
[Peer]
PublicKey = ubh+z69hcWcUKgHl3LVfm54sYkDZAaocIKNN5zlsZWA=
PresharedKey = <PRESHARED_KEY>
Endpoint = 71.25.179.69:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Bring the tunnel up:
sudo wg-quick up drheck
# To enable on boot:
sudo systemctl enable --now wg-quick@drheck
Method B: NetworkManager
sudo nmcli connection import type wireguard file /path/to/<name>.conf
sudo nmcli connection up <name>
3. Android
sudo qrencode -t ansiutf8 < /etc/wireguard/clients/<name>.conf
Enter tunnel name drheck and tap to activate.
4. Microsoft Windows
Ctrl+O) and open <name>.conf.
Click Activate.
5. OpenBSD / FreeBSD
OpenBSD (hostname.wg0)
Create /etc/hostname.wg0:
inet 10.77.0.X 255.255.255.0 NONE
inet6 fd77:7777:5010:7700::X 64
wgkey <CLIENT_PRIVATE_KEY>
wgpeer ubh+z69hcWcUKgHl3LVfm54sYkDZAaocIKNN5zlsZWA= \
wgpresharedkey <PRESHARED_KEY> \
wgendpoint 71.25.179.69 51820 \
wgaip 0.0.0.0/0 wgaip ::/0
up
Run sh /etc/netstart wg0.
Split Tunneling vs Full Tunneling
By default, the client configuration routes all traffic (AllowedIPs = 0.0.0.0/0, ::/0) through the home network connection.
If you only want access to the internal drheck.dev LAN resources and DNS without tunneling general internet browsing, adjust AllowedIPs in the client's [Peer] section:
# Split Tunnel (Internal LAN & VPN Subnet Only)
AllowedIPs = 10.0.0.0/24, 10.77.0.0/24, fd77:7777:5010::/48