Skip to content

feat(egress): coxswain egress tunnel + relay-routed gRPC/SSH dialers#32

Merged
bodaay merged 2 commits into
mainfrom
feat/control-plane-egress-relay
Jun 1, 2026
Merged

feat(egress): coxswain egress tunnel + relay-routed gRPC/SSH dialers#32
bodaay merged 2 commits into
mainfrom
feat/control-plane-egress-relay

Conversation

@bodaay

@bodaay bodaay commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Coxswain side of control-plane egress relaying (decision 19). Reaches nodes through a relay so a node never sees coxswain's IP.

  • internal/egress.Tunnel — TLS-dials the relay, holds a yamux client session (lazy reconnect), exposes DialContext: the one chokepoint both control channels route through.
  • gRPC NodeControl: control.NewDialer gains WithContextDialer.
  • SSH: ssh.DialConfig gains an optional Dialer.

Both opt-in and backward-compatible — direct dial stays the default; the mTLS / SSH handshake runs end-to-end over the relayed conn (relay stays protocol-blind). Full coxswain→relay→node path + lazy reconnect proven in internal/egress tests against beacon's egress relay.

Merge order / dev replace: go.mod has replace github.com/PharosVPN/beacon => ../beacon for the new egress package. Land PharosVPN/relay#6 first, bump the beacon dep here, then drop the replace.

Not yet wired into the CLI (deferred): enabling relaying will make the egress relay a DB-enrolled relay (reusing beacon enrollment) and thread the Tunnel through the dialer call sites, then live-validate. Depends on PharosVPN/docs#12 (decision 19).

🤖 Generated with Claude Code

Decision 19: coxswain reaches nodes through a relay so a node never sees
coxswain's IP. internal/egress.Tunnel TLS-dials the relay, holds a yamux
client session (lazy reconnect on a dead session), and exposes DialContext —
the single chokepoint both control channels route through:

- gRPC NodeControl: control.NewDialer gains WithContextDialer.
- SSH: ssh.DialConfig gains an optional Dialer.

Both opt-in and backward-compatible — direct dial stays the default. The mTLS
and SSH handshakes run end-to-end over the relayed conn, so the relay is
protocol-blind. Full coxswain->relay->node path (and lazy reconnect) proven in
internal/egress tests against beacon's egress relay.

Dev: go.mod replaces github.com/PharosVPN/beacon => ../beacon for the new
egress package; drop once beacon's egress branch lands and the dep is bumped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
beacon's egress package is on main now (PharosVPN/relay#6, #7), so bump the
beacon dependency to it and remove the development `replace => ../beacon`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bodaay bodaay merged commit ebd98e0 into main Jun 1, 2026
@bodaay bodaay deleted the feat/control-plane-egress-relay branch June 1, 2026 22:34
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