If you want Windows to reach only a particular IP range through your corporate VPN—while everything else stays on your normal Internet—one clean approach is to use WSL2 (Alpine Linux) as a tiny VPN router. Windows sends just the target routes to the WSL VM; Alpine dials the VPN with openfortivpn and NATs the traffic. Here’s a concise walkthrough.
-
A lightweight Alpine Linux distro inside WSL2.
-
openfortivpnto connect to a FortiGate VPN without auto-installed routes. -
An Alpine script that:
- Detects the PPP interface created by
openfortivpn - Enables IP forwarding + NAT
- Adds routes only for your destination IP range
- Keeps the setup stable even if the VPN reconnects
- Detects the PPP interface created by
-
A short PowerShell snippet on Windows to add a single route to WSL for that destination range.
Download the Alpine minirootfs and import it as a new WSL distro (named forti below):
curl.exe -LO https://dl-cdn.alpinelinux.org/alpine/vXXX/releases/x86_64/alpine-minirootfs-XXX-x86_64.tar.gz
wsl --import forti path\to\wsl\forti path\to\alpine-minirootfs-XXX-x86_64.tar.gz --version 2Replace
XXXwith the actual Alpine version you want.
From the forti WSL shell:
echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositoriesapk update
apk add openfortivpn iptables iproute2 jqopenfortivpn: VPN clientiptables: NAT and forwarding rulesiproute2: route and interface controljq: JSON parsing for robust interface detection
Put destination prefix and WSL distro name on ~/.myvpnrc.ps1:
$dstIpRange = "A.B.C.D/E" # Your target network(s)
$wslName = "forti" # The Alpine WSL instanceThe script setup.ps1 tells Windows: “Send packets for A.B.C.D/E to the WSL VM.” Everything else continues using your normal adapter.
Put destination prefix on ~/.myvpnrc:
VPN_IPRANGE=A.B.C.D/E
The script setup.sh:
- Runs
openfortivpn --no-routesso the client doesn’t override routes - Detects the new PPP interface
- Enables IP forwarding and NAT
- Ensures the VPN endpoint itself is reached via your default gateway (not tunneled)
- Adds the specific
VPN_IPRANGEroute via the PPP interface - Handles reconnects gracefully
- Selective routing (split tunneling by route): Windows forwards only the target network (
A.B.C.D/E) to WSL. - No conflicting routes:
openfortivpn --no-routesprevents broad VPN routes from hijacking all traffic. - NAT from Alpine:
iptablesmasquerades traffic out the PPP interface, so the remote network sees the VPN endpoint IP. - Stability: The script auto-detects the PPP device, preserves access to the VPN endpoint via your normal gateway, and survives reconnects.
- If DNS for the private range is required, either add per-process DNS on Windows or run a lightweight DNS forwarder inside WSL and point specific lookups to it.
- If Windows can’t reach the target hosts, re-run the PowerShell route command—WSL IPs can change after a reboot or distro restart.
- If
openfortivpnfails to connect, verify credentials and any requiredopenfortivpnoptions (host/port, 2FA, etc.) in your config file.
With this setup, you keep your regular Internet fast and untouched, and only the required private subnets go through the VPN—clean, minimal, and easy to reason about.