tunnels: optional remote_host forward destination (default 127.0.0.1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 14:18:18 +02:00
parent 00671f5133
commit ce0aa728b1
4 changed files with 19 additions and 2 deletions

View File

@@ -107,6 +107,7 @@ def _parse_tunnel(name: str, data: dict) -> TunnelConfig:
reconnect=reconnect, reconnect=reconnect,
health_check=health_check, health_check=health_check,
direction=direction, direction=direction,
remote_host=str(data.get("remote_host", "127.0.0.1")),
cert_command=cert_command, cert_command=cert_command,
) )

View File

@@ -29,9 +29,9 @@ def build_ssh_command(cfg: TunnelConfig, cert_path: Optional[Path] = None) -> Li
"""Build the SSH tunnel command (reverse -R or local -L).""" """Build the SSH tunnel command (reverse -R or local -L)."""
key = os.path.expanduser(cfg.ssh_key) key = os.path.expanduser(cfg.ssh_key)
if cfg.direction == "local": if cfg.direction == "local":
forward_flag = ["-L", f"{cfg.local_port}:127.0.0.1:{cfg.remote_port}"] forward_flag = ["-L", f"{cfg.local_port}:{cfg.remote_host}:{cfg.remote_port}"]
else: else:
forward_flag = ["-R", f"{cfg.remote_port}:127.0.0.1:{cfg.local_port}"] forward_flag = ["-R", f"{cfg.remote_port}:{cfg.remote_host}:{cfg.local_port}"]
cmd = [ cmd = [
"ssh", "ssh",
"-N", "-N",

View File

@@ -51,6 +51,10 @@ class TunnelConfig:
reconnect: ReconnectPolicy = field(default_factory=ReconnectPolicy) reconnect: ReconnectPolicy = field(default_factory=ReconnectPolicy)
health_check: Optional[HealthCheckConfig] = None health_check: Optional[HealthCheckConfig] = None
direction: str = "reverse" # "reverse" (-R) or "local" (-L) direction: str = "reverse" # "reverse" (-R) or "local" (-L)
# Forward-destination host as seen from the remote end (direction "local")
# or from this workstation (direction "reverse"). Defaults to loopback;
# set e.g. a k3s ClusterIP to tunnel to an in-cluster Service.
remote_host: str = "127.0.0.1"
cert_command: Optional[str] = None cert_command: Optional[str] = None

View File

@@ -3,6 +3,8 @@ import os
import signal import signal
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from dataclasses import replace
import pytest import pytest
from bridge.models import BridgeState, ReconnectPolicy, TunnelConfig from bridge.models import BridgeState, ReconnectPolicy, TunnelConfig
@@ -38,6 +40,16 @@ class TestBuildSshCommand:
assert "-i" in cmd assert "-i" in cmd
assert "ubuntu@host.local" in cmd assert "ubuntu@host.local" in cmd
def test_remote_host_override_local(self, tunnel_cfg):
cfg = replace(tunnel_cfg, direction="local", remote_host="10.43.103.154")
cmd = build_ssh_command(cfg)
assert "-L" in cmd
assert f"{cfg.local_port}:10.43.103.154:{cfg.remote_port}" in cmd
def test_remote_host_default_loopback(self, tunnel_cfg):
cmd = build_ssh_command(tunnel_cfg)
assert "18000:127.0.0.1:8000" in cmd
def test_server_alive_options(self, tunnel_cfg): def test_server_alive_options(self, tunnel_cfg):
cmd = build_ssh_command(tunnel_cfg) cmd = build_ssh_command(tunnel_cfg)
assert "-o" in cmd assert "-o" in cmd