- Rust 67.9%
- Shell 23.4%
- Scheme 5.8%
- Makefile 2.8%
- Common Lisp 0.1%
| .builds | ||
| .jerboa | ||
| bin | ||
| crates/jsshd-core | ||
| docs | ||
| examples | ||
| fuzz | ||
| packaging | ||
| scripts | ||
| support | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| jpkg.sexp | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| SECURITY.md | ||
jerboa-sshd
Experimental SSH server for Jerboa-managed network services.
The intended split is conservative:
- Rust owns SSH transport, packet framing, key exchange, crypto, auth state, channel flow control, and later PTY/SFTP plumbing.
- Jerboa owns policy, configuration, supervision, audit logging, reloads, and OS sandbox orchestration.
See docs/secure-jerboa-sshd-plan.md for the current design plan.
Current Status
jsshd-core is now a config-driven Rust SSH daemon using russh with the
aws-lc-rs crypto backend. It supports:
- OpenSSH host keys, config, and authorized-key files opened once with no-follow, owner, link-count, parent-directory, size, and mode checks on Unix
- OpenSSH
authorized_keysparsing for configured SSH users - public-key authentication only
- exact-match restricted
execcommands - bounded stdin/stdout/stderr, command timeouts, and process-group cleanup
- connection, user, and server-wide live-exec permits held for the complete child lifetime, plus a per-connection command-start rate limit
- global connection limiting
- configured Unix rlimits inherited by child commands
- bind-before-sandbox startup, with optional Unix
chroot,chdir,setgid,setuid, and Linux Landlock filesystem rules - Jerboa wrapper entrypoint for build/check/run/health/supervise/smoke workflows
- cargo-fuzz targets for config, authorized-key, and exec-request parsers
- systemd and launchd service examples
- rejection of password, keyboard-interactive, shell, PTY, agent forwarding, X11, TCP forwarding, streamlocal forwarding, and subsystems
- optional telemetry through one bounded nonblocking queue and one worker with a numeric collector address and a total send deadline
Build
Install the audit tool once:
cargo install cargo-audit --locked
make check
make test
make lint
make audit
make fuzz-check
make smoke
make smoke-hardening
make jerboa-smoke
make verify
Bounded local coverage-guided fuzz evidence is generated with:
JSSHD_RUN_COVERAGE_FUZZ=1 JSSHD_FUZZ_RUNS=2048 make fuzz-evidence
Release evidence is generated with:
make release-evidence
The release bundle includes SBOM, RustSec, reproducibility, bounded fuzz status,
and SSHD connection/load status under dist/release-evidence/. Default local
evidence records sustained connection/load soak as blocked/not-run; production
release requires target-host connection/load evidence beyond the OpenSSH,
hardening, and bounded local connection-load smokes.
Configuration
Start from examples/jsshd.example.toml.
max_exec_sessions_per_connection, max_exec_sessions_per_user, and
max_exec_sessions_global bound live child operations; closing an SSH channel
does not release a permit until its process group is terminated and the direct
child is reaped. max_exec_starts_per_minute bounds accepted start attempts on
each connection. Relative trusted-file paths may not contain ..; every parent
must be root- or daemon-owned and non-writable by group/other (root-owned sticky
temporary directories are permitted for local tests).
Production mode requires a host private key:
ssh-keygen -t ed25519 -N '' -f ssh_host_ed25519_key
chmod 600 ssh_host_ed25519_key
cargo run -p jsshd-core -- --config jsshd.toml
Development mode can use an ephemeral host key, but clients will see a new host identity on every restart:
JSSHD_DEV_EPHEMERAL_HOST_KEY=1 cargo run -p jsshd-core -- --config jsshd.toml
Validate config without starting the listener:
cargo run -p jsshd-core -- --config jsshd.toml --check-config
Or use the Jerboa wrapper:
/Users/user/mine/jerboa/.chez/bin/scheme --libdirs /Users/user/mine/jerboa/lib --script bin/jsshd.ss check --config jsshd.toml
/Users/user/mine/jerboa/.chez/bin/scheme --libdirs /Users/user/mine/jerboa/lib --script bin/jsshd.ss health --config jsshd.toml
/Users/user/mine/jerboa/.chez/bin/scheme --libdirs /Users/user/mine/jerboa/lib --script bin/jsshd.ss run --config jsshd.toml
/Users/user/mine/jerboa/.chez/bin/scheme --libdirs /Users/user/mine/jerboa/lib --script bin/jsshd.ss supervise --config jsshd.toml
Environment overrides are available for deployment glue:
JSSHD_CONFIGJSSHD_BINDJSSHD_HOST_KEYJSSHD_DEV_EPHEMERAL_HOST_KEYJSSHD_ALLOW_SANDBOX_FALLBACKJSSHD_ALLOW_LANDLOCK_FALLBACK
Optional Secmon telemetry uses SECMON_TELEMETRY_ADDR (or
SECMON_TELEMETRY_CONNECT) and requires a numeric IP:port, not a hostname,
so hostile events cannot consume an unbounded DNS resolver path. The fixed
queue drops excess events rather than blocking SSH protocol work.
See docs/deployment.md for release, host-key, sandbox, service-manager, health-check, and rollback guidance.