Offline laptop on Hyper-V: corp-only via Tailscale, browsing VM for Internet, WSL updates via proxy

A hardened Hyper-V setup: laptop stays offline, corp access goes through gw-vm (Tailscale + iptables/ipset), browsing VM gets Internet only, and WSL can temporarily download packages via a proxy on the browsing VM.

Goal

A Windows 11 laptop stays offline (no direct Internet), while still allowing:

  • Laptop → RDP to a browsing VM (Windows)
  • Laptop → corp networks via a gateway VM (Ubuntu) using Tailscale
  • Browsing VM → Internet only via the gateway VM, with no corp access
  • Optional: WSL on laptop can temporarily download packages only through a proxy hosted on the browsing VM.

Topology

  • Host laptop (Windows 11):

    • RDP-LINK: 10.199.199.10/24 (no default gateway)
    • CORP-LINK: 172.25.30.10/24 (no default gateway)
  • Browsing VM (Windows):

    • RDP-LINK: 10.199.199.50/24
    • INET-LINK: 10.254.254.50/24 gateway 10.254.254.100, DNS 8.8.8.8
  • gw-vm (Ubuntu):

    • eth0 = Wi-Fi uplink (internet)
    • eth1 = INET-LINK 10.254.254.100/24
    • eth2 = CORP-LINK 172.25.30.100/24
    • tailscale0 = corp overlay

Corp subnets allowed from laptop:

  • 192.168.0.0/16
  • 10.0.0.0/24

Hyper-V switches

Recommended:

  • RDP-LINK = Private vSwitch (Host ↔ browsing VM)
  • INET-LINK = Private vSwitch (browsing VM ↔ gw-vm)
  • CORP-LINK = Internal or Private vSwitch (Host ↔ gw-vm)
  • WIFI-EXT = External vSwitch bound to Wi-Fi card with “Allow management OS” disabled (gw-vm only)

gw-vm firewall: iptables + ipset (corp allowlist)

Download:

Highlights:

  • NATs browsing VM (10.254.254.0/24) to the Internet via eth0
  • Blocks browsing VM from tailscale0
  • Allows laptop subnet (172.25.30.0/24) only to allowlisted corp nets via tailscale0
  • Blocks laptop from Internet (eth0)
  • Inserts rules before Tailscale’s ts-forward accept rules.

ipset persistence after reboot

Download:

Install on gw-vm:

sudo mkdir -p /etc/ipset
sudo ipset save > /etc/ipset/ipset.rules
sudo cp ipset-restore.service /etc/systemd/system/ipset-restore.service
sudo systemctl daemon-reload
sudo systemctl enable --now ipset-restore.service

Laptop routing to corp (static routes)

No default gateway. Add only corp routes via 172.25.30.100:

route -p add 192.168.0.0 mask 255.255.0.0 172.25.30.100
route -p add 10.0.0.0 mask 255.255.255.0 172.25.30.100

Laptop firewall: allow only RDP + corp (block all else)

Download:


Temporary Internet for WSL (without enabling Internet for Windows)

Model:

  1. Squid proxy inside WSL on browsing VM
  2. Windows portproxy exposes it as 10.199.199.50:3128
  3. Laptop allows only wslhost.exe to connect to 10.199.199.50:3128
  4. Laptop WSL uses proxy for apt/curl/pip

Files: