mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2026-02-04 05:00:32 -07:00
Additional Networking Changes to WireGuard
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# ======================================================
|
# ======================================================
|
||||||
# Data\Agent\Roles\role_VpnShell.py
|
# Data\Agent\Roles\role_RemotePowershell.py
|
||||||
# Description: PowerShell TCP server for VPN shell access (Engine connects over WireGuard /32).
|
# Description: PowerShell TCP server for VPN shell access (Engine connects over WireGuard /32).
|
||||||
#
|
#
|
||||||
# API Endpoints (if applicable): None
|
# API Endpoints (if applicable): None
|
||||||
@@ -19,19 +19,19 @@ from pathlib import Path
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
import os
|
import os
|
||||||
|
|
||||||
ROLE_NAME = "VpnShell"
|
ROLE_NAME = "RemotePowershell"
|
||||||
ROLE_CONTEXTS = ["system"]
|
ROLE_CONTEXTS = ["system"]
|
||||||
FIREWALL_RULE_NAME = "Borealis - WireGuard - Shell"
|
|
||||||
FIREWALL_REMOTE_ADDRESS = "10.255.0.1/32"
|
|
||||||
|
|
||||||
|
|
||||||
def _log_path() -> Path:
|
def _log_path() -> Path:
|
||||||
|
# Keep shell logs alongside other VPN tunnel artifacts.
|
||||||
root = Path(__file__).resolve().parents[2] / "Logs" / "VPN_Tunnel"
|
root = Path(__file__).resolve().parents[2] / "Logs" / "VPN_Tunnel"
|
||||||
root.mkdir(parents=True, exist_ok=True)
|
root.mkdir(parents=True, exist_ok=True)
|
||||||
return root / "remote_shell.log"
|
return root / "remote_shell.log"
|
||||||
|
|
||||||
|
|
||||||
def _write_log(message: str) -> None:
|
def _write_log(message: str) -> None:
|
||||||
|
# Lightweight file logger for the shell bridge; avoid raising on failures.
|
||||||
ts = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())
|
ts = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())
|
||||||
try:
|
try:
|
||||||
_log_path().open("a", encoding="utf-8").write(f"[{ts}] [vpn-shell] {message}\n")
|
_log_path().open("a", encoding="utf-8").write(f"[{ts}] [vpn-shell] {message}\n")
|
||||||
@@ -40,13 +40,16 @@ def _write_log(message: str) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _b64encode(data: bytes) -> str:
|
def _b64encode(data: bytes) -> str:
|
||||||
|
# Wire payloads are JSON lines; encode binary stdout safely.
|
||||||
return base64.b64encode(data).decode("ascii").strip()
|
return base64.b64encode(data).decode("ascii").strip()
|
||||||
|
|
||||||
|
|
||||||
def _b64decode(value: str) -> bytes:
|
def _b64decode(value: str) -> bytes:
|
||||||
|
# Decode base64-encoded stdin payloads from the engine.
|
||||||
return base64.b64decode(value.encode("ascii"))
|
return base64.b64decode(value.encode("ascii"))
|
||||||
|
|
||||||
def _resolve_shell_port() -> int:
|
def _resolve_shell_port() -> int:
|
||||||
|
# Use the configured port when present, otherwise default to 47002.
|
||||||
raw = os.environ.get("BOREALIS_WIREGUARD_SHELL_PORT")
|
raw = os.environ.get("BOREALIS_WIREGUARD_SHELL_PORT")
|
||||||
try:
|
try:
|
||||||
value = int(raw) if raw is not None else 47002
|
value = int(raw) if raw is not None else 47002
|
||||||
@@ -57,30 +60,6 @@ def _resolve_shell_port() -> int:
|
|||||||
return value
|
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:
|
class ShellSession:
|
||||||
def __init__(self, conn: socket.socket, address: tuple[str, int]) -> None:
|
def __init__(self, conn: socket.socket, address: tuple[str, int]) -> None:
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
@@ -93,6 +72,7 @@ class ShellSession:
|
|||||||
self.output_bytes = 0
|
self.output_bytes = 0
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
|
# Spawn an interactive PowerShell process and bridge stdin/stdout.
|
||||||
_write_log(f"Shell session starting for {self.address[0]}:{self.address[1]}")
|
_write_log(f"Shell session starting for {self.address[0]}:{self.address[1]}")
|
||||||
self.proc = subprocess.Popen(
|
self.proc = subprocess.Popen(
|
||||||
["powershell.exe", "-NoLogo", "-NoProfile", "-NoExit", "-Command", "-"],
|
["powershell.exe", "-NoLogo", "-NoProfile", "-NoExit", "-Command", "-"],
|
||||||
@@ -106,6 +86,7 @@ class ShellSession:
|
|||||||
self._writer_loop()
|
self._writer_loop()
|
||||||
|
|
||||||
def _reader_loop(self) -> None:
|
def _reader_loop(self) -> None:
|
||||||
|
# Forward PowerShell stdout to the engine as JSONL payloads.
|
||||||
if not self.proc or not self.proc.stdout:
|
if not self.proc or not self.proc.stdout:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@@ -126,6 +107,7 @@ class ShellSession:
|
|||||||
_write_log(f"Shell stdout error: {exc}")
|
_write_log(f"Shell stdout error: {exc}")
|
||||||
|
|
||||||
def _writer_loop(self) -> None:
|
def _writer_loop(self) -> None:
|
||||||
|
# Read JSONL stdin from the engine and feed it into PowerShell.
|
||||||
buffer = b""
|
buffer = b""
|
||||||
try:
|
try:
|
||||||
while not self._stop.is_set():
|
while not self._stop.is_set():
|
||||||
@@ -165,6 +147,7 @@ class ShellSession:
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
|
# Ensure the TCP connection and PowerShell child are cleaned up.
|
||||||
self._stop.set()
|
self._stop.set()
|
||||||
try:
|
try:
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
@@ -189,12 +172,12 @@ class ShellServer:
|
|||||||
def __init__(self, host: str = "0.0.0.0", port: Optional[int] = None) -> None:
|
def __init__(self, host: str = "0.0.0.0", port: Optional[int] = None) -> None:
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port or _resolve_shell_port()
|
self.port = port or _resolve_shell_port()
|
||||||
_ensure_firewall_rule(self.port)
|
|
||||||
self._thread = threading.Thread(target=self._serve, daemon=True)
|
self._thread = threading.Thread(target=self._serve, daemon=True)
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
_write_log(f"VPN shell server listening on {self.host}:{self.port}")
|
_write_log(f"VPN shell server listening on {self.host}:{self.port}")
|
||||||
|
|
||||||
def _serve(self) -> None:
|
def _serve(self) -> None:
|
||||||
|
# Accept TCP shell connections; restrict to the WireGuard subnet.
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
|
||||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
server.bind((self.host, self.port))
|
server.bind((self.host, self.port))
|
||||||
@@ -213,6 +196,7 @@ class ShellServer:
|
|||||||
|
|
||||||
class Role:
|
class Role:
|
||||||
def __init__(self, ctx) -> None:
|
def __init__(self, ctx) -> None:
|
||||||
|
# Start the shell server immediately when the role loads.
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.server = ShellServer()
|
self.server = ShellServer()
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@ TUNNEL_NAME = "Borealis"
|
|||||||
TUNNEL_DISPLAY_NAME = "Borealis"
|
TUNNEL_DISPLAY_NAME = "Borealis"
|
||||||
SERVICE_DISPLAY_NAME = "Borealis - WireGuard - Agent"
|
SERVICE_DISPLAY_NAME = "Borealis - WireGuard - Agent"
|
||||||
TUNNEL_IDLE_ADDRESS = "169.254.255.254/32"
|
TUNNEL_IDLE_ADDRESS = "169.254.255.254/32"
|
||||||
|
FIREWALL_RULE_NAME = "Borealis - WireGuard - Shell"
|
||||||
|
|
||||||
|
|
||||||
def _log_path() -> Path:
|
def _log_path() -> Path:
|
||||||
@@ -108,6 +109,17 @@ def _generate_client_keys(root: Path) -> Dict[str, str]:
|
|||||||
return {"private": priv, "public": pub}
|
return {"private": priv, "public": pub}
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_shell_port() -> int:
|
||||||
|
raw = os.environ.get("BOREALIS_WIREGUARD_SHELL_PORT")
|
||||||
|
try:
|
||||||
|
value = int(raw) if raw is not None else 47002
|
||||||
|
except Exception:
|
||||||
|
value = 47002
|
||||||
|
if value < 1 or value > 65535:
|
||||||
|
return 47002
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class SessionConfig:
|
class SessionConfig:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -254,6 +266,63 @@ class WireGuardClient:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _normalize_firewall_remote(self, allowed_ips: Optional[str]) -> Optional[str]:
|
||||||
|
if not allowed_ips:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
network = ipaddress.ip_network(str(allowed_ips).strip(), strict=False)
|
||||||
|
except Exception:
|
||||||
|
_write_log(f"Refusing to apply shell firewall rule; invalid allowed_ips={allowed_ips}.")
|
||||||
|
return None
|
||||||
|
if network.prefixlen != 32:
|
||||||
|
_write_log(f"Refusing to apply shell firewall rule; allowed_ips not /32: {network}.")
|
||||||
|
return None
|
||||||
|
return str(network)
|
||||||
|
|
||||||
|
def _ensure_shell_firewall(self, allowed_ips: Optional[str]) -> None:
|
||||||
|
if os.name != "nt":
|
||||||
|
return
|
||||||
|
remote = self._normalize_firewall_remote(allowed_ips)
|
||||||
|
if not remote:
|
||||||
|
return
|
||||||
|
rule_name = FIREWALL_RULE_NAME.replace("'", "''")
|
||||||
|
port = _resolve_shell_port()
|
||||||
|
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=remote)
|
||||||
|
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 shell firewall rule: {result.stderr.strip()}")
|
||||||
|
else:
|
||||||
|
_write_log(f"Ensured shell firewall rule for {remote} on port {port}.")
|
||||||
|
except Exception as exc:
|
||||||
|
_write_log(f"Failed to ensure shell firewall rule: {exc}")
|
||||||
|
|
||||||
|
def _remove_shell_firewall(self) -> None:
|
||||||
|
if os.name != "nt":
|
||||||
|
return
|
||||||
|
rule_name = FIREWALL_RULE_NAME.replace("'", "''")
|
||||||
|
command = "Remove-NetFirewallRule -DisplayName '{name}' -ErrorAction SilentlyContinue".format(
|
||||||
|
name=rule_name
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
subprocess.run(
|
||||||
|
["powershell.exe", "-NoProfile", "-Command", command],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def _service_exists(self) -> bool:
|
def _service_exists(self) -> bool:
|
||||||
code, _, _ = self._run(["sc.exe", "query", self._service_id()])
|
code, _, _ = self._run(["sc.exe", "query", self._service_id()])
|
||||||
if code == 0:
|
if code == 0:
|
||||||
@@ -447,6 +516,7 @@ class WireGuardClient:
|
|||||||
self._restart_service()
|
self._restart_service()
|
||||||
self._ensure_adapter_name()
|
self._ensure_adapter_name()
|
||||||
self._ensure_service_display_name()
|
self._ensure_service_display_name()
|
||||||
|
self._ensure_shell_firewall(session.allowed_ips)
|
||||||
|
|
||||||
self.session = session
|
self.session = session
|
||||||
self.idle_deadline = time.time() + max(60, session.idle_seconds)
|
self.idle_deadline = time.time() + max(60, session.idle_seconds)
|
||||||
@@ -455,6 +525,7 @@ class WireGuardClient:
|
|||||||
|
|
||||||
def stop_session(self, reason: str = "stop", ignore_missing: bool = False) -> None:
|
def stop_session(self, reason: str = "stop", ignore_missing: bool = False) -> None:
|
||||||
with self._session_lock:
|
with self._session_lock:
|
||||||
|
self._remove_shell_firewall()
|
||||||
if not self._service_exists():
|
if not self._service_exists():
|
||||||
if not ignore_missing:
|
if not ignore_missing:
|
||||||
_write_log("WireGuard tunnel service not found when stopping session.")
|
_write_log("WireGuard tunnel service not found when stopping session.")
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ API_LOG_FILE_PATH = LOG_ROOT / "api.log"
|
|||||||
VPN_TUNNEL_LOG_FILE_PATH = LOG_ROOT / "VPN_Tunnel" / "tunnel.log"
|
VPN_TUNNEL_LOG_FILE_PATH = LOG_ROOT / "VPN_Tunnel" / "tunnel.log"
|
||||||
DEFAULT_WIREGUARD_PORT = 30000
|
DEFAULT_WIREGUARD_PORT = 30000
|
||||||
DEFAULT_WIREGUARD_ENGINE_VIRTUAL_IP = "10.255.0.1/32"
|
DEFAULT_WIREGUARD_ENGINE_VIRTUAL_IP = "10.255.0.1/32"
|
||||||
DEFAULT_WIREGUARD_PEER_NETWORK = "10.255.0.0/24"
|
DEFAULT_WIREGUARD_PEER_NETWORK = "10.255.0.0/16"
|
||||||
DEFAULT_WIREGUARD_SHELL_PORT = 47002
|
DEFAULT_WIREGUARD_SHELL_PORT = 47002
|
||||||
DEFAULT_WIREGUARD_ACL_WINDOWS = (3389, 5985, 5986, 5900, 3478, DEFAULT_WIREGUARD_SHELL_PORT)
|
DEFAULT_WIREGUARD_ACL_WINDOWS = (3389, 5985, 5986, 5900, 3478, DEFAULT_WIREGUARD_SHELL_PORT)
|
||||||
VPN_SERVER_CERT_ROOT = PROJECT_ROOT / "Engine" / "Certificates" / "VPN_Server"
|
VPN_SERVER_CERT_ROOT = PROJECT_ROOT / "Engine" / "Certificates" / "VPN_Server"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Use this doc for agent-only work (Borealis agent runtime under `Data/Agent` →
|
|||||||
|
|
||||||
## Reverse VPN Tunnels
|
## Reverse VPN Tunnels
|
||||||
- WireGuard reverse VPN design and lifecycle live in `Docs/Codex/REVERSE_TUNNELS.md` and `Docs/Codex/Reverse_VPN_Tunnel_Deployment.md`.
|
- WireGuard reverse VPN design and lifecycle live in `Docs/Codex/REVERSE_TUNNELS.md` and `Docs/Codex/Reverse_VPN_Tunnel_Deployment.md`.
|
||||||
- Agent roles: `Data/Agent/Roles/role_WireGuardTunnel.py` (tunnel lifecycle) and `Data/Agent/Roles/role_VpnShell.py` (VPN PowerShell TCP server).
|
- Agent roles: `Data/Agent/Roles/role_WireGuardTunnel.py` (tunnel lifecycle) and `Data/Agent/Roles/role_RemotePowershell.py` (VPN PowerShell TCP server).
|
||||||
|
|
||||||
## Execution Contexts & Roles
|
## Execution Contexts & Roles
|
||||||
- Auto-discovers roles from `Data/Agent/Roles/`; no loader changes needed.
|
- Auto-discovers roles from `Data/Agent/Roles/`; no loader changes needed.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ This document is the reference for Borealis reverse VPN tunnels built on WireGua
|
|||||||
## 4) Agent Components
|
## 4) Agent Components
|
||||||
- Tunnel lifecycle: `Data/Agent/Roles/role_WireGuardTunnel.py`
|
- Tunnel lifecycle: `Data/Agent/Roles/role_WireGuardTunnel.py`
|
||||||
- Validates orchestration tokens, starts/stops WireGuard client service, enforces idle.
|
- Validates orchestration tokens, starts/stops WireGuard client service, enforces idle.
|
||||||
- Shell server: `Data/Agent/Roles/role_VpnShell.py`
|
- Shell server: `Data/Agent/Roles/role_RemotePowershell.py`
|
||||||
- TCP PowerShell server bound to `0.0.0.0:47002`, restricted to VPN subnet (10.255.x.x).
|
- TCP PowerShell server bound to `0.0.0.0:47002`, restricted to VPN subnet (10.255.x.x).
|
||||||
- Logging: `Agent/Logs/VPN_Tunnel/tunnel.log` (tunnel lifecycle) and `Agent/Logs/VPN_Tunnel/remote_shell.log` (shell I/O).
|
- Logging: `Agent/Logs/VPN_Tunnel/tunnel.log` (tunnel lifecycle) and `Agent/Logs/VPN_Tunnel/remote_shell.log` (shell I/O).
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ You are a new Codex agent working in d:\Github\Borealis. Please do the following
|
|||||||
- Endpoint override: if Engine sends localhost, use host from server_url.txt and port from the token.
|
- Endpoint override: if Engine sends localhost, use host from server_url.txt and port from the token.
|
||||||
- Config path preference: Agent\Borealis\Settings\WireGuard.
|
- Config path preference: Agent\Borealis\Settings\WireGuard.
|
||||||
- Service display name set to "Borealis - WireGuard - Agent".
|
- Service display name set to "Borealis - WireGuard - Agent".
|
||||||
|
- Applies/removes the VPN shell firewall rule using the engine /32 from allowed_ips.
|
||||||
- Data/Engine/services/VPN/wireguard_server.py
|
- Data/Engine/services/VPN/wireguard_server.py
|
||||||
- Engine config path: Engine\WireGuard\borealis-wg.conf (project root only).
|
- Engine config path: Engine\WireGuard\borealis-wg.conf (project root only).
|
||||||
- Removed invalid "SaveConfig = false" line (WireGuard rejected it).
|
- Removed invalid "SaveConfig = false" line (WireGuard rejected it).
|
||||||
@@ -60,19 +61,16 @@ 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\.
|
Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under Agent\.
|
||||||
|
|
||||||
## Current Symptoms (2026-01-13 23:40)
|
## Current Symptoms (2026-01-14 00:05)
|
||||||
|
|
||||||
- `wg.exe show` confirms the tunnel is up with a recent handshake and RX/TX bytes on both Engine and Agent.
|
- Tunnel handshakes are healthy; TCP shell connectivity succeeds after adding a firewall rule for TCP/47002 from the engine /32.
|
||||||
- Engine sees the remote agent peer at 10.0.0.55:59733; agent sees the engine endpoint at 10.0.0.54:30000.
|
- The firewall rule is now applied/removed by `role_WireGuardTunnel.py` using the engine /32 in the `allowed_ips` payload.
|
||||||
- ICMP over the tunnel works: `Test-NetConnection -ComputerName 10.255.0.2 -Port 47002` reports `PingSucceeded=True` but `TcpTestSucceeded=False`.
|
- `wireguard.exe /dumplog /tail` still fails with "Stdout must be set" when run from PowerShell (use file redirection).
|
||||||
- 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
|
## Key Paths
|
||||||
|
|
||||||
- Agent WireGuard role: Data/Agent/Roles/role_WireGuardTunnel.py
|
- Agent WireGuard role: Data/Agent/Roles/role_WireGuardTunnel.py
|
||||||
- Agent VPN shell role: Data/Agent/Roles/role_VpnShell.py
|
- Agent VPN shell role: Data/Agent/Roles/role_RemotePowershell.py
|
||||||
- Engine WireGuard manager: Data/Engine/services/VPN/wireguard_server.py
|
- Engine WireGuard manager: Data/Engine/services/VPN/wireguard_server.py
|
||||||
- Engine tunnel service: Data/Engine/services/VPN/vpn_tunnel_service.py
|
- Engine tunnel service: Data/Engine/services/VPN/vpn_tunnel_service.py
|
||||||
- Agent tunnel logs: Z:\Agent\Logs\VPN_Tunnel\tunnel.log
|
- Agent tunnel logs: Z:\Agent\Logs\VPN_Tunnel\tunnel.log
|
||||||
@@ -107,8 +105,7 @@ Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under
|
|||||||
|
|
||||||
## Current Blockers / Next Steps
|
## Current Blockers / Next Steps
|
||||||
|
|
||||||
1) During an active session, run `Test-NetConnection -ComputerName 10.255.0.2 -Port 47002` on the Engine and confirm it reaches the agent.
|
1) Ensure the agent runtime is re-staged so `role_WireGuardTunnel.py` applies the shell firewall rule on tunnel start.
|
||||||
2) If the TCP test times out, inspect agent-side firewall rules; the shell server listens but may be blocked on the WireGuard adapter.
|
2) During an active session, run `Test-NetConnection -ComputerName 10.255.0.2 -Port 47002` on the Engine and confirm it reaches the agent.
|
||||||
- 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).
|
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.
|
4) Capture engine + agent tunnel/shell logs around a failed shell open attempt and re-check WireGuard service state if issues persist.
|
||||||
|
|||||||
Reference in New Issue
Block a user