# 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
