diff --git a/Data/Agent/Roles/role_VpnShell.py b/Data/Agent/Roles/role_VpnShell.py index c2e0bede..7aa57fc9 100644 --- a/Data/Agent/Roles/role_VpnShell.py +++ b/Data/Agent/Roles/role_VpnShell.py @@ -21,6 +21,8 @@ import os ROLE_NAME = "VpnShell" ROLE_CONTEXTS = ["system"] +FIREWALL_RULE_NAME = "Borealis - WireGuard - Shell" +FIREWALL_REMOTE_ADDRESS = "10.255.0.1/32" def _log_path() -> Path: @@ -55,6 +57,30 @@ def _resolve_shell_port() -> int: return value +def _ensure_firewall_rule(port: int) -> None: + if os.name != "nt": + return + rule_name = FIREWALL_RULE_NAME.replace("'", "''") + command = ( + "Remove-NetFirewallRule -DisplayName '{name}' -ErrorAction SilentlyContinue; " + "New-NetFirewallRule -DisplayName '{name}' -Direction Inbound -Action Allow " + "-Protocol TCP -LocalPort {port} -RemoteAddress {remote} -Profile Any" + ).format(name=rule_name, port=port, remote=FIREWALL_REMOTE_ADDRESS) + try: + result = subprocess.run( + ["powershell.exe", "-NoProfile", "-Command", command], + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0: + _write_log(f"Failed to ensure firewall rule for VPN shell: {result.stderr.strip()}") + else: + _write_log(f"Ensured firewall rule for VPN shell on port {port}.") + except Exception as exc: + _write_log(f"Failed to ensure firewall rule for VPN shell: {exc}") + + class ShellSession: def __init__(self, conn: socket.socket, address: tuple[str, int]) -> None: self.conn = conn @@ -163,6 +189,7 @@ class ShellServer: def __init__(self, host: str = "0.0.0.0", port: Optional[int] = None) -> None: self.host = host self.port = port or _resolve_shell_port() + _ensure_firewall_rule(self.port) self._thread = threading.Thread(target=self._serve, daemon=True) self._thread.start() _write_log(f"VPN shell server listening on {self.host}:{self.port}") diff --git a/Docs/Codex/WireGuard_Troubleshooting.md b/Docs/Codex/WireGuard_Troubleshooting.md index fd42164d..0fc72d0d 100644 --- a/Docs/Codex/WireGuard_Troubleshooting.md +++ b/Docs/Codex/WireGuard_Troubleshooting.md @@ -60,13 +60,14 @@ You are a new Codex agent working in d:\Github\Borealis. Please do the following Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under Agent\. -## Current Symptoms (2026-01-13 21:22) +## Current Symptoms (2026-01-13 23:40) -- Engine installs WireGuard listener service, but it immediately stops. -- Engine log error: connect_failed: WireGuard tunnel service WireGuardTunnel$borealis-wg failed to start (state=STOPPED). -- WireGuard log shows: "Invalid key for [Interface] section: saveconfig" (fixed by removing SaveConfig). -- Agent config shows endpoint set to 10.0.0.54:30000 and sends keepalives, but wg.exe show reports 0 B received (no handshake) because the Engine listener is down. -- Local Engine + local Agent (same device) works; remote Engine -> remote Agent shell is the failing case. +- `wg.exe show` confirms the tunnel is up with a recent handshake and RX/TX bytes on both Engine and Agent. +- Engine sees the remote agent peer at 10.0.0.55:59733; agent sees the engine endpoint at 10.0.0.54:30000. +- ICMP over the tunnel works: `Test-NetConnection -ComputerName 10.255.0.2 -Port 47002` reports `PingSucceeded=True` but `TcpTestSucceeded=False`. +- Remote shell connects to 10.255.0.2:47002 still time out; agent logs show the shell server listening but no accepted connections. +- Agent session idles out; the on-disk `Borealis.conf` reverts to idle-only [Interface] after stop (no [Peer]). +- `wireguard.exe /dumplog /tail` fails with "Stdout must be set" when run from PowerShell. ## Key Paths @@ -97,7 +98,8 @@ Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under - sc.exe query "WireGuardTunnel$borealis-wg" - netstat -ano -p udp | findstr :30000 - Engine WireGuard log tail: - - "C:\\Program Files\\WireGuard\\wireguard.exe" /dumplog /tail + - cmd /c ""C:\\Program Files\\WireGuard\\wireguard.exe" /dumplog /tail > %TEMP%\\wg-tail.log" + - powershell -NoProfile -Command "& 'C:\\Program Files\\WireGuard\\wireguard.exe' /dumplog /tail 2>&1 | Out-File $env:TEMP\\wg-tail.log" - Agent tunnel state (remote, via Z:\ logs): - Z:\Agent\Logs\VPN_Tunnel\tunnel.log - Z:\Agent\Logs\VPN_Tunnel\remote_shell.log @@ -105,6 +107,8 @@ Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under ## Current Blockers / Next Steps -1) Re-test after the SaveConfig removal to confirm the Engine listener stays running and UDP/30000 binds. -2) If the service still stops, use wireguard.exe /dumplog /tail to capture the exact failure. -3) Once the Engine listener stays up, confirm that wg.exe show shows received bytes/handshake on both Engine and Agent, then retry remote shell. +1) During an active session, run `Test-NetConnection -ComputerName 10.255.0.2 -Port 47002` on the Engine and confirm it reaches the agent. +2) If the TCP test times out, inspect agent-side firewall rules; the shell server listens but may be blocked on the WireGuard adapter. + - Added a candidate fix in `Data/Agent/Roles/role_VpnShell.py` to add an inbound firewall rule for TCP/47002 from 10.255.0.1/32. +3) While the session is active, confirm `Agent\Borealis\Settings\WireGuard\Borealis.conf` includes a [Peer] with endpoint/AllowedIPs (it reverts to idle config after stop). +4) Capture engine + agent tunnel/shell logs around a failed shell open attempt and re-check WireGuard service state.