fix(manager): pin local forwards to 127.0.0.1 so port collisions fail loudly
An unbound `-L port:host:port` listens on every loopback family. When another process already holds the IPv4 port, the IPv6 bind still succeeds and ExitOnForwardFailure does not fire: the tunnel comes up on [::1] while every client resolving 127.0.0.1 reaches the other process instead. This is how the local State Hub cache impersonated the primary from 2026-07-08 onward — both on port 8000, separated only by IP family. Refs CUST-WP-0067-T02, ADR-010 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
This commit is contained in:
parent
e8b007ad74
commit
22138474b8
2 changed files with 28 additions and 2 deletions
|
|
@ -25,6 +25,10 @@ def tunnel_cfg():
|
|||
)
|
||||
|
||||
|
||||
def cmd_value(cmd, flag):
|
||||
"""Return the argument following ``flag`` in an argv list."""
|
||||
return cmd[cmd.index(flag) + 1]
|
||||
|
||||
@pytest.fixture
|
||||
def state_dir(tmp_path):
|
||||
return tmp_path / "bridge"
|
||||
|
|
@ -44,7 +48,19 @@ class TestBuildSshCommand:
|
|||
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
|
||||
assert f"127.0.0.1:{cfg.local_port}:10.43.103.154:{cfg.remote_port}" in cmd
|
||||
|
||||
def test_local_forward_pins_bind_address(self, tunnel_cfg):
|
||||
"""An unbound -L also listens on [::1], so a taken IPv4 port does not fail.
|
||||
|
||||
ExitOnForwardFailure only fires when every requested bind fails. Pinning
|
||||
127.0.0.1 makes a port collision loud instead of routing clients to
|
||||
whatever else holds the port (CUST-WP-0067-T02).
|
||||
"""
|
||||
cfg = replace(tunnel_cfg, direction="local")
|
||||
forward = cmd_value(build_ssh_command(cfg), "-L")
|
||||
assert forward.startswith("127.0.0.1:")
|
||||
assert forward.count(":") == 3
|
||||
|
||||
def test_remote_host_default_loopback(self, tunnel_cfg):
|
||||
cmd = build_ssh_command(tunnel_cfg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue