{"id":31287228,"url":"https://github.com/cjnuk/wsl2-port-mapper","last_synced_at":"2026-05-19T10:01:31.060Z","repository":{"id":316039502,"uuid":"1061702499","full_name":"cjnuk/wsl2-port-mapper","owner":"cjnuk","description":"Windows service (Go) that manages netsh port forwarding for WSL2 instances with dynamic IPs","archived":false,"fork":false,"pushed_at":"2025-09-22T11:24:19.000Z","size":1308,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-22T11:26:38.293Z","etag":null,"topics":["golang","netsh","port-forwarding","windows","wsl2","wsl2-networking"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cjnuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY-GUIDE.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-22T09:15:46.000Z","updated_at":"2025-09-22T11:24:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"fd7a0e6e-b23b-4950-9dc8-0cfab67c42eb","html_url":"https://github.com/cjnuk/wsl2-port-mapper","commit_stats":null,"previous_names":["cjnuk/wsl2-port-mapper"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cjnuk/wsl2-port-mapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjnuk%2Fwsl2-port-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjnuk%2Fwsl2-port-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjnuk%2Fwsl2-port-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjnuk%2Fwsl2-port-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cjnuk","download_url":"https://codeload.github.com/cjnuk/wsl2-port-mapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cjnuk%2Fwsl2-port-mapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276737524,"owners_count":25695700,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-24T02:00:09.776Z","response_time":97,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","netsh","port-forwarding","windows","wsl2","wsl2-networking"],"created_at":"2025-09-24T11:01:08.346Z","updated_at":"2025-09-24T11:03:03.528Z","avatar_url":"https://github.com/cjnuk.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WSL2 Port Forwarder Service\n\n**Automatically manages port forwarding for WSL2 instances with dynamic IP addresses**\n\n## Overview\n\nWSL2 instances in NAT mode receive dynamic internal IP addresses (172.x.x.x range) that change when Windows reboots, WSL2 instances restart, or the WSL2 subsystem shuts down. This service automatically maintains consistent external access to services running in WSL2 instances without manual intervention.\n\n## Features\n\n- ✅ **Configuration-Driven**: JSON configuration file defines instance and port mappings\n- ✅ **State Reconciliation**: Periodically compares desired vs actual port forwarding state  \n- ✅ **Automatic Correction**: Updates port forwarding rules when WSL2 IP addresses change\n- ✅ **Windows Service**: Runs automatically on system startup with restart on failure\n- ✅ **Live Configuration**: Reloads config file changes without service restart\n- ✅ **Zero Dependencies**: Single executable with no external requirements\n\n## Security and Privacy (IMPORTANT)\n\n⚠️ **DO NOT commit your personal `wsl2-config.json` file!** It contains your private instance names and port mappings.\n\n### Multiple Security Layers:\n- **`.gitignore`**: Blocks ALL `.json` files except `wsl2-config.example.json`\n- **Git hooks**: Pre-commit hooks prevent accidental JSON commits\n- **Secret scanning**: GitHub Actions run Gitleaks to detect sensitive data\n- **Local protection**: Files stored in `%LOCALAPPDATA%\\wsl2-port-mapper\\` are safe\n\n### Safe Configuration:\n1. Copy `wsl2-config.example.json` → `wsl2-config.json` (locally)\n2. Edit with your actual WSL2 instance names and ports\n3. The file is automatically ignored by Git\n4. Alternatively, store it outside the repo entirely\n\n## Quick Start\n\n### Prerequisites\n\n1. **Windows 11 with WSL2** installed and configured\n2. **Administrator privileges** for service installation\n3. **WSL2 in NAT mode** (see WSL Configuration section below)\n\n### Installation\n\n1. **Download/Copy** all files to a directory (e.g., `C:\\WSL2Service\\`)\n2. **Configure** your WSL2 instances and ports in `wsl2-config.json`\n3. **Run as Administrator**: `install-service.bat`\n4. **Start using** your port-forwarded services immediately\n\n### Basic Usage\n\n```bash\n# Validate configuration before using\nwsl2-port-forwarder.exe --validate wsl2-config.json\n\n# Check service status\ncheck-service.bat\n\n# View current port forwarding rules\nnetsh interface portproxy show v4tov4\n\n# Restart service if needed\nnssm restart WSL2PortForwarder\n```\n\n### Configuration Validation\n\n**NEW**: Use `--validate` to check your configuration before deployment:\n\n```bash\nwsl2-port-forwarder.exe --validate wsl2-config.json\n```\n\n**What it checks:**\n- ✅ **JSON syntax and structure** \n- ✅ **Port ranges** (1-65535)\n- ✅ **Instance name validity**\n- ✅ **Firewall configuration validity** (\"local\", \"full\", or omitted)\n- ⚠️ **External port conflicts** (warnings, not errors)\n- ⚠️ **Windows Firewall rules** for configured ports\n- 🎆 **Firewall rule preview** (shows what automatic rules will be created)\n\n**Exit codes:**\n- `0` = Configuration valid, no warnings\n- `1` = Configuration has errors (must fix)\n- `2` = Configuration valid but has warnings\n\n**Example output:**\n```\nWSL2 Port Forwarder - Configuration Validation\n==============================================\nConfig file: wsl2-config.json\n\n✅ Configuration syntax and structure: Valid\n✅ Check interval: 5 seconds\n✅ Configured instances: 3\n\n⚠️  Potential external port conflicts:\n  Port 8080: Ubuntu-Dev, Ubuntu-Staging\n    → First instance (Ubuntu-Dev) will win\n\n⚠️  2 port(s) may be blocked by Windows Firewall:\n  - Port 2201 (TCP) - Will be automatically managed (local mode)\n  - Port 8080 (TCP) - Will be automatically managed (full mode)\n\n🎆 Automatic firewall rules that will be created:\n  Port 2201: local network access (LocalSubnet)\n  Port 8080: any address access (any)\n\n⚠️  Note: Admin privileges required for automatic firewall rule creation\n    Run as Administrator for automatic firewall management\n\n⚠️  Configuration is valid but has warnings\n```\n\n## WSL Configuration\n\nFor optimal compatibility, update your `~/.wslconfig` (Windows user home) to use NAT networking:\n\n```ini\n[wsl2]\nnetworkingMode=nat\nmemory=8GB\nprocessors=4\n\n[experimental]  \nautoMemoryReclaim=dropCache\nsparseVhd=true\n```\n\nAfter updating, restart WSL2:\n```bash\nwsl --shutdown\n# Wait 10 seconds, then start your instances\n```\n\n## Configuration File\n\n### Example `wsl2-config.json`\n\n```json\n{\n  \"check_interval_seconds\": 5,\n  \"instances\": [\n    {\n      \"name\": \"Ubuntu-AI\",\n      \"comment\": \"AI/ML development instance\",\n      \"ports\": [\n        {\n          \"port\": 2201,\n          \"internal_port\": 22,\n          \"comment\": \"SSH access (external 2201 -\u003e internal 22)\"\n        },\n        {\n          \"port\": 8001,\n          \"comment\": \"FastAPI server (same port internally)\"\n        },\n        {\n          \"port\": 8888,\n          \"comment\": \"Jupyter notebook\"\n        }\n      ]\n    },\n    {\n      \"name\": \"Ubuntu-GPU\", \n      \"comment\": \"CUDA development\",\n      \"ports\": [\n        {\n          \"port\": 2202,\n          \"internal_port\": 22,\n          \"comment\": \"SSH access (external 2202 -\u003e internal 22)\"\n        },\n        {\n          \"port\": 8002,\n          \"internal_port\": 6006,\n          \"comment\": \"TensorBoard (external 8002 -\u003e internal 6006)\"\n        }\n      ]\n    }\n  ]\n}\n```\n\n### Configuration Rules\n\n- ✅ **check_interval_seconds**: 1-3600 seconds (how often to check for changes)\n- ✅ **instance names**: Must match exact WSL2 distribution names (`wsl -l`)\n- ✅ **port numbers**: 1-65535, duplicate **external** ports allowed (see Conflict Resolution)\n- ✅ **internal_port** (optional): Target port inside WSL instance; defaults to same as `port`\n- ✅ **firewall** (optional): Automatic Windows Firewall management - \"local\" or \"full\"\n- ✅ **comments**: Optional for both instances and ports\n- ✅ **live reload**: Changes take effect on next check cycle (no restart needed)\n\n### External vs Internal Port Mapping\n\n**NEW FEATURE**: You can now map different external and internal ports!\n\n- **`port`**: External port on Windows host (required)\n- **`internal_port`**: Target port inside WSL instance (optional, defaults to `port`)\n\n**Key Benefits:**\n- Multiple WSL instances can use standard internal ports (like SSH port 22)\n- External ports remain unique for each instance\n- Backward compatible - existing configs work unchanged\n\n**Examples:**\n```json\n// SSH access to different instances, all using port 22 internally\n{ \"port\": 2201, \"internal_port\": 22, \"comment\": \"SSH to Ubuntu-AI\" }\n{ \"port\": 2202, \"internal_port\": 22, \"comment\": \"SSH to Ubuntu-GPU\" }\n{ \"port\": 2203, \"internal_port\": 22, \"comment\": \"SSH to Ubuntu-Web\" }\n\n// Web services using standard HTTP/HTTPS ports internally\n{ \"port\": 8080, \"internal_port\": 80,  \"comment\": \"HTTP server\" }\n{ \"port\": 8443, \"internal_port\": 443, \"comment\": \"HTTPS server\" }\n\n// Same external and internal port (legacy behavior)\n{ \"port\": 3000, \"comment\": \"Node.js dev server\" }\n\n// Allowed: Same external port for different instances (runtime conflict resolution)\n{ \"port\": 2201, \"internal_port\": 22, \"comment\": \"Dev SSH\" },    // Ubuntu-Dev\n{ \"port\": 2201, \"internal_port\": 22, \"comment\": \"Staging SSH\" } // Ubuntu-Staging\n```\n\n### Runtime Conflict Resolution\n\n**NEW**: Duplicate external ports are now allowed! This enables flexible scenarios:\n\n**Common Use Cases:**\n- **Dev/Staging/Prod environments** that don't run simultaneously\n- **Seasonal services** (e.g., tax software active only during tax season)\n- **Testing configurations** where you switch between different setups\n\n**How it works:**\n- Multiple instances can specify the same external port\n- If multiple instances with the same external port run simultaneously:\n  - ✅ **First instance in config file wins** (gets the port)\n  - ⚠️ **Later instances are ignored** (with warning logs)\n  - 📢 **Conflict summary displayed** during operation\n\n**Example Scenario:**\n```bash\n# Both instances configured for external port 8080\n# If both are running simultaneously:\nInstance 'Ubuntu-Dev' port 8080 -\u003e 172.18.144.5:80     ✅ Active\nInstance 'Ubuntu-Staging' port 8080 -\u003e ignored         ⚠️ Ignored (logged)\n```\n\n### Automatic Firewall Management\n\n**NEW**: Automatic Windows Firewall rule creation for your ports!\n\n**Configuration Options:**\n- **Omitted/Empty**: Warn if port blocked (current behavior)\n- **\"local\"**: Create firewall rule allowing **local network** traffic only\n- **\"full\"**: Create firewall rule allowing traffic from **any address**\n\n**Security Levels:**\n```json\n// No automatic firewall management (default)\n{ \"port\": 8080, \"comment\": \"Manual firewall setup required\" }\n\n// Local network only (recommended for SSH, databases)\n{ \"port\": 2201, \"internal_port\": 22, \"firewall\": \"local\", \"comment\": \"SSH - local network only\" }\n\n// Internet accessible (for web services)\n{ \"port\": 8080, \"internal_port\": 80, \"firewall\": \"full\", \"comment\": \"HTTP - internet accessible\" }\n```\n\n**Security Implications:**\n- 🔒 **\"local\"**: Safe for internal services (SSH, databases, development servers)\n- 🌐 **\"full\"**: Exposes service to internet - use carefully!\n- ⚠️ **Admin required**: Firewall rule creation needs Administrator privileges\n\n**What happens:**\n1. ✅ Port forwarding created successfully \n2. 🔥 Firewall rule created automatically\n3. ℹ️ Detailed logging of firewall operations\n4. 💡 Manual command provided if automatic creation fails\n\n## Service Management\n\n### Installation Scripts\n\n| Script | Purpose |\n|--------|---------|\n| `install-service.bat` | Install and configure Windows service |\n| `uninstall-service.bat` | Remove service and optionally logs |\n| `check-service.bat` | Display service status and recent logs |\n\n### Manual Commands\n\n```bash\n# Service control\nnssm start WSL2PortForwarder\nnssm stop WSL2PortForwarder  \nnssm restart WSL2PortForwarder\n\n# Windows service commands\nsc query WSL2PortForwarder\nsc start WSL2PortForwarder\nsc stop WSL2PortForwarder\n```\n\n### Log Files\n\nLocated in `logs/` directory:\n- **service-output.log**: Normal operation output\n- **service-error.log**: Error messages and warnings\n\nLogs rotate automatically at 1MB with older versions preserved.\n\n## Troubleshooting\n\n### Common Issues\n\n**Service won't start:**\n- Verify WSL2 is installed: `wsl --version`\n- Check config file syntax: valid JSON format\n- Ensure no port conflicts with existing applications\n- Run `check-service.bat` to see recent errors\n\n**Port forwarding not working:**\n- Confirm WSL2 instances are running: `wsl -l --running`\n- Verify instance names match exactly (case-sensitive)\n- Check Windows Firewall isn't blocking ports\n- Ensure services are listening on 0.0.0.0 (not just 127.0.0.1) inside WSL2\n\n**Config changes not taking effect:**\n- Wait for next check cycle (5 seconds by default)\n- Verify JSON syntax is valid\n- Check service logs for parsing errors\n\n### Debug Steps\n\n1. **Check WSL2 status**: `wsl -l -v`\n2. **Verify network mode**: Check `~/.wslconfig` has `networkingMode=nat`\n3. **Test WSL2 connectivity**: From WSL2, ping Windows host\n4. **Check current forwarding**: `netsh interface portproxy show v4tov4`\n5. **Review service logs**: `check-service.bat`\n\n## Directory Structure\n\n```\nWSL2Service/\n├── wsl2-port-forwarder.exe    # Main service executable\n├── wsl2-config.json           # Configuration file\n├── nssm.exe                   # Service manager utility\n├── install-service.bat        # Installation script\n├── uninstall-service.bat      # Removal script\n├── check-service.bat          # Status checker\n├── README.md                  # This documentation\n└── logs/\n    ├── service-output.log     # Service output\n    └── service-error.log      # Service errors\n```\n\n## Technical Details\n\n### How It Works\n\n1. **Discovery**: Queries WSL2 for running instances using `wsl --list --running`\n2. **IP Detection**: Gets current IP for each instance via `wsl -d \u003cname\u003e -- hostname -I` \n3. **State Comparison**: Compares desired config vs current `netsh` forwarding rules\n4. **Reconciliation**: Adds/updates/removes port forwarding rules as needed\n5. **Wait \u0026 Repeat**: Sleeps for configured interval and repeats\n\n### Port Forwarding Commands\n\n```bash\n# Add rule\nnetsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=172.18.144.5\n\n# Remove rule  \nnetsh interface portproxy delete v4tov4 listenport=8080\n\n# List all rules\nnetsh interface portproxy show v4tov4\n```\n\n### Performance\n\n- **Memory Usage**: \u003c 10MB typical, \u003c 50MB maximum\n- **CPU Usage**: \u003c 1% average, \u003c 5% during checks\n- **Network Impact**: None (only local command execution)\n- **Scalability**: Supports up to 50 instances, 100 ports each\n\n## Cross-Host Deployment\n\nThis service works on any Windows 11 system with WSL2. To deploy:\n\n1. **Copy entire directory** to target Windows system\n2. **Update `wsl2-config.json`** for target system's WSL2 instances\n3. **Run `install-service.bat`** as Administrator\n4. **Service runs automatically** on startup\n\nNo modifications to scripts or executables needed - everything uses relative paths.\n\n## License \u0026 Support\n\nBuilt according to the WSL2-Port-Forwarder-Specification.md requirements.\n\nFor issues:\n1. Run `check-service.bat` to gather diagnostic info\n2. Check logs in `logs/` directory\n3. Verify WSL2 configuration and instance names\n4. Test port accessibility from within WSL2 instances\n\n## Version Info\n\n- **Build**: Phase 2 Complete (Service Integration)\n- **Go Version**: 1.25.1\n- **Target**: Windows 11 AMD64 with WSL2\n- **Dependencies**: None (single executable + NSSM)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjnuk%2Fwsl2-port-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcjnuk%2Fwsl2-port-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcjnuk%2Fwsl2-port-mapper/lists"}