-
Notifications
You must be signed in to change notification settings - Fork 429
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 -
CLI Configuration: Use
set_vpncommand for console-based setup -
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 |
| 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.
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
- 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, 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.