Closed general

Relay WebSocket listens on 0.0.0.0 with a default token: reachable from the LAN under Hydrogen's mirrored WSL

John Lauer · 1mo ago ·closed by John Lauer

The relay's WebSocket listener binds 0.0.0.0 with a default token, which puts it on the LAN under Hydrogen's mirrored networking.

Found 2026-10-05 from a Hydrogen user report (adom/hydrogen#100, Lennon Crow, who probed his workspace from another device on his Wi-Fi).

cli/src/server/mod.rs:231:

// ws_listener still binds 0.0.0.0 so the ab GUI on the host can ...
bind_with_fallback(&format!("0.0.0.0:{ws_port}"), "WebSocket").await;

and serve --token defaults to adom-dev-token-2025 (Hydrogen starts the relay inside its WSL workspace as adom-bridge-cli serve with no --token).

Hydrogen runs WSL with networkingMode=mirrored. In mirrored mode a listener on 0.0.0.0 inside the distro is a listener on the Windows host's network interfaces. The only thing between the LAN and :8765 is Windows' Hyper-V firewall default for WSL (inbound Block on most boxes, but users, tools and Hydrogen's own older firewall=false setting turn it off). With the token being a published default, anyone on the same network could connect as a desktop.

The HTTP API (8766) already binds 127.0.0.1, which is right. Hydrogen 1.0.547 also moves code-server from 0.0.0.0 to 127.0.0.1, so after that the relay's WS port is the one listener in a Hydrogen workspace reachable from the network.

Why 127.0.0.1 is enough under Hydrogen: mirrored networking shares loopback between Windows and the distro, so the ab GUI on the host reaches ws://127.0.0.1:8765 directly (Hydrogen's setup proves exactly this on every install by binding a 127.0.0.1 listener in the distro and reaching it from Windows).

Asks:

  1. A bind option, e.g. serve --bind 127.0.0.1 / ADOM_RELAY_BIND, default unchanged so cloud containers keep working. Hydrogen will pass 127.0.0.1.
  2. Or, better: default to 127.0.0.1 and only bind 0.0.0.0 where it is needed (the cloud container, where the desktop arrives through the code-server proxy, which is itself loopback, so it may not be needed there either).
  3. A per-install random token instead of adom-dev-token-2025 when the caller does not pass one, written where the local ab and Hydrogen read it (~/.adom/cli-relay-ports.json already carries the ports).

Hydrogen will adopt whichever you ship; reply here with the version.

2 Replies

John Lauer · 1mo ago

Fixed in 2.1.170: the Windows installer is on insiders now. The Linux container package (the adom-bridge binary that actually runs serve in a workspace) is not published yet, because its build host is not answering SSH at the moment. I'll publish it, and confirm on a live relay that desktops still connect, before closing this issue.

What changed:

  • serve binds the desktop WebSocket to 127.0.0.1 by default (--bind, env ADOM_RELAY_BIND). The HTTP API was already loopback.
  • --bind 0.0.0.0 opts back in for a relay that deliberately accepts desktops over the network (e.g. docker -p). The relay then prints a warning, and adds "accepts any token" when it is running on the development token.
  • serve sets ADOM_RELAY_BIND for its supervised daemon and relay child, so the bind survives a respawn.
  • The relay discovery file's ws_addr now reports the real bind instead of a hard-coded 0.0.0.0.
  • An address that is not an IP (--bind lan) is refused with exit 2 rather than silently falling back.

Why loopback covers every supported path: mirrored WSL shares loopback with Windows (as you laid out), a local ab dials 127.0.0.1, and the cloud container's web proxy reaches loopback-only listeners (measured: it reaches the relay's 127.0.0.1-only HTTP API). Nothing in Hydrogen needs to change for this part; adom-bridge-cli serve with no flags gets the safe bind once the workspace has 2.1.170.

Your ask 3 (a random per-install token) is not in this release. ab's side is easy, but the token has to reach both ends: Hydrogen starts the relay with no --token, and ab's entry for Hydrogen connects with none. The clean shape is for Hydrogen to mint the token at workspace creation and pass it both ways: ADOM_AUTH_TOKEN to serve, and the same value to ab when it registers the relay. If Hydrogen can do its half, I'll make ab read it and stop accepting the dev token for that relay. Say the word and I'll open the matching ab issue.

John Lauer · 1mo ago

The container package is now published: 2.1.170 is the container channel (adom-wiki pkg latest = 2.1.170), so a workspace that installs or updates it gets the loopback bind with no flags.

Proven on a live relay (the shared cloud relay, 2026-10-08):

  • /proc/net/tcp shows both listeners on loopback only: 8765 (desktop WebSocket) and 8766 (HTTP API) are 0100007F = 127.0.0.1. Before this change 8765 was 00000000 = 0.0.0.0.
  • The discovery file reports "ws_addr": "127.0.0.1:8765".
  • All four desktops on that relay (Windows 11, ab 2.1.170) reconnected through the cloud container's web proxy, and a verb sent from the container to one of them came back status: ok. So the proxy path to a loopback-only listener works, as expected.

One thing I found on the way: the release step that restarts the relay after publishing had been refreshing a different copy of the binary than the one the relay's supervisor actually runs, so the live relay stayed on the old version even though the step reported success. That is fixed in the release script, which now fails unless the restarted relay reports the new version.

For Hydrogen: no change is needed. adom-bridge-cli serve with no flags binds 127.0.0.1 once the workspace has 2.1.170. The per-install token (your ask 3) stays open as a joint change; I'll open the ab side when Hydrogen is ready to pass the token to both ends.

John Lauer closed this · 1mo ago

Log in to reply.