Commit Graph

165 Commits

Author SHA1 Message Date
DuProcess f9c1973c13 Harden native protocol: version discipline, rekey, migration, rate limit, O(1) client index
Track A protocol hardening for native-v1.

1. Protocol VERSION discipline (protocol.rs, native.rs, dosh-server.rs,
   dosh-client.rs): bump protocol::VERSION to 2 and NATIVE_PROTOCOL_VERSION to 2.
   Foreign wire-version datagrams now get a clear named "protocol version
   mismatch - upgrade dosh" reject from the server instead of a silent timeout
   (peek_foreign_wire_version + VERSION_MISMATCH_REASON). The native handshake's
   plaintext protocol_version is also checked server-side before any crypto via
   check_native_protocol_version, returning a typed ProtocolVersionMismatch.

2. Transport rekey (spec section 11/9): server rotates a client's traffic key
   after rekey_after_packets OR rekey_after_secs (config knobs). Rotated keys are
   derived independently of the handshake keys from the current key plus fresh
   server CSPRNG material shipped confidentially in an AEAD Rekey packet
   (derive_rekey_session_key). The previous epoch's key is retained briefly so
   in-flight pre-rekey packets still decrypt (matched by session_key_id), and
   stale-epoch packets are ignored, not fatal. Client handles Rekey/RekeyAck.

3. Connection migration (spec section 11): every authenticated, replay-accepted
   packet now migrates client.endpoint to the new source address (input, resize,
   ping, ack, resume, stream*, rekey-ack), not just resume. Ping now verifies its
   AEAD tag before acting so migration cannot be spoofed.

4. Native auth rate limiting: per-source-IP token bucket
   (native_auth_rate_limit_per_minute) enforced in handle_native_client_hello
   BEFORE any X25519/Ed25519 work; over-limit hellos get a non-crypto reject.

5. Speed: replaced O(sessions x clients) per-packet linear scans with an O(1)
   HashMap<conn_id, session_name> index in ServerState, kept in sync on every
   client insert/remove (attach handlers, detach, remove_client, cleanup reap,
   session-exit drain).

New config keys (ServerConfig, with defaults): rekey_after_packets = 100000,
rekey_after_secs = 3600.

Tests: version-mismatch reject (no hang), rate-limit flood reject, rekey
round-trip end-to-end + key-derivation unit tests, source-address migration,
client-index sync + cleanup purge. fmt and full test suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:45:44 -04:00
DuProcess 1306adb558 Merge track E: clean-room mosh-grade predictive echo 2026-06-14 10:42:57 -04:00
DuProcess 1e5517dcf1 Add llms.txt agent-oriented overview
Self-contained orientation for AI agents: what dosh is, capabilities,
the bidirectional homelab forwarding patterns (-L/-R/-D with concrete
examples), fast-path order, architecture, security summary, config, and
how to drive dosh non-interactively. Links to the deeper docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:42:03 -04:00
DuProcess cdeba047bc Add mosh-grade predictive local echo
Replace the basic printable-only predictor with a clean-room speculative
local-echo engine modeled on the Mosh paper's prediction overlay design
(no GPL code copied or translated; original Rust written from the
algorithm).

Model:
- Per-line cell model with a local cursor; printable keystrokes echo
  immediately, dimmed (and underlined on a very slow link) via
  save/restore cursor so full-screen TUIs are never corrupted.
- Backspace and in-line Left/Right arrow prediction (CSI and SS3).
- Epoch grouping per keystroke burst; anything unmodelable (CR/LF,
  escapes, control bytes, wide chars, right margin, paste-sized bursts)
  ends the epoch safely rather than mispredicting.
- Frame-sequenced confirmation: an authoritative server frame supersedes
  and erases the overlay (dosh has no client-side emulator, so it cannot
  do Mosh's per-cell content match; frame arrival is the confirmation).
- Glitch detection: contradicting output (e.g. alternate-screen entry)
  discards the epoch.
- SRTT-based display policy with hysteresis and a latency-spike override;
  modes off / experimental(adaptive, default) / always via new
  client config `predict_mode` and `DOSH_PREDICT_MODE` env override.

Improvements over the prior predictor: in-line arrow motion, dim+flag
styling, exact-width erase, paste guard, and faster (frame-arrival)
confirmation. Prediction is display-only and never swallows input.

Adds unit tests: printable run, confirmation-clears, glitch-discards,
backspace, line-wrap budget, paste-skip, newline, inline arrows, and the
experimental SRTT threshold gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:41:42 -04:00
DuProcess c47ae98c68 Merge track C: benchmark path matrix + safe local harness + BENCHMARKS.md 2026-06-14 10:34:30 -04:00
DuProcess c48f2280a0 Add benchmark path matrix and safe local harness
Extend dosh-bench to benchmark the full attach path matrix and emit both raw
per-iteration samples and summary statistics (count/min/median/p95/mean/max):

- --cold-native:   native cold auth terminal-ready (dosh_cold_native_ms)
- --cached-ticket: cached attach-ticket fast path (dosh_cached_attach_ms)
- --resume:        UDP resume path (dosh_resume_ms; roaming-only, see docs)
- --local-auth:    self-contained local bootstrap, no SSH (dosh_local_attach_ms)
- default:         legacy SSH-bootstrap cold attach (dosh_attach_ms)

Existing ssh-bootstrap/local-auth/mosh modes and all assert gates are preserved;
legacy flags (--local-auth/--warm-cache/--no-cache) keep their prior behavior so
the CI docker scripts run unchanged. Add --json (machine-readable raw samples)
and --label. Add a table/JSON renderer and percentile-based summary stats.

Add scripts/bench-local.sh: a safe, self-contained harness that builds release,
spins up a throwaway dosh-server bound to 127.0.0.1 on a random free UDP port in
a temp HOME (never port 50000, never a systemd unit), runs the matrix, prints
results, sanity-checks native auth actually trusted the host, and cleans up.

Point `make bench-local` at the new harness and add `make bench-local-json`;
keep bench-docker-* targets intact.

Add docs/BENCHMARKS.md: how to run each benchmark, metric meanings, methodology
and caveats (resume is the roaming path, not cold reconnect; cite cached attach
as the core claim per PUBLIC_READINESS.md), plus a real loopback sample table
with machine/OS/sample-count and raw samples.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:33:37 -04:00
DuProcess 6bded28d40 Merge track B: hostile-network tests + fuzzing + CI fuzz job 2026-06-14 10:32:41 -04:00
DuProcess 9b0f09a8a8 Add hostile-network tests, parser fuzzing, and CI fuzz job
Track B (milestone 5 / §16 hardening):

- tests/hostile_network.rs: in-process UDP relay/shim between a test
  client and a real dosh-server that can drop, reorder, and duplicate
  datagrams, and rebind its upstream socket mid-session. Asserts:
  session survives loss/reorder, duplicated/replayed Input is applied at
  most once, stale packets after resume are ignored (not fatal), and a
  client source-address change preserves the session.
- tests/parser_robustness.rs: deterministic randomized tests throwing
  garbage at every reachable public parser (packet decode, from_body for
  all protocol/native structs, authorized_keys, known_hosts, host-key
  line, ssh-ed25519 blob, bootstrap, attach ticket); asserts none panic.
- fuzz/: standalone cargo-fuzz crate (own [workspace], non-default
  member) with libfuzzer-sys harnesses for packet decode, from_body,
  authorized_keys, known_hosts, handshake structs+verifiers, and attach
  tickets. README documents the run command.
- .github/workflows/ci.yml: add fuzz-smoke job (nightly + cargo-fuzz,
  short -max_total_time per target, tolerant if tooling unavailable);
  existing fmt/test/build/bench steps unchanged.

cargo fmt --check and cargo test are green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:31:47 -04:00
DuProcess c37424eb45 Merge track D: threat model + readiness docs 2026-06-14 10:29:05 -04:00
DuProcess 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
DuProcess 2a6f28d529 Fix native-v1 connection break, server panic, and resource leaks
The native-v1 work changed the UDP wire format (HEADER_LEN 42->58) without a
version bump, so a current client silently timed out against the older
still-deployed server. The server just needed redeploying; alongside that,
fix the robustness bugs surfaced while restoring the connection:

- Server: clamp terminal size to >=1 at every PTY/parser resize site. A client
  reporting a 0x0 terminal made vt100::Parser::set_size panic ("attempt to
  subtract with overflow") and took down the whole single-threaded daemon.
- Client: treat size() == Ok((0,0)) like a missing size and fall back to 80x24
  instead of sending 0x0 to the server.
- Reap abandoned sessions and their shells. PtyHandle now retains the child and
  kills it on drop, and the cleanup task removes clientless, non-prewarmed
  sessions after the grace period. Previously the shell leaked forever (one
  zsh per abandoned session); prewarmed sessions still stay hot.
- Evict half-finished native handshakes (pending_native) after 30s so an
  unauthenticated ClientHello flood can't grow the map without bound.
- Drop the per-client, per-packet vt100 Screen clone on the output hot path and
  remove the write-only last_screen field.
- Guard load_or_create_server_secret against a <32-byte secret file (was an
  index-out-of-range panic at startup).
- Reconcile stream flow-control credit (client and server) when StreamData hits
  a missing writer, so a closed/unknown stream can't wedge the peer's window.

Adds a unit test for session reaping. cargo fmt + cargo test green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:06:27 -04:00
DuProcess 6c14d669b8 Gate non-loopback remote binds
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-14 09:10:09 -04:00
DuProcess fb5c25ea0b Add stream window flow control
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-14 09:08:19 -04:00
DuProcess dd9c4daeda Report server version in doctor
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:34:09 -04:00
DuProcess f66de64b3f Support host-config login users
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:32:45 -04:00
DuProcess 1b1278f39e Add explicit environment propagation
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:30:15 -04:00
DuProcess 38e2fa091a Ignore stale packets during attach resume
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:21:20 -04:00
DuProcess 76e2e980f1 Avoid PTY allocation for forward-only mode
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:18:15 -04:00
DuProcess 7fec3592f5 Honor more SSH config in native auth
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:13:47 -04:00
DuProcess af5e9f7956 Enforce authorized_keys from restrictions
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:07:04 -04:00
DuProcess 0575cf678f Add native doctor auth diagnostics
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:01:27 -04:00
DuProcess 6d1e9d3065 Add background forwarding mode
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:55:14 -04:00
DuProcess da16588bc5 Add packet session key identifiers
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:51:55 -04:00
DuProcess 3642de71e4 Add native dynamic port forwarding
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:48:49 -04:00
DuProcess 64b00783fd Bound forwarded stream buffering
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:43:42 -04:00
DuProcess 6a0f12c59e Add native remote port forwarding
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:41:48 -04:00
DuProcess 6aa81d0ce3 Add native local port forwarding
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:36:10 -04:00
DuProcess f324a7627f Support encrypted native identity keys
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:26:31 -04:00
DuProcess 55a0fc1ab4 Add ssh-agent native auth
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 15:21:21 -04:00
DuProcess e7f3679fc1 Wire native Dosh auth runtime
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:54:24 -04:00
DuProcess 80c7889b46 Verify native Dosh Ed25519 user auth
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:38:00 -04:00
DuProcess a72f7eacf5 Add native Dosh handshake skeleton
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:34:05 -04:00
DuProcess 26fc863149 Add native Dosh host trust foundation
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:32:01 -04:00
DuProcess f6ab4473bd Define native Dosh workflow parity requirements
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:25:52 -04:00
DuProcess 9bece26bc8 Spec native Dosh auth and forwarding v1
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 10:54:19 -04:00
DuProcess 80166eae15 Keep Dosh alive across stale UDP reconnects
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 10:20:03 -04:00
DuProcess 93374162ff Measure cached Dosh attach fast path
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 22:45:13 -04:00
DuProcess 3a38a9da80 Add public comparison benchmarks and SSH import
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 14:27:58 -04:00
DuProcess 063c44d971 Quiet Dosh update git fetches
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:59:47 -04:00
DuProcess 4ac5d63faf Avoid login shell for Dosh sessions listing
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:59:12 -04:00
DuProcess 83b2d9d70c Quote Dosh sessions remote command
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:58:16 -04:00
DuProcess e3f61a4efb Add Dosh host workflows and reconnect QoL
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:48:44 -04:00
DuProcess c56e8f9fe1 Add guarded local typing prediction
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:39:27 -04:00
DuProcess 03df1c6ed7 Ignore stale Dosh snapshots
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:33:55 -04:00
DuProcess 32da29e2fb Render Dosh frames in stream order
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:32:07 -04:00
DuProcess f8df38efb0 Stop drawing client overlay over TUIs
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 13:03:39 -04:00
DuProcess fd7849f889 Forward terminal input bytes without cursor rewriting
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-11 22:22:03 -04:00
DuProcess 6580e75fbf Resolve SSH aliases for Dosh UDP host
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-11 22:09:55 -04:00
DuProcess 1860a0e610 Preserve alternate screen snapshots and speed builds
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-11 16:19:30 -04:00
Codex 93a210b420 Normalize application cursor arrows
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-11 16:11:56 -04:00