Add launch hardening gates

This commit is contained in:
DuProcess
2026-06-18 09:45:27 -04:00
parent 25d9a6aefa
commit d0d6f59cdf
11 changed files with 583 additions and 61 deletions
+10 -9
View File
@@ -13,16 +13,17 @@
> the default with explicit, visible SSH fallback. Local and Docker benchmark gates
> cover cached attach, SSH fallback, and native cold auth (Track C /
> `BENCHMARKS.md`).
> - Milestone 4 — forwarding: **implemented.** Stream mux, `-L`, `-R`, `-D`, `-N`,
> `-f`, and per-stream flow control exist; terminal-priority/load regressions are
> covered, and hostile-network/long-soak proof is still being expanded before parity
> is claimed.
> - Milestone 4 — forwarding: **implemented with one reliability caveat.** Stream
> mux, `-L`, `-R`, `-D`, `-N`, `-f`, and per-stream flow control exist;
> terminal-priority/load and replay/reorder regressions are covered. Dropped
> `StreamData` recovery still needs stream retransmission before lossy-link
> forwarding parity is claimed.
> - Milestone 5 — hardening: **partly done.** Per-IP token-bucket rate limiting,
> fail-closed protocol-version checks, parser fuzz targets, fuzz-smoke CI, scripted
> TUI transport tests, forwarding load/priority tests, and independent persistent
> session restart tests exist. External review, long soak, and future multi-version
> compatibility policy are not yet complete. The threat model is published
> (`docs/THREAT_MODEL.md`).
> fail-closed protocol-version checks with a documented v1 policy, parser fuzz
> targets, fuzz-smoke/deep CI entry points, scripted TUI transport tests,
> forwarding load/priority/replay tests, and independent persistent session restart
> tests exist. External review and published long-soak evidence are not yet
> complete. The threat model is published (`docs/THREAT_MODEL.md`).
> - Milestone 6 — workflow parity: **mostly done.** `dosh doctor`, host-trust
> management, and the encrypted-key prompt flow exist; cross-OS daily-driver soak is
> ongoing.
+40
View File
@@ -0,0 +1,40 @@
# Dosh Protocol Versioning
Dosh v1 uses a deliberately simple compatibility policy: **single-version,
fail-closed, explicit error**.
The wire header carries `protocol::VERSION`. The native handshake carries
`native::NATIVE_PROTOCOL_VERSION`. A peer that speaks any other version is rejected
before application data is accepted:
- foreign wire `VERSION` packets get an `AttachReject` with
`protocol version mismatch - upgrade dosh`;
- foreign native handshake `protocol_version` values get the same named upgrade
error with local/remote versions;
- there is no silent downgrade, compatibility fallback, or best-effort decoding.
## When To Bump
Bump `protocol::VERSION` when a change affects packet framing, packet kind meaning,
serialized protocol structs carried outside native handshake negotiation, or anything
an older peer could misparse.
Bump `native::NATIVE_PROTOCOL_VERSION` when a change affects native handshake
transcripts, native auth semantics, algorithm negotiation, attach tickets, or any
field that is signed or key-derived by native auth.
If both layers are affected, bump both.
## Compatibility Window
Native v1 supports exactly the current version. That keeps the implementation small
and makes security review tractable. Multi-version negotiation can be added later
only with an explicit downgrade-resistance design:
- negotiated version must be transcript-bound;
- the selected version must be visible in diagnostics;
- tests must prove an active attacker cannot force an older mutually supported
version;
- unsupported peers must still get the same named upgrade error.
Until that exists, the public policy is: upgrade both sides together.
+19 -13
View File
@@ -10,8 +10,8 @@ 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,
`dosh doctor`, token-bucket auth rate limiting, and fuzz-smoke CI all exist (see the
feature matrix and the verification-checklist status table below). It is **not yet
fully verified**: long sleep/roaming soak, adversarial UDP forwarding tests, deeper
fuzzing, protocol-version compatibility policy, and external review are still open.
fully verified**: long sleep/roaming soak, packet-loss recovery for forwarding,
deeper fuzzing results, 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
@@ -63,8 +63,8 @@ with ordinary SSH.
| `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 | implemented; needs more hostile-network/soak proof |
| Survive sleep or network loss | yes | yes | needs long-running soak tests |
| Roaming by client address change | yes | yes | implemented; hostile-network covered, 30-minute soak gate available |
| Survive sleep or network loss | yes | yes | implemented; run `make soak-local` before public launch |
| 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 |
@@ -78,9 +78,9 @@ with ordinary SSH.
| Unicode edge-case handling | strong | basic terminal emulator dependent | not parity |
| X11 forwarding | no | no | non-goal unless tunneled separately |
| SSH agent forwarding | no | yes, explicit `-A` / `forward_agent` plus server allow-list | implemented; opt-in only |
| Local TCP forwarding, `-L` | no | yes, native encrypted stream mux | implemented; load/priority tested, adversarial UDP pending |
| Remote TCP forwarding, `-R` | no | yes, loopback bind by default | implemented; adversarial UDP pending |
| Dynamic SOCKS forwarding, `-D` | no | yes, SOCKS5 over native streams | implemented; adversarial UDP pending |
| Local TCP forwarding, `-L` | no | yes, native encrypted stream mux | implemented; load/priority and replay/reorder tested; packet-loss recovery pending |
| Remote TCP forwarding, `-R` | no | yes, loopback bind by default | implemented; packet-loss recovery pending |
| Dynamic SOCKS forwarding, `-D` | no | yes, SOCKS5 over native streams | implemented; packet-loss recovery pending |
| 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; covered by blocked-stream and local-forward load tests |
@@ -130,7 +130,9 @@ Implemented:
Still open before claiming forwarding parity:
- A dedicated dropped/reordered/replayed-UDP forwarding test suite.
- Reliable packet-loss recovery for forwarded stream data. Reorder and replay are
covered by `forwarded_stream_data_survives_reorder_and_rejects_replay`; true
dropped `StreamData` recovery requires stream retransmission.
- More real-host load soak. The integration suite already covers terminal-priority
behavior while a local forward is under blocked-stream pressure.
@@ -162,19 +164,18 @@ from code; in progress = partially implemented; pending = not yet implemented.
| `-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. |
| Closing laptop 30+ min does not kill session | in progress | `sleep_roaming_soak_30m` is an ignored launch gate; run `make soak-local` for 1800s evidence. |
| 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 | done | Covered by the local-forward bulk-load integration test; still needs real-host soak before launch claims. |
| Fuzz targets run in CI | done | `fuzz/` has parser/auth targets and CI runs a nightly `fuzz-smoke` job when cargo-fuzz is available. |
| Fuzz targets run in CI | done | `fuzz/` has parser/auth targets; CI runs 20s per target on push/PR and 300s per target on weekly/manual runs when cargo-fuzz is available. |
| 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: implemented for native auth and covered by
unit/integration tests. It still needs real-host tuning under abusive traffic.
- Protocol VERSION handling: current behavior is single-version, fail-closed reject
at the packet/header and native-handshake layers. Future multi-version
compatibility/downgrade policy is still open.
- Protocol VERSION handling: v1 policy is single-version, fail-closed reject at the
packet/header and native-handshake layers. See `docs/PROTOCOL_VERSIONING.md`.
- ECDSA P-256 / SHA-2 RSA user keys: implemented for ssh-agent and OpenSSH
identity-file native auth. RSA is compatibility-only and uses SHA-2 signatures;
legacy SHA-1 `ssh-rsa` signatures are not accepted.
@@ -182,12 +183,17 @@ Additional security hardening tracked outside the section 16 list:
## Before Public Launch
- Keep `cargo test`, `make bench-docker-ssh`, and `make bench-docker-mosh` green.
- Run `make soak-local` before launch to produce 30-minute sleep/roaming evidence.
- Run `make fuzz-deep` before launch, or use the scheduled/manual CI fuzz pass, and
publish the target durations.
- Keep scripted TUI tests green and add a broader app matrix for real alternate-screen
tools.
- Publish benchmark output with raw samples, not just averages.
- Mark prediction as experimental until it has a real framebuffer model.
- Stress-test `persist_sessions = true` before making restart-survivable holders the
default.
- Add reliable retransmission for forwarded stream data before claiming TCP
forwarding survives arbitrary UDP packet loss.
- Tune the native auth token bucket under abusive real-host traffic.
- 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).
+18 -14
View File
@@ -188,24 +188,28 @@ be evaluated honestly. Items here are *not* yet "green".
half-finished handshakes on a TTL, and reports remaining capacity in
`ServerHello`. It is covered by unit/integration tests, but still needs abusive
real-host tuning before public hardening claims.
- **Protocol VERSION compatibility policy is still simple.** The wire format pins a
single protocol version: the packet header rejects any non-matching `VERSION` byte
and the native handshake rejects any non-matching `protocol_version`. There is no
multi-version negotiation yet, so cross-version interop and downgrade-resistance for
future versions are still being designed. Today's behavior is fail-closed (reject),
not silent downgrade.
- **Fuzzing is smoke-tested in CI, not yet a deep campaign.** CI runs parser/auth
fuzz targets briefly with nightly/cargo-fuzz when available. That catches obvious
panics and parser robustness regressions; it is not a substitute for longer
coverage-guided fuzz campaigns before public security claims.
- **Protocol VERSION compatibility is intentionally single-version for v1.** The
packet header rejects any non-matching `VERSION` byte and the native handshake
rejects any non-matching `protocol_version`; peers get a named upgrade error, not
a silent downgrade. `docs/PROTOCOL_VERSIONING.md` defines the bump rules and the
post-v1 requirements for any future multi-version negotiation.
- **Deep fuzzing still needs launch evidence.** CI runs parser/auth fuzz targets for
20 seconds per target on push/PR and 300 seconds per target on weekly/manual runs
when nightly/cargo-fuzz is available. That catches obvious panics and parser
robustness regressions; public security claims should cite a completed
`make fuzz-deep` or scheduled CI run with durations.
- **User-key algorithm coverage now matches the v1 target.** Ed25519, ECDSA P-256,
and compatibility RSA-SHA2 native auth are implemented for ssh-agent and OpenSSH
identity files. RSA remains compatibility-only and deliberately rejects legacy
SHA-1 `ssh-rsa` signatures.
- **Hostile-network and long-soak integration tests are partial.** Roaming,
retransmit, resize, and multi-client tests exist; a dedicated adversarial
drop/reorder/replay suite and 30-minute-sleep soak (spec section 16) are still being
expanded.
- **Forwarded stream data is not yet reliable across arbitrary UDP loss.** Terminal
frames have retransmit coverage; forwarding streams have flow control and
replay/reorder tests, but dropped `StreamData` recovery requires stream
retransmission before Dosh should claim TCP-forwarding parity on lossy links.
- **Long-soak evidence is a launch gate.** Roaming, retransmit, resize, and
multi-client tests exist, and `sleep_roaming_soak_30m` / `make soak-local` provide
the 30-minute sleep/roaming gate. That gate should be run and published before
public security/reliability claims.
- **No external security review yet.** The spec's milestone 5 requires an external
review checklist before public security claims. That review has not happened.