fix(ssh-gate): listen on the upstream port so URL-supplied ports work
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 12s

Bug: git fetch failed with "connect to host
claude-bottle-ssh-gate-implementer port 30009: Connection refused".
OpenSSH treats a URL-supplied port (the user's remote was
ssh://git@gitea.dideric.is:30009/...) as overriding the
~/.ssh/config Port directive, so even though the config wrote
Port 30000 the agent dialed :30009 — where nothing was listening
because the gate had been assigned BASE_LISTEN_PORT + index.

Fix: the gate's listen port now equals the upstream port. Same
script, same socat, just port = entry.Port. Two entries on the
same upstream port are rejected at prepare time (the gate is one
container with a flat port space).

Re-smoked: probe nc github.com via the gate at :22, banner came
back as expected.

PRD 0007 updated to record the design refinement.
This commit is contained in:
2026-05-12 16:19:07 -04:00
parent a7633977de
commit a3d77cd015
3 changed files with 78 additions and 29 deletions
+8 -2
View File
@@ -108,8 +108,14 @@ script that backgrounds N socat invocations:
socat TCP-LISTEN:<port_i>,reuseaddr,fork TCP:<Hostname_i>:<Port_i>
```
Listen ports are assigned deterministically per ssh entry (e.g.
`30000 + index`). One container, N listeners, N upstreams.
Listen ports mirror the upstream port (entry `Port`, default 22).
That choice is load-bearing: OpenSSH treats a URL-supplied port
(e.g. `ssh://git@host:30009/repo.git`) as overriding the config's
`Port` directive, so the gate has to be reachable on the same port
the URL names — otherwise git fetch hits "connection refused" on
the URL's port even though the config block points elsewhere. Two
ssh entries sharing an upstream port are a config error and
rejected at prepare time. One container, N listeners, N upstreams.
### Existing code touched