Stream SSH proxy over Iroh

This commit is contained in:
Eric Wendland 2026-05-21 01:03:38 +02:00
commit 87d8801d71
7 changed files with 366 additions and 23 deletions

View file

@ -60,8 +60,8 @@ discovery is enabled by default with `[iroh].local_discovery = true`.
SSH keys are used as admin trust anchors and ecosystem integration points.
OpenSSH, FIDO, and YubiKey-backed keys can sign geth trust objects through
canonical geth envelopes with explicit namespaces such as
`geth.keychain.v1@geth.local`. Future SSH proxying may carry SSH protocol bytes
over authorized Iroh streams, but the geth transport remains Iroh.
`geth.keychain.v1@geth.local`. SSH proxying carries SSH protocol bytes over an
authorized Iroh stream, but SSH is still not a geth transport backend.
SSH certificate request and renewal flows are managed as geth metadata. A node
can create a certificate request, another machine can approve it and receive an
@ -141,7 +141,7 @@ The bootstrap implementation provides:
- `geth ssh revocation export --out <path> [--format jsonl|openssh-krl-spec|openssh-krl] [--subject <principal>]`
- `geth ssh revocation import <path> [--format jsonl|openssh-krl-spec] [--subject <principal>]`
- `geth ssh revocation sync <node-id> [--bearer-secret <secret>]`
- SSH proxy authorization probe: `geth ssh proxy <node-id> [--bearer-secret <secret>]`
- SSH proxy over Iroh: `geth ssh proxy <node-id> [--bearer-secret <secret>]`
- pipe registry/message commands:
`geth pipe listen <name> [--node <node-id>] [--bearer-secret <secret>]`,
`geth pipe connect <name> [--node <node-id>] [--bearer-secret <secret>]`,
@ -209,11 +209,12 @@ Remote pipe listen uses the same protected path:
`resource:pipe:<name>` before registering a daemon-lifetime listener on the
peer. Long-lived stdin/stdout streaming and socket forwarding are still future
work.
`geth ssh proxy <node-id>` also uses the protected Iroh control path. The remote
peer validates the caller's endpoint/card binding and requires
`ssh_proxy.connect` on `resource:ssh-proxy:local` before returning proxy
connection metadata. The current prototype does not carry SSH bytes or connect
to remote sshd yet; it only proves the authorization gate.
`geth ssh proxy <node-id>` is usable as an OpenSSH `ProxyCommand`: the CLI opens
a local daemon stream, the daemon opens the dedicated `/geth/ssh-proxy/1` Iroh
ALPN, the remote daemon validates the caller's endpoint/card binding and
requires `ssh_proxy.connect` on `resource:ssh-proxy:local`, and only then
connects the stream to `127.0.0.1:22`. SSH remains normal OpenSSH on top of that
byte stream; SSH is not a geth transport backend.
Document sync is a bootstrap JSON last-writer-wins path before Automerge:
manual `geth document sync <node-id> <name>` and background live-sync require
`document.read` on `resource:document:<name>` and import only state that is not