Skip to content

WireGuard VPN

Martin Gergeleit edited this page Mar 4, 2026 · 1 revision

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.

Features

  • Auto-reconnect: VPN reconnects automatically when the STA interface goes down and comes back up
  • Web Configuration: Full configuration via the /vpn page
  • CLI Configuration: Use set_vpn command 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 -R flag 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 -K flag or web UI)
  • Automatic MSS/PMTU: MSS clamping (1380) and Path MTU (1440) are automatically enabled when VPN is active

Quick Start

  1. Configure via web interface (/vpn page) or CLI:
set_vpn <your_private_key> <peer_public_key> <endpoint_ip> <tunnel_ip> -e 1
  1. Check status:
show vpn

Configuration

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.

Setting Up a WireGuard Server on Linux

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.

1. Install WireGuard

# Debian/Ubuntu
sudo apt install wireguard

# Fedora
sudo dnf install wireguard-tools

# Arch
sudo pacman -S wireguard-tools

2. Generate Keys

# 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.key

3. Configure the Server

Create /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/24

Replace 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

4. Start the Server

# Start and enable on boot
sudo systemctl enable --now wg-quick@wg0

# Verify
sudo wg show

5. Open the Firewall

sudo ufw allow 51820/udp

6. Configure the ESP32

Use 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

7. Verify the Connection

On the server:

sudo wg show

You 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".

Troubleshooting

  • 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 = 1420 to the server's [Interface] section.

Clone this wiki locally