# Rego-Tunnel VPN Bridge This app runs a Windows VM inside a Docker container with Cisco AnyConnect VPN, providing transparent access to VPN-protected resources (IBM i at 10.35.33.230) from the local network. ## Architecture ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Laptop (192.168.0.230) │ │ Route: 172.31.0.0/24 via 192.168.0.150 │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Linux Host (192.168.0.150 / 192.168.1.150) │ │ │ │ rego-routing.service: │ │ - Routes 172.32.0.0/24 and 10.35.33.0/24 via 172.31.0.10 │ │ - Removes Docker nft isolation rules for 172.31.0.10 │ │ - DOCKER-USER iptables rules for forwarding │ │ │ │ Bridge: br-vpn-rego (172.31.0.1/24) │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Container: rego-tunnel (172.31.0.10) │ │ │ │ start.sh: │ │ - socat: port 2222 → VM:2222 (SSH to VM) │ │ - DNAT: ports 22,23,446,448,449,8470-8476,2000-2020,3000-3020, │ │ 10000-10020,36000-36010 → VM │ │ - MASQUERADE for docker bridge │ │ │ │ Internal docker bridge: 172.32.0.1/24 │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Windows VM (172.32.0.20) │ │ │ │ SSH Server: port 2222 │ │ Cisco AnyConnect VPN: connected to corporate network │ │ VPN IP: 10.215.x.x │ │ │ │ Portproxy rules (persistent): │ │ - 0.0.0.0:22 → 10.35.33.230:22 │ │ - 0.0.0.0:23 → 10.35.33.230:23 │ │ - 0.0.0.0:446,448,449 → 10.35.33.230:* │ │ - 0.0.0.0:8470-8476 → 10.35.33.230:* │ │ - 0.0.0.0:2000-2020 → 10.35.33.230:* │ │ - 0.0.0.0:3000-3020 → 10.35.33.230:* │ │ - 0.0.0.0:10000-10020 → 10.35.33.230:* │ │ - 0.0.0.0:36000-36010 → 10.35.33.230:* │ │ │ │ vpn-login.js: │ │ - Auto-login to Cisco AnyConnect via WebView DevTools │ │ - TOTP authentication │ │ - Watchdog: monitors VPN and reconnects if dropped │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ IBM i (10.35.33.230) │ │ Via Cisco VPN tunnel │ └─────────────────────────────────────────────────────────────────────────┘ ``` ## Network Configuration ### IP Addresses | Component | IP Address | |-----------|------------| | Container external (br-vpn-rego) | 172.31.0.10 | | Container internal bridge | 172.32.0.1 | | Windows VM | 172.32.0.20 | | IBM i (via VPN) | 10.35.33.230 | ### Ports | Port | Destination | Purpose | |------|-------------|---------| | 2222 | VM SSH (2222) | SSH access to Windows VM | | 22 | IBM i (via portproxy) | SSH to IBM i | | 23 | IBM i (via portproxy) | Telnet to IBM i | | 446,448,449 | IBM i (via portproxy) | IBM i services | | 8470-8476 | IBM i (via portproxy) | IBM i data ports | | 2000-2020 | IBM i (via portproxy) | Additional ports | | 3000-3020 | IBM i (via portproxy) | Additional ports | | 10000-10020 | IBM i (via portproxy) | Additional ports | | 36000-36010 | IBM i (via portproxy) | Additional ports | | 8006 | Container | Web-based Windows viewer | ## Host Configuration ### Systemd Service: rego-routing.service Location: `/etc/systemd/system/rego-routing.service` This service runs after docker.service and: 1. Adds routes for 172.32.0.0/24 and 10.35.33.0/24 via 172.31.0.10 2. Adds DOCKER-USER iptables rules for forwarding 3. Removes Docker's nft isolation rules that block external access to 172.31.0.10 ```bash # Check status sudo systemctl status rego-routing.service # Restart if needed sudo systemctl restart rego-routing.service ``` ### Client Route (Windows Laptop) Add a persistent route to reach the container network: ```cmd route add 172.31.0.0 mask 255.255.255.0 192.168.0.150 -p ``` Where 192.168.0.150 is the Linux host IP. ## Files ### vpn_scripts/start.sh Startup script that runs before the Windows VM entry.sh: - Installs required packages (socat, openssh-client, netcat-openbsd) - Sets up SSH key for VM access - Waits for Windows VM to boot - Configures iptables MASQUERADE and FORWARD rules - Sets up socat for SSH forwarding (port 2222) - Configures DNAT rules for all IBM i ports **Important**: Uses `return 0` (not `exit 0`) at the end because it's sourced. ### vpn_scripts/vpn-login.js Automated Cisco AnyConnect VPN login: - Connects via WebView DevTools protocol (port 9222) - Handles Microsoft/ADFS authentication - Generates TOTP codes for 2FA - Watchdog mode: monitors VPN every 2 minutes, reconnects if dropped ### vpn_scripts/id_ed25519-lenovo SSH private key for accessing the Windows VM from the container. ## Windows VM Configuration ### SSH Server Windows OpenSSH is configured to listen on port 2222 (not 22) to allow port 22 for IBM i portproxy. Config: `C:\ProgramData\ssh\sshd_config` ``` Port 2222 ``` ### Portproxy Rules Portproxy rules forward IBM i ports through the VPN. These are persistent (stored in registry). ```cmd # View all portproxy rules netsh interface portproxy show all # Add a rule netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=22 connectaddress=10.35.33.230 connectport=22 # Delete all rules netsh interface portproxy reset ``` Rules are defined in: `/etc/runtipi/user-config/runtipi/rego-tunnel/port-proxy.txt` ### IP Helper Service The IP Helper service (iphlpsvc) must be running for portproxy to work: ```cmd net start iphlpsvc ``` ## User Config Location: `/etc/runtipi/user-config/runtipi/rego-tunnel/docker-compose.yml` ```yaml networks: vpn_static-rego: driver: bridge driver_opts: com.docker.network.bridge.name: "br-vpn-rego" ipam: config: - subnet: 172.31.0.0/24 services: rego-tunnel: entrypoint: ["/bin/bash", "-c", "source /vpn_scripts/start.sh; exec /run/entry.sh"] sysctls: - net.ipv4.conf.all.rp_filter=0 - net.ipv4.conf.default.rp_filter=0 cap_add: - NET_ADMIN environment: - VM_NET_IP=172.32.0.20 volumes: - /etc/runtipi/repos/runtipi/apps/rego-tunnel/vpn_scripts:/vpn_scripts:ro networks: vpn_static-rego: ipv4_address: 172.31.0.10 ``` ## Troubleshooting ### Container won't start / restarts immediately Check if start.sh has `exit 0` instead of `return 0` at the end. Since it's sourced, `exit` terminates the parent shell. ### Can't reach container from laptop 1. Check route on laptop: `route print | findstr 172.31` 2. Check rego-routing.service: `sudo systemctl status rego-routing.service` 3. Check if Docker nft rules are blocking: `sudo nft list ruleset | grep 172.31` ### Portproxy not working 1. Restart IP Helper: `net stop iphlpsvc && net start iphlpsvc` 2. Check if SSH is on port 2222: `netstat -an | findstr :22` 3. Verify portproxy rules: `netsh interface portproxy show all` ### VPN not connecting 1. Check vpn-login.js logs in Windows VM 2. Verify time sync (TOTP requires accurate time) 3. Check if VPN credentials in vpn-login.js are correct ### Bridge name too long error Linux bridge names are limited to 15 characters. "br-vpn-static-rego" (18 chars) won't work; use "br-vpn-rego" (11 chars). ## Maintenance ### Updating vpn_scripts 1. Edit files in `/etc/runtipi/repos/runtipi/apps/rego-tunnel/vpn_scripts/` 2. Commit and push to git 3. Run `sudo ./runtipi-cli appstore update` 4. Restart app: `sudo ./runtipi-cli app stop rego-tunnel:runtipi && sudo ./runtipi-cli app start rego-tunnel:runtipi` ### Updating portproxy rules 1. Edit `/etc/runtipi/user-config/runtipi/rego-tunnel/port-proxy.txt` 2. SSH to VM: `ssh -p 2222 docker@172.31.0.10` 3. Reset and re-apply: `netsh interface portproxy reset` then run the commands from port-proxy.txt