Skip to content

Fix exit node REPL blindness and hostname resolution#37

Merged
maxholman merged 5 commits intomainfrom
fix/exit-repl-peers-hostname
Feb 27, 2026
Merged

Fix exit node REPL blindness and hostname resolution#37
maxholman merged 5 commits intomainfrom
fix/exit-repl-peers-hostname

Conversation

@maxholman
Copy link
Copy Markdown
Contributor

Fix exit node REPL blindness and hostname resolution

Scope

Exit node peer lifecycle (registration/deregistration in shared Registry),
IPC address parsing, and the NodeApi trait boundary between IPC and daemon.

Crates: crates/daemon/src/mode/exit.rs, crates/core/src/ipc.rs,
crates/core/src/control/handler.rs, and the NodeApi trait.

Out of scope

  • REPL output formatting/colours (bugs 1+2 from TODO.md "Random" section — separate task)
  • Tracing subscriber changes (logfmt for wallhackd/systemd, consistent prefixed for REPL — separate task)
  • Entry node connect path (already works)
  • TUN EBUSY lifecycle bug
  • New features, performance work

Why

The REPL is non-functional on exit nodes — three related bugs:

  1. Peers invisible (TODO "Random" bugs 3+4): run_exit_loop never calls
    peers.register(), so PeerConnected notifications never fire and peers
    always returns empty. The entry node does this correctly — the exit connect
    path was never wired up.

  2. Hostname rejected (TODO "Random" bug 5): The IPC connect command does
    req.addr.parse::<SocketAddr>() which rejects bare hostnames. The CLI
    --connect path goes through AddressSpec + DNS resolution, but the REPL
    bypasses both. Users cannot connect attacker from the REPL.

Notes

  • No new dependencies. All fixes must use what's already in the workspace.
  • The Registry needs to be threaded through to run_exit_loop — currently
    exit::run() takes metrics: &Arc<Metrics> but no peers. Follow the
    entry node pattern in entry.rs where conn_peers.register() /
    conn_peers.unregister() bracket the connection lifecycle.
  • For the hostname bug, the IPC dispatcher needs DNS resolution before calling
    api.connect(). Options: (a) resolve in the dispatcher and keep
    NodeApi::connect(SocketAddr), (b) change the trait to accept AddressSpec
    or String and resolve inside the implementation. Option (a) is less
    invasive. Either way, default port injection via apply_default_port (or
    equivalent) is needed so bare hostnames work.
  • The exit node's Handler currently returns NotSupported for connect()
    this also needs to become functional if we want REPL connect to work on
    exit nodes.

maxholman and others added 5 commits February 27, 2026 19:58
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nnect

Exit node run_exit_loop and run_listen_server_loop never called
peers.register(), so PeerConnected notifications never fired and the
REPL `peers` command always returned empty. Thread the Registry through
the exit mode call stack and bracket connections with register/unregister,
matching the entry node pattern.

Change NodeApi::connect to accept &str instead of SocketAddr so the IPC
dispatcher no longer rejects bare hostnames. Implementations handle
address parsing and DNS resolution, reusing the existing resolve_endpoint
infrastructure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ions

- Extract ExitContext struct grouping metrics + peers into a single Arc,
  reducing clone dance in connect-loop closures from 2-3 clones to 1.
- Fix peers: None bug in ServerOptions for listener and relay paths —
  the Handler was getting a fresh empty Registry instead of the shared
  one, so IPC peers command always returned empty.
- Rename internal functions: run_connect_mode → run_exit_connector,
  run_listen_mode → run_exit_listener, run_listen_server_loop →
  run_accept_loop.
- Fix NodeApi doc comments: remove banned "upstream"/"downstream"
  terminology, "exit nodes" → "exit mode".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
release-please changed the tag format from cli-v* to wallhack-cli-v*
when the workspace plugin was configured. The startsWith filter in
build-release.yml was still checking for the old prefix, silently
skipping all builds and leaving releases without attached binaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@maxholman maxholman merged commit d3e0911 into main Feb 27, 2026
4 checks passed
@maxholman maxholman deleted the fix/exit-repl-peers-hostname branch February 27, 2026 13:44
maxholman added a commit that referenced this pull request May 6, 2026
Sweep of website/ deps to latest within ranges, plus a vite downgrade
from 8 -> 7 to match astro's transitive vite (7.3.2) and avoid a
rolldown regression with @tailwindcss/vite 4.2.4.

Closes alerts #28 #29 #30 #31 #33 #34 #35 #36 #37 #38 #39 #40 #44 #48
covering vite, picomatch, postcss, yaml, astro, smol-toml.

- vite ^8.0.1 -> ^7.3.2 (drops the now-redundant vite 8 lineage; astro
  pulls 7.3.2 transitively, which is the patched version)
- astro 6.0.6 -> 6.2.2 (#44)
- @tailwindcss/vite 4.2.2 -> 4.2.4
- smol-toml: lockfile bump to 1.6.1 (#28)
- postcss: lockfile bump to 8.5.14 (#48)
- picomatch: lockfile bumps to 2.3.2 + 4.0.4 (#29 #30 #39 #40)
- yaml is now omitted entirely (it was an optional vite peer)

Verified: pnpm build succeeds; no @tailwindcss/vite peer-dep warnings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant