-
Notifications
You must be signed in to change notification settings - Fork 470
WireGuard VPN
The router supports an optional WireGuard VPN tunnel for upstream traffic. When enabled, traffic from AP clients is routed through the WireGuard tunnel while the physical STA WiFi link remains unchanged.
- Auto-reconnect: VPN reconnects automatically when the STA interface goes down and comes back up
-
Web Configuration: Full configuration via the
/vpnpage -
Config Import: Paste a standard WireGuard
.conffile (e.g. from ProtonVPN) on the/vpnpage to auto-fill all settings -
CLI Configuration: Use
set_vpncommand for console-based setup - Custom DNS: Optionally hand a specific DNS server to AP clients while the VPN is enabled, preventing DNS leaks outside the tunnel
-
Split Tunneling: Route all traffic through VPN (default) or only VPN-subnet traffic, letting internet traffic go direct via STA (configurable via
-Rflag or web UI) -
Kill Switch: Blocks non-local AP client traffic when VPN is enabled but not connected, preventing data leakage outside the tunnel. In route-all mode, blocks all non-local traffic; in split tunnel mode, blocks only VPN-subnet-destined traffic (enabled by default, configurable via
-Kflag or web UI) - Automatic MSS/PMTU: MSS clamping (1380) and Path MTU (1440) are automatically enabled when VPN is active
- Configure via web interface (
/vpnpage) or CLI:
set_vpn <your_private_key> <peer_public_key> <endpoint_ip> <tunnel_ip> -e 1
- Check status:
show vpn
| Setting | CLI Flag | Default | Description |
|---|---|---|---|
| Private Key | (positional) | - | Your WireGuard private key (base64) |
| Public Key | (positional) | - | Peer's public key (base64) |
| Endpoint | (positional) | - | Peer endpoint IP or hostname |
| Tunnel IP | (positional) | - | Your tunnel IP (e.g. 10.0.0.2) |
| Preshared Key | -k |
empty | Optional preshared key |
| Netmask | -m |
255.255.255.0 | Tunnel netmask |
| DNS | -d |
empty | DNS server handed to AP clients while VPN is enabled (optional) |
| Port | -p |
51820 | Peer UDP port |
| Keepalive | -a |
0 | Persistent keepalive (seconds, 0=disabled) |
| Enabled | -e |
0 | Enable VPN (0 or 1) |
| Kill Switch | -K |
1 | Block AP client internet when VPN is down (0 or 1) |
| Route All | -R |
1 | Route all traffic through VPN (1) or only VPN subnet (0, split tunnel) |
All settings are persisted in NVS and applied after restart.
Most VPN providers (ProtonVPN, Mullvad, etc.) and wg-quick produce a standard WireGuard .conf file. Instead of copying each field by hand, open the /vpn page, paste the whole file into the Import Config box, and click Import & Reboot.
The importer maps the standard config keys onto the router's settings:
.conf line |
Mapped to |
|---|---|
PrivateKey |
Private Key |
Address = 10.2.0.2/32 |
Tunnel IP + Netmask (CIDR prefix converted to a dotted netmask) |
DNS = 10.2.0.1 |
DNS |
PublicKey |
Public Key |
PresharedKey |
Preshared Key |
Endpoint = host:51820 |
Endpoint + Port |
PersistentKeepalive |
Keepalive |
AllowedIPs |
Route All (0.0.0.0/0 → on; anything else → split tunnel) |
After a successful import the VPN is enabled and the device reboots to apply the settings.
Notes / limitations:
- IPv4 only — IPv6 addresses and DNS entries are skipped, and only the first
Addressis used. - A single peer is supported; with multiple
[Peer]sections the last one wins. -
PrivateKey,PublicKey,Endpoint, andAddressare required. A file missing any of these is rejected and the current configuration is left unchanged. -
wg-quickdirectives the router doesn't use (MTU,Table,PreUp/PostUp, etc.) are ignored.
To use the ESP32 NAT Router as a VPN client, you need a WireGuard server (peer) to connect to. Here's how to set one up on a Linux machine.
# Debian/Ubuntu
sudo apt install wireguard
# Fedora
sudo dnf install wireguard-tools
# Arch
sudo pacman -S wireguard-tools# Server keys
wg genkey | tee server_private.key | wg pubkey > server_public.key
# ESP32 client keys
wg genkey | tee esp32_private.key | wg pubkey > esp32_public.key
# Optional: preshared key for extra security
wg genpsk > preshared.keyCreate /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = <contents of server_private.key>
Address = 10.0.0.1/24
ListenPort = 51820
# Enable IP forwarding and NAT for client traffic
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; sysctl -w net.ipv4.ip_forward=1
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# ESP32 NAT Router
PublicKey = <contents of esp32_public.key>
# PresharedKey = <contents of preshared.key> # optional
AllowedIPs = 10.0.0.2/32, 192.168.4.0/24Replace eth0 with your server's internet-facing interface (check with ip route show default).
The AllowedIPs line includes:
-
10.0.0.2/32- the ESP32's tunnel address -
192.168.4.0/24- the ESP32's AP subnet, so the server can route traffic back to AP clients
# Start and enable on boot
sudo systemctl enable --now wg-quick@wg0
# Verify
sudo wg showsudo ufw allow 51820/udpUse the server's public key and the ESP32's private key to configure the router:
Web interface (/vpn page):
- Private Key: contents of
esp32_private.key - Public Key: contents of
server_public.key - Endpoint: your server's public IP or hostname
- Port: 51820
- Tunnel IP: 10.0.0.2
- Netmask: 255.255.255.0
- DNS: (optional) DNS server to push to AP clients, e.g. 10.0.0.1
- Keepalive: 25 (recommended when ESP32 is behind NAT)
- Enable: checked
CLI:
set_vpn <esp32_private_key> <server_public_key> <server_ip> 10.0.0.2 -p 51820 -a 25 -e 1
On the server:
sudo wg showYou should see a handshake timestamp and data transfer for the ESP32 peer. On the ESP32, show vpn or the /vpn web page should show "Connected".
- No handshake: Check that UDP port 51820 is reachable on the server. Verify keys are correct (public/private not swapped).
-
Handshake but no traffic: Ensure IP forwarding is enabled (
sysctl net.ipv4.ip_forward) and the MASQUERADE rule is active (iptables -t nat -L). -
DNS not working: The ESP32 routes all client traffic through the tunnel. Make sure the server can forward DNS queries, set a tunnel DNS with
set_vpn -d <dns_ip>(or the DNS field on the/vpnpage) to push a specific resolver to AP clients while the VPN is up, or set a public DNS on the ESP32's AP (set_ap_dns 1.1.1.1). -
MTU issues: The ESP32 automatically applies MSS clamping (1380) and Path MTU (1440). If you still see issues, try reducing the server's tunnel MTU: add
MTU = 1420to the server's[Interface]section.