## Why The existing loopback listener mode does not provide the stdin/stdout transport needed by OpenSSH's `ProxyCommand`. ## What changed - Relay one SSH session over HTTP/3 CONNECT with `--environment-id ENV --port PORT`, defaulting to the public Portals gateway and port 22. Also accept an explicit `--proxy-url` with `--target ENV:PORT`. - Require ChatGPT OAuth login, enforce cloud configuration and application network policy, and restrict OAuth credentials to the built-in gateway origin. Leave SSH authentication and host-key verification to OpenSSH. - Preserve binary stdio, propagate input half-close, exit on gateway EOF, and report rejected CONNECT requests by HTTP status without exposing arbitrary peer error text. - Require ERS-issued v2 tunnel JWTs for Portals listener mode unless OAuth mode is selected, and reject older ERS tunnel JWTs during credential updates. - Disable UDP segmentation offload for SSH tunnels on Linux to avoid stalled bulk transfers on affected paths. Document an OpenSSH configuration example. ## Testing Add coverage for argument validation, gateway routing, credential boundaries, JWT startup and renewal checks, binary relay and half-close behavior, gateway EOF and rejection, and cloud policy enforcement before gateway connection. GitOrigin-RevId: 0d9afbddef01748efcc1c4b88f7e19923deff7e1
HTTP/3 TCP tunnel
The ordinary Codex binary includes the hidden codex tcp-tunnel command. In listener mode, it forwards a loopback TCP listener to an explicitly selected host and port through a TLS-verified HTTP/3 CONNECT proxy. The proxy URL must be an exact HTTPS origin in the supplied policy file; the target is provided separately as host:port or [IPv6]:port.
The initial bearer must be provided as a single line on standard input (--auth-token-stdin). With --auth-token-updates-stdin, later lines replace the bearer for new connections, emit AUTH_UPDATED, and closure of the controlling pipe stops the tunnel. With --connect-headers-stdin, the first line is instead a JSON list of ["x-name","value"] pairs; token lines follow. Only non-forwarding x- extension headers are accepted. No header values or credentials belong in the command arguments.
The process emits LISTENING 127.0.0.1:<port> after connecting to the proxy. A proxy handshake does not authorize the target; each local connection makes its own authenticated CONNECT. The listener survives transport reconnects, but TCP streams are never replayed.
--diagnostics-json opts into newline-delimited JSON on stderr. Version 1 contains
v, phase (startup, connect, transport, or control), code (failed,
timeout, rejected, closed, draining, or invalid_input), and terminal.
A rejected CONNECT may also include a numeric http_status (100–599, excluding
2xx). Records contain no credentials, addresses, headers, or raw error messages
and are less than 256 bytes. Stdout readiness and credential acknowledgments are
unchanged. A terminal record is flushed before an unsuccessful return; closing
the controlling pipe normally emits no failure. The CLI may append a generic
error line after the terminal record. Nonterminal events may concern
one TCP stream or a reconnecting shared transport and do not identify the cause
of a later child-process failure. Consumers must ignore records with unknown versions or fields and keep a generic
fallback for helpers without this flag.
Version 1 terminal combinations are startup/{failed,timeout},
control/{failed,invalid_input}, and transport/failed. Nonterminal combinations
are connect/{failed,rejected} and transport/{failed,timeout,closed,draining}.
Other combinations are unknown records and must use the generic fallback.
OpenSSH ProxyCommand
With --environment-id ENV --port PORT, codex tcp-tunnel opens one
HTTP/3 CONNECT and carries SSH bytes on stdin and stdout.
The defaults are the public Portals gateway and port 22. You can also specify
--proxy-url ORIGIN --target ENV:PORT. The gateway resolves the environment
and port.
A rejected CONNECT ends the command with its HTTP status on stderr.
This example uses a verified host key stored under ccarenv_example in
known_hosts.
Host ccarenv_example
User dev
StrictHostKeyChecking yes
ProxyCommand /opt/codex/bin/codex tcp-tunnel --environment-id ccarenv_example --port %p