Unified VPN lifecycle and policy-routing engine for Route10 that can be used by different VPN protocols like WireGuard and OpenVPN.
Release artifacts include SHA256 checksums and SLSA Build L3 provenance generated by the official SLSA GitHub Generator. See SUPPLY_CHAIN.md for verification steps.
| Feature | Description |
|---|---|
| IPv4/IPv6/MAC policy-based routing | Route selected LAN clients by IP, subnet, or MAC address through a specific VPN interface. |
| Automatic roaming support | DHCP hotplug handling keeps MAC-based routing attached to the device as its IP changes. |
| Internet kill switch | Blocks managed client traffic when the assigned VPN tunnel is down. |
| IPv6 leak prevention | Prevents routed clients from bypassing an IPv4-only tunnel through the WAN IPv6 path. |
| IPv4/IPv6 DNS leak protection | Redirects managed client DNS traffic through the VPN path and blocks unwanted WAN DNS replies. |
| Domain split tunneling | Route selected domains through WireGuard while leaving other traffic on the normal gateway. |
| IPv6 routing modes | Supports NAT66 for provider-style IPv6 and WireGuard routed-prefix mode for public routable IPv6 when the VPN server delegates a prefix. |
| Plugin architecture | Extensible through shared and protocol-specific hooks in plugins/. |
- Protocol wrappers such as
wg.shandovpn.shparse VPN-specific config. - The shared core manages lifecycle, state, routing, DNS protection, hotplug, and cleanup.
- Changes are staged first, then applied together with
commit. - WireGuard and OpenVPN are the current migrated clients.
- Future VPNs can use the same engine by adding a wrapper/plugin layer.
wg.sh / ovpn.sh / future wrappers
|
v
lib/vpn-core.sh
|
+-- lib/state.sh SQLite staged + committed state
+-- lib/routing/ policy routing, DNS routing, split tunnel
+-- hooks/ + hotplug DHCP roaming and firewall reload handling
+-- plugins/ command and lifecycle extensions
Wrappers understand the VPN protocol. The core understands Route10 routing behavior.
That split is the important part: adding another VPN type should mean writing or adapting a wrapper, not rebuilding the PBR, DNS, DHCP, and leak-prevention logic again.
| Client | Wrapper | Details |
|---|---|---|
| WireGuard | wg.sh |
Client routing, split tunnel, NAT66, and public routed-prefix IPv6. See WireGuard guide. |
| OpenVPN | ovpn.sh |
OpenVPN guide |
| Future VPNs | New wrapper/plugin | Can reuse the shared core when migrated |
ROUTER_HOST="root@10.90.1.1"
INSTALL_DIR="/cfg/vpn-client"
scp -r . "${ROUTER_HOST}:${INSTALL_DIR}"
ssh "${ROUTER_HOST}" "find '${INSTALL_DIR}' -name '*.sh' -exec chmod +x {} +"
ssh "${ROUTER_HOST}" "cd '${INSTALL_DIR}' && ./setup.sh --non-interactive"Route a subnet through a WireGuard interface:
cd /cfg/vpn-client
./wg.sh wgproton1 -c conf/wgproton1.conf -t 10.90.15.0/24
./wg.sh commitRoute multiple targets (supporting IPv4, IPv6, and subnets) through a WireGuard interface:
cd /cfg/vpn-client
./wg.sh wgproton1 -c conf/wgproton1.conf -t 10.90.15.20,2001:db8:1::50,10.90.16.0/24
./wg.sh commitRoute selected domains through a WireGuard interface (Domain Split Tunneling):
cd /cfg/vpn-client
./wg.sh wgsplit1 -c conf/wgsplit1.conf -d ipleak.net,example.com
./wg.sh commitRefer to docs/wireguard.md for all supported commands
Route a subnet through an OpenVPN profile:
cd /cfg/vpn-client
./ovpn.sh ovproton1 -c conf/proton.udp.ovpn -a conf/proton-auth.conf -t 10.90.10.0/24
./ovpn.sh commitRoute multiple targets (supporting IPv4, IPv6, and subnets) through an OpenVPN profile:
cd /cfg/vpn-client
./ovpn.sh ovproton1 -c conf/proton.udp.ovpn -a conf/proton-auth.conf -t 10.90.10.20,2001:db8:1::50,10.90.11.0/24
./ovpn.sh commitRefer to docs/openvpn.md for all supported commands
Global defaults live in project.conf.
Most users only need these:
| Setting | Purpose |
|---|---|
VPN_PREFIX |
Runtime namespace for temp files, hotplug files, and marks |
VPN_RT_START, VPN_RT_END |
Routing table allocation range |
VPN_IPV6_MODE_DEFAULT |
Default IPv6 behavior: nat66, routed-prefix, or disabled |
VPN_ENABLE_AUTO_UPDATE |
Enable script/rule auto-updates |
VPN_UPDATE_CRON |
Auto-update schedule |
Manual updater commands:
./scripts/updater.sh check
./scripts/updater.sh forcePlugins live in plugins/.
plugins/*.shruns for all VPN types.plugins/wg/*.shruns for WireGuard only.plugins/ovpn/*.shruns for OpenVPN only.
Plugins can add commands, react to lifecycle hooks, and reapply firewall rules after reloads. See plugins/README.md for the full hook list.
Run the local validation matrix:
sh tests/validation-matrix-test.shRun the non-production router integration test:
ssh root@10.90.1.1 "cd /cfg/vpn-client && R10_LIVE_ALLOW_COMMIT=1 sh tests/router-live-nonprod-integration-test.sh"MIT. See LICENSE.