Files
dosh/docs/PUBLIC_READINESS.md
T
DuProcessandClaude Opus 4.8 828206f757 Publish threat model and refresh native v1 docs
Add docs/THREAT_MODEL.md deriving a publishable threat model from
NATIVE_V1_SPEC.md sections 4-6: assets, in/out-of-scope attackers,
security properties vs SSH (including where Dosh aims to exceed it),
cryptographic building blocks as implemented, and an honest
accepted-residual-risks / known-gaps section.

Refresh docs/PUBLIC_READINESS.md: feature matrix now reflects native
auth, host-key trust, authorized_keys policy, doctor, and -L/-R/-D
forwarding; add a per-item "Native v1 verification checklist status"
table mapping spec section 16 to done/in-progress/pending from code.

Update README.md status with a native v1 section and honest claim
posture pointing to THREAT_MODEL.md. Annotate NATIVE_V1_SPEC.md with a
v1 status block summarizing milestone progress. Point SPEC.md security
model and header at native auth and the threat model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:27:40 -04:00

11 KiB

Dosh Public Readiness

Dosh's defensible public claim is fast terminal attach and reconnect. It should not 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, and the published threat model is in docs/THREAT_MODEL.md. Native v1 is now substantially implemented: native key-exchange + user auth, host-key pinning/trust, -L/-R/-D forwarding, and dosh doctor all exist (see the feature matrix and the verification-checklist status table below). It is not yet fully verified: per-IP token-bucket rate limiting, protocol-version negotiation hardening, fuzzing in CI, and external review are still open. Until the verification checklist (NATIVE_V1_SPEC.md section 16) is green and that review is done, Dosh's defensible public security claim remains fast encrypted native attach/reconnect with SSH-equivalent transport security and an explicit SSH bootstrap fallback — not a fully verified, externally reviewed SSH replacement.

Objective Benchmarks

Run the same-host SSH comparison:

make bench-docker-ssh

Run the Dosh, SSH, and Mosh comparison:

make bench-docker-mosh

The Mosh-inclusive target builds one Docker image with OpenSSH, Mosh, dosh-server, and dosh-auth. It uses the same generated key, localhost network path, SSH server, and container for all samples.

Reported metrics:

Metric Meaning
ssh_true_ms Time to run ssh host true with the same key/options.
dosh_attach_ms Time for dosh-client --attach-only to render the first frame and detach on the configured path. With --no-cache, this is cold SSH bootstrap plus UDP attach.
dosh_cached_attach_ms Time for a warmed Dosh client to attach using cached UDP credentials/tickets, render the first frame, and detach. This is the fast-path claim and should be approximately network RTT plus local process/render overhead.
mosh_start_true_ms Time for mosh host -- true to bootstrap, run true, and exit.

These are not identical workloads. They are still useful because they measure the startup path each tool must pay before useful remote work begins. Public numbers must include the command, machine, OS, CPU, network path, and sample count.

Do not cite cold dosh_attach_ms as the core speed claim. Cold Dosh still pays SSH startup/authentication. Cite dosh_cached_attach_ms for repeat attach/reconnect speed, and cite cold dosh_attach_ms only to show that fallback remains competitive with ordinary SSH.

Feature Matrix

Feature Mosh Dosh now Public status
SSH-based first authentication yes yes ready
Native UDP key auth (no SSH per attach) no yes, Ed25519 via ssh-agent or encrypted key implemented; pending full verification
Dosh host-key pinning and trust no yes, known_hosts + dosh trust + mismatch hard-fail implemented
authorized_keys policy enforcement no yes, from=/no-port-forwarding/permitopen=, unsupported fail closed implemented
dosh doctor diagnostics no yes, config/auth/UDP/forwarding-policy check implemented
Encrypted UDP terminal data yes yes ready
Roaming by client address change yes yes needs more hostile-network tests
Survive sleep or network loss yes yes needs long-running soak tests
Fast repeat attach without SSH no yes, via attach tickets core differentiator
Resident server daemon no yes core differentiator
One UDP port for all sessions port range by default yes ready
Fresh session by default yes yes ready
Named persistent sessions no built-in shared session model yes ready
Multiple clients on one session no yes needs conflict-policy docs
View-only clients no yes ready
Full-screen TUI correctness yes improving must stay green before public push
Predictive local echo mature guarded printable-only opt-in not parity
Non-destructive disconnect UI yes not currently needed
Unicode edge-case handling strong basic terminal emulator dependent not parity
X11 forwarding no no non-goal unless tunneled separately
SSH agent forwarding no no planned as forwarding channel
Local TCP forwarding, -L no yes, native encrypted stream mux implemented; needs hostile-network tests
Remote TCP forwarding, -R no yes, loopback bind by default implemented; needs hostile-network tests
Dynamic SOCKS forwarding, -D no yes, SOCKS5 over native streams implemented; needs hostile-network tests
Forward-only / background forwarding, -N / -f no yes, -f requires -N implemented
Per-stream flow control / terminal priority no yes, windowed credit per stream implemented; needs load tests

SSH Config Inheritance

Dosh intentionally delegates SSH parsing and authentication to OpenSSH. Bootstrap uses the user's normal ssh command, so ~/.ssh/config options such as Host, HostName, User, Port, IdentityFile, ProxyJump, and UserKnownHostsFile continue to apply.

Dosh also calls ssh -G <alias> to infer the UDP target host when no dosh_host is configured. To write explicit Dosh host entries from SSH aliases:

dosh import-ssh palav homelab

This appends entries to ~/.config/dosh/hosts.toml without trying to become an OpenSSH config parser.

Forwarding (Implemented)

SSH forwarding cannot be copied by keeping the bootstrap SSH connection open, because that would remove Dosh's fast reconnect advantage and would break after roaming. Dosh forwarding therefore runs as native encrypted stream channels over the Dosh transport, and is now implemented.

CLI Meaning
dosh -L 8080:127.0.0.1:80 host Local listener on the client; server connects to target.
dosh -R 8080:127.0.0.1:80 host Remote listener on the server (loopback by default); client connects to target.
dosh -D 1080 host SOCKS5 listener on the client; server connects to whatever the SOCKS request names.

Implemented:

  • StreamOpen/StreamOpenOk/StreamOpenReject/StreamData/StreamWindowAdjust/ StreamEof/StreamClose packet types.
  • Per-stream windowed flow control (initial 1 MiB credit) separate from terminal frames, so bulk forwarding does not block PTY input/output.
  • Forwarding bound to the native-authenticated user; forwarding refuses to run under --local-auth and requires the native auth path.
  • Server-side policy enforcement: allow_tcp_forwarding, allow_remote_forwarding, loopback-only remote bind unless allow_remote_non_loopback_bind, plus per-key no-port-forwarding and permitopen=.
  • -N forward-only (no PTY) and -f background (requires -N, backgrounds only after listeners are ready).

Still open before claiming forwarding parity:

  • A dedicated dropped/reordered/replayed-UDP forwarding test suite.
  • Load tests proving large forwarded transfers add no visible terminal input lag.

Native v1 Verification Checklist Status

This maps each item in NATIVE_V1_SPEC.md section 16 to its status based on what the code in src/ actually does. Done = implemented and exercised by tests or obvious from code; in progress = partially implemented; pending = not yet implemented.

Spec section 16 item Status Evidence / note
Unknown host key fails unless TOFU explicitly enabled done Client refuses KnownHostStatus::Unknown unless trust_on_first_use.
Known host-key mismatch hard fails done KnownHostStatus::Mismatch aborts; trust_host refuses overwrite without --replace.
Native Ed25519 auth via ssh-agent done src/ssh_agent.rs signs the user-auth transcript.
Native Ed25519 auth via encrypted key prompt done load_ed25519_identity_with_passphrase decrypts OpenSSH keys.
Removed authorized key can no longer authenticate done Covered by native_user_auth_accepts_authorized_key_and_rejects_removed_key.
Unsupported authorized-key options fail closed done ensure_native_allowed bails on any unsupported option.
Replayed handshake packets rejected done Handshake is transcript-bound and signature-verified; pending entries TTL-evicted.
Replayed transport packets rejected done ReplayWindow (128-wide) over per-direction counter.
Stale encrypted packets after reconnect ignored, not fatal done session_key_id mismatch drops the packet instead of erroring fatally.
Client IP/port change preserves session done Server matches by ClientId/session key id, updates endpoint.
Native cold auth beats cold ssh host true pending Benchmark gate not yet run for native cold path (Track C / BENCHMARKS.md).
Cached attach near network RTT pending Same benchmark dependency.
-L works without delaying terminal input in progress Implemented with per-stream window; load proof pending.
-R enforces bind and permission policy done remote_bind_allowed + start_remote_forwards policy checks.
-N -L does not allocate a PTY done forward-only mode skips PTY allocation.
-f -N -L backgrounds only after listener readiness done spawn_background_forwarder waits for a readiness token.
Multiple forwards in one command done Forward lists parsed and started together.
dosh doctor identifies UDP-blocked/auth-denied/mismatch/forwarding-denied done run_doctor_command reports each state.
Closing laptop 30+ min does not kill session in progress Long client_timeout_secs + resume; 30-min soak evidence pending.
Three concurrent terminals independent unless named done Generated session names per attach; named sessions shared on purpose.
Large forwarded transfers add no visible input lag in progress Per-stream flow control exists; load test pending.
Fuzz targets run in CI pending No fuzz/ dir; CI runs fmt/test/build/bench only.
Threat model updated with accepted residual risks done docs/THREAT_MODEL.md.

Additional security hardening tracked outside the section 16 list:

  • Full per-IP token-bucket rate limiting: in progress (another track). Today only handshake-map eviction and a static rate_limit_remaining hint exist.
  • Protocol VERSION negotiation: in progress. Single version, fail-closed reject; no multi-version negotiation yet.
  • ECDSA P-256 / SHA-2 RSA user keys: pending. Ed25519 only today.

Before Public Launch

  • Keep cargo test, make bench-docker-ssh, and make bench-docker-mosh green.
  • Add a non-destructive disconnect indicator.
  • Run scripted TUI tests for alternate-screen apps, arrow keys, resize, mouse mode, bracketed paste, and terminal cleanup.
  • Publish benchmark output with raw samples, not just averages.
  • Mark prediction as experimental until it has a real framebuffer model.
  • Land full per-IP token-bucket auth rate limiting and wire fuzz targets into CI.
  • Complete the native-v1 verification checklist above and an external security review before making any "native SSH replacement" claim (NATIVE_V1_SPEC.md section 17).