From 9bece26bc8d96ae54f0f44a91d2e42464e0f3507 Mon Sep 17 00:00:00 2001 From: DuProcess <273172371+DuProcess@users.noreply.github.com> Date: Sat, 13 Jun 2026 10:54:19 -0400 Subject: [PATCH] Spec native Dosh auth and forwarding v1 --- SPEC.md | 7 +- docs/NATIVE_V1_SPEC.md | 464 +++++++++++++++++++++++++++++++++++++++ docs/PUBLIC_READINESS.md | 5 + 3 files changed, 474 insertions(+), 2 deletions(-) create mode 100644 docs/NATIVE_V1_SPEC.md diff --git a/SPEC.md b/SPEC.md index dc82a69..233c6ae 100644 --- a/SPEC.md +++ b/SPEC.md @@ -3,7 +3,8 @@ **Status:** Implemented Rust build with local and Docker SSH verification **Default language:** Rust, unless benchmarks prove the stack is the bottleneck **Binaries:** `dosh-server`, `dosh-client`, `dosh-auth`, `dosh-bench` -**Helper mode:** `dosh-server auth` or `~/.local/bin/dosh-auth`, invoked by SSH with `-T` +**Helper mode:** `dosh-server auth` or `~/.local/bin/dosh-auth`, invoked by SSH with `-T` +**Native v1 plan:** `docs/NATIVE_V1_SPEC.md` --- @@ -17,7 +18,9 @@ as quickly as possible. The daemon is resident. Sessions are named. A session owns one PTY and one authoritative terminal screen. Clients attach to that session over encrypted UDP. SSH is used for first trust establishment and as fallback when cached credentials are -missing, expired, or rejected. +missing, expired, or rejected. Native Dosh auth is specified separately in +`docs/NATIVE_V1_SPEC.md` as the path toward replacing the day-to-day SSH workflow on +Dosh-installed servers. --- diff --git a/docs/NATIVE_V1_SPEC.md b/docs/NATIVE_V1_SPEC.md new file mode 100644 index 0000000..8ec9f67 --- /dev/null +++ b/docs/NATIVE_V1_SPEC.md @@ -0,0 +1,464 @@ +# Dosh Native v1 Spec + +Native Dosh is a remote-login protocol for Dosh-installed servers. It is intended to +replace the user's day-to-day `ssh host` workflow for terminals and forwarding while +keeping SSH as a compatibility and recovery fallback. + +Native Dosh is not an RFC-compatible SSH implementation. It deliberately avoids the +full SSH transport/channel protocol and implements the smaller set of behavior Dosh +needs: authenticated login, encrypted terminal transport, reconnect/roaming, and TCP +forwarding. + +## 1. Product Contract + +User-facing commands: + +```bash +dosh host +dosh host command... +dosh -L 8080:127.0.0.1:80 host +dosh -R 9000:127.0.0.1:9000 host +dosh --session work host +dosh --view-only --session work host +``` + +Compatibility expectations: + +- Existing SSH keys and `ssh-agent` are reused. +- Server-side authorization uses `~/.ssh/authorized_keys`. +- Host trust is pinned in a Dosh known-hosts file and can be bootstrapped by SSH. +- `~/.ssh/config` host aliases, `HostName`, `User`, `Port`, `IdentityFile`, + `ProxyJump`, and `UserKnownHostsFile` are honored where practical. +- SSH bootstrap remains available with `--auth=ssh` and is used automatically when + native auth is disabled or cannot complete. + +Non-goals for v1: + +- RFC-compatible SSH server/client behavior. +- Arbitrary SSH subsystems. +- X11 forwarding. +- SFTP/SCP compatibility. +- Multi-user daemon mode with privileged account switching. +- Replacing OpenSSH on hosts that do not run `dosh-server`. + +## 2. Security Contract + +Native Dosh must match the security properties users rely on from SSH for this use +case: + +- Server authentication before terminal data is trusted. +- User authentication by possession of an authorized private key or agent key. +- Forward secrecy for terminal and forwarding traffic. +- AEAD encryption and authentication for every post-handshake packet. +- Replay protection for handshake and transport packets. +- Host-key pinning with explicit first-use behavior. +- No plaintext terminal bytes after handshake begins. +- No custom cryptographic primitives. +- Clear downgrade behavior: native auth failure must not silently fall back to an + unauthenticated mode. + +Native Dosh does not claim SSH's full protocol security surface. It claims equivalent +security for Dosh terminal and forwarding sessions on Dosh-installed servers. + +## 3. Threat Model + +In scope: + +- Passive network observer. +- Active network attacker that can spoof, drop, replay, reorder, or modify packets. +- NAT rebinding and client IP/port changes. +- Stolen attach-ticket cache without the user's private key. +- Server restart and key rotation. +- Malicious unauthenticated client flooding auth attempts. +- Compromised low-privilege local user trying to read Dosh caches on a shared client. + +Out of scope: + +- Compromised client machine. +- Compromised server account. +- Malicious kernel, terminal emulator, or PTY implementation. +- Protecting against a server that is already authorized and then becomes malicious. + +## 4. Cryptographic Building Blocks + +Allowed primitives: + +- Handshake pattern: Noise `NK` or `XX` through a maintained Rust Noise framework, or + a small audited construction over `x25519-dalek` plus transcript binding. +- KEX: X25519. +- Signatures for user auth: Ed25519 and ECDSA P-256 via SSH-agent and OpenSSH key + formats. RSA may be accepted only for compatibility and must use SHA-2 signatures. +- AEAD: ChaCha20-Poly1305 by default; AES-GCM optional when hardware support is known. +- KDF: HKDF-SHA256. +- Hash/transcript: SHA-256. +- Randomness: OS CSPRNG only. + +Disallowed: + +- Homegrown ciphers, MACs, padding, or key derivation. +- Reusing a nonce/key pair. +- Unauthenticated encryption. +- MD5/SHA-1 signatures for user auth. + +## 5. Identity And Trust + +### Server Identity + +Each `dosh-server` has a persistent host key: + +```text +~/.config/dosh/host_key +~/.config/dosh/host_key.pub +``` + +Default host-key algorithm: Ed25519. + +Client pins host keys in: + +```text +~/.config/dosh/known_hosts +``` + +Entry format: + +```text +host-pattern key-type base64-public-key first-seen=unix-seconds source=tofu|ssh|manual +``` + +First-use policy: + +- Default for public internet: refuse unknown native host key and suggest + `dosh trust host` or SSH bootstrap. +- Default for local/private hosts may be TOFU only when `trust_on_first_use = true`. +- `dosh trust host` may verify the Dosh host key over the existing SSH bootstrap path. + +Host-key mismatch: + +- Hard fail. +- Print old fingerprint, new fingerprint, and known-hosts file path. +- Never auto-replace. + +### User Identity + +Native auth user identity is the login user resolved from: + +1. Explicit CLI user: `user@host`. +2. Dosh host config. +3. `ssh -G host` `user`. +4. Local username. + +Server verifies user keys against: + +```text +~/.ssh/authorized_keys +~/.config/dosh/authorized_keys +``` + +`~/.config/dosh/authorized_keys` is optional and may restrict Dosh access without +changing SSH access. + +Authorized-key options required in v1: + +- `from=` +- `command=` must reject native Dosh terminal login unless explicitly supported later. +- `restrict` +- `no-port-forwarding` +- `permitopen=` + +Unsupported restrictive options must fail closed. + +## 6. Native Auth Handshake + +Native auth runs over UDP on the same Dosh port. It establishes a short-lived +authenticated control channel and returns the same terminal attach material that SSH +bootstrap returns today. + +Target path: + +```text +client -> server: ClientHello +server -> client: ServerHello +client -> server: UserAuth +server -> client: AuthOk + first terminal snapshot +``` + +The server may combine `AuthOk` and `AttachOk` to get terminal-ready in the final +handshake flight. + +### ClientHello + +Fields: + +- protocol version +- client random +- client ephemeral X25519 public key +- requested host alias +- requested user +- requested session +- requested mode +- terminal size +- supported AEAD algorithms +- supported user key algorithms +- optional cached host-key id +- optional attach ticket envelope + +### ServerHello + +Fields: + +- protocol version +- server random +- server ephemeral X25519 public key +- server host public key +- server host-key signature over transcript +- chosen AEAD +- server key epoch +- auth challenge +- rate-limit metadata when applicable + +The client must verify the host key before sending user authentication. + +### UserAuth + +Fields: + +- selected public key +- key algorithm +- signature over transcript and auth challenge +- optional agent identity metadata +- optional requested forwarding declarations + +The signature must bind: + +- both ephemeral keys +- both randoms +- server host key +- requested user/session/mode/terminal size +- selected algorithms +- protocol version + +### AuthOk + +Fields: + +- assigned `ClientId` +- session name +- mode +- session key id +- encrypted session key material or derived key confirmation +- attach ticket +- attach ticket PSK encrypted to the handshake key +- initial output sequence +- first snapshot +- server policy flags + +`AuthOk` is AEAD-encrypted under the handshake traffic key. + +## 7. Key Schedule + +Handshake transcript: + +```text +H = SHA256(protocol_label || ClientHello || ServerHello || UserAuth) +``` + +Shared secret: + +```text +dh = X25519(client_ephemeral, server_ephemeral) +``` + +Handshake key: + +```text +handshake_key = HKDF-SHA256(dh, H, "dosh/native/handshake/v1") +``` + +Session traffic keys: + +```text +c2s_key = HKDF-SHA256(handshake_key, H, "dosh/native/c2s/v1") +s2c_key = HKDF-SHA256(handshake_key, H, "dosh/native/s2c/v1") +``` + +Attach ticket PSKs and rotated session keys must be derived independently from server +secret material and fresh randomness. They must not reuse handshake traffic keys. + +## 8. Attach Tickets And Cache + +Native attach tickets replace most cold auth after first login. + +Ticket properties: + +- Server-sealed AEAD blob. +- Scoped to server host key, user, session, mode, client key fingerprint, server key + epoch, and policy flags. +- Paired with a client-held random PSK. +- Default TTL: 24 hours for trusted personal machines, configurable down to zero. +- Stored mode `0600`. +- Revoked by server host-key rotation, server secret rotation, or user key removal. + +Client cache path: + +```text +~/.local/share/dosh/credentials/ +``` + +Cache entries must include: + +- host identity fingerprint +- user +- session +- mode +- ticket expiry +- last rendered sequence +- client id +- session key id +- attach ticket +- attach ticket PSK + +## 9. Transport + +Post-auth terminal traffic continues to use the current Dosh UDP packet model: + +- fixed binary header +- AEAD body +- monotonic packet sequence +- ack field +- replay window +- server snapshots for recovery + +Required v1 changes: + +- Separate packet namespaces for terminal frames, control messages, and forwarding + streams. +- Explicit `key_epoch` or `session_key_id` in packet metadata so stale packets can be + ignored without fatal decrypt errors. +- Rekey command after configurable packet count or wall-clock interval. +- Connection migration must be accepted after any valid encrypted packet from a new + source address. + +## 10. Forwarding + +Native forwarding is a Dosh stream multiplexer over the encrypted transport. + +CLI: + +```bash +dosh -L [bind_host:]listen_port:target_host:target_port host +dosh -R [bind_host:]listen_port:target_host:target_port host +dosh -D [bind_host:]listen_port host +``` + +Stream packet types: + +- `StreamOpen` +- `StreamOpenOk` +- `StreamOpenReject` +- `StreamData` +- `StreamWindowAdjust` +- `StreamEof` +- `StreamClose` + +Forwarding rules: + +- Terminal traffic has priority over stream bulk data. +- Each stream has independent flow control. +- Backpressure must not block PTY input or output. +- Server enforces `no-port-forwarding` and `permitopen=`. +- Remote listeners bind to loopback by default. +- Non-loopback remote bind requires explicit config. + +## 11. Config + +Client: + +```toml +auth_preference = "native,ssh" +trust_on_first_use = false +native_auth_timeout_ms = 700 +known_hosts = "~/.config/dosh/known_hosts" +credential_cache = "~/.local/share/dosh/credentials" +identity_files = ["~/.ssh/id_ed25519"] +use_ssh_agent = true +``` + +Server: + +```toml +native_auth = true +host_key = "~/.config/dosh/host_key" +authorized_keys = ["~/.ssh/authorized_keys", "~/.config/dosh/authorized_keys"] +native_auth_rate_limit_per_minute = 30 +attach_ticket_ttl_secs = 86400 +allow_tcp_forwarding = true +allow_remote_forwarding = false +``` + +## 12. Migration Plan + +Milestone 1: host identity and trust + +- Generate Dosh host key on server install. +- Add `dosh trust host`. +- Add known-hosts file and mismatch handling. +- Keep SSH bootstrap as the only auth path. + +Milestone 2: native user auth + +- Implement `ClientHello`/`ServerHello`/`UserAuth`/`AuthOk`. +- Support ssh-agent Ed25519 first. +- Verify against `authorized_keys`. +- Add `--auth=native|ssh|auto`. + +Milestone 3: default native auth + +- Make `auth_preference = "native,ssh"` default. +- Keep SSH fallback explicit and visible. +- Add benchmark gates for native cold auth. + +Milestone 4: forwarding + +- Add stream mux and `-L`. +- Add `-R`. +- Add `-D` only after flow control is proven. + +Milestone 5: hardening + +- Fuzz packet parsing, authorized-key parsing, known-host parsing, and handshake state. +- Add hostile-network integration tests. +- Add external review checklist before public security claims. + +## 13. Verification + +Native v1 is not complete until all are true: + +- Unknown host key fails by default unless TOFU is explicitly enabled. +- Known host key mismatch hard fails. +- Native Ed25519 auth succeeds via ssh-agent. +- Native Ed25519 auth succeeds via encrypted private key prompt. +- Removed authorized key can no longer authenticate. +- Restrictive unsupported authorized-key options fail closed. +- Replayed handshake packets are rejected. +- Replayed transport packets are rejected. +- Stale encrypted packets after reconnect are ignored, not fatal. +- Client IP/port change preserves the session. +- Native cold auth benchmark beats cold `ssh host true` on the same host. +- Cached attach remains near network RTT plus local render overhead. +- `-L` forwarding works without delaying terminal input. +- `-R` forwarding enforces bind and permission policy. +- Fuzz targets run in CI. +- Threat model is updated with any accepted residual risks. + +## 14. Public Claim Gate + +Dosh may claim "native SSH replacement for Dosh-installed servers" only after: + +- Native auth is default on at least one real host. +- SSH fallback remains available. +- The verification checklist is green. +- The threat model is published. +- Benchmarks include raw samples for SSH cold, Dosh native cold, Dosh cached attach, + and Mosh startup. + +Dosh must not claim generic SSH compatibility unless it implements the SSH protocol. diff --git a/docs/PUBLIC_READINESS.md b/docs/PUBLIC_READINESS.md index 386ebb6..56281ac 100644 --- a/docs/PUBLIC_READINESS.md +++ b/docs/PUBLIC_READINESS.md @@ -4,6 +4,11 @@ Dosh's defensible public claim is fast terminal attach and reconnect. It should claim full Mosh replacement status until the feature matrix below is green and the comparison benchmark is reproducible outside the author's homelab. +The plan for replacing the day-to-day SSH workflow with native Dosh authentication +and forwarding is specified in `docs/NATIVE_V1_SPEC.md`. Until that spec is +implemented and verified, Dosh's public security claim remains SSH-bootstrap plus +encrypted Dosh transport. + ## Objective Benchmarks Run the same-host SSH comparison: