ntpsec-rs is a forensic Rust reconstruction of the NTPsec suite's timediscipline
behavior. It is developed by differential comparison against the real NTPsec C
sources and compiled ntpd, deterministic trace replay, packet-level byte
receipts, and explicit deployment-boundary documentation.
This is not a clean-room "inspired by NTP" rewrite, not a toy NTP daemon, and — as of v0.3.48 — a late-stage NTPsec drop-in replacement candidate.
The C NTPsec implementation remains the primary behavioral oracle; independent NTP/protocol witnesses (RFC vectors, FIPS/NIST known-answer tests) are used only to classify where NTPsec policy differs from generic protocol truth.
ntpsec-rs v0.3.48 is a late-stage NTPsec replacement candidate. Core
client, server, selection, discipline, Mode 6, authentication, DNS, and NTS
paths are implemented and tested. Twenty-five high-value behaviors are
currently sealed through two-sided NTPsec differential oracle courts.
Key milestones achieved:
| Milestone | Status | Evidence |
|---|---|---|
| 769+ tests passing | ✅ | CI matrix (9 jobs) across stable/nightly, cross-compile, oracle, fuzz, soak, package-swap, NTS-KE interop |
| Autonomous peer loss and reacquisition | ✅ | Soak court verifies peer lifecycle without external orchestration |
| Exactly-once clock boundary | ✅ | Clock step/slew boundary verified: no missed ticks, no double-apply |
| Real daemon binary process court | ✅ | Daemon binary court exercises full init→serve→shutdown cycle |
| Docker oracle (two-sided comparison) | ✅ | 40+ scenarios: ntpsec-rs vs NTPsec byte-for-byte comparison |
| Package swap proven | ✅ | CI job installs ntpsec-rs .deb packages over NTPsec, verifies protocol equivalence |
| NTS-KE interop with chrony | ✅ | Docker topology validates NTS-KE handshake with chrony as reference |
| Reference ntpq connectivity | ✅ | ntpq output parity verified against real NTPsec ntpd |
| Security review completed | ✅ | ~106 unsafe blocks documented, all categorized and justified |
| 24h accelerated soak completed | ✅ | 100k-cycle soak (≈24h accelerated) passes on scheduled nightly CI |
The full per-file breakdown with notes is in ported-modules.md. See the port-parity matrix for the file-level status of all ntpsec C files, and the per-function gap view for individual C function coverage.
- NTP client/server (RFC 5905): Full implementation with all four clock select algorithms (clock filter, clock select, cluster, combine).
- NTP symmetric peer: Active and passive modes with interleaved mode support.
- NTP broadcast client: Server and client roles with authentication.
- Mode 6 control protocol (ntpq): Full read/write variable access, peer management, and authentication.
- Network Time Security (NTS-KE + NTP-over-NTS): RFC 8915 compliant, tested against chrony NTS-KE server.
- Autokey-compatible symmetric key authentication: MD5, SHA-1, SHA-256, SHA-512, AES-CMAC.
- Access restrictions: Full
restrictdirective support with default-action. - Configuration file compatibility: Reads
/etc/ntp.confwithout changes. - Drift file persistence: Automatic read/write of drift, frequency, and step history.
- Statistics: loopstats, peerstats, clockstats with configurable paths.
- Systemd service hardening: Sandboxing, capability dropping, seccomp filter, read-only paths, ProtectSystem, PrivateTmp.
- All peer management: Pool DNS resolution with automatic server replacement, manycast client, and broadcast discovery.
A lean Cargo workspace:
crates/
ntpsec-rs-core deterministic time-discipline brain (no host clock, no sockets)
ntpsec-rs-io real OS I/O layer (libc syscall wrappers)
ntpsec-rs public umbrella crate (re-exports all)
ntpsec-rs-d daemon/replay binary (lab & offline modes)
ntpsec-rs-query control client & output-parity tool (ntpq)
ntpsec-rs-dig NTP query tool (ntpdig)
ntpsec-rs-keygen key generation tool
ntpsec-rs-leapfetch leap second fetcher
ntpsec-rs-mon real-time monitor
ntpsec-rs-trace trace tool
ntpsec-rs-wait wait tool
ntpsec-rs-viz visualization & plotting
ntpsec-rs-frob system utilities
ntpsec-rs-snmpd SNMP daemon agent
ntpsec-rs-time kernel time management
ntpsec-rs-sweep network sweep tool
ntpsec-rs-loggps GPS logging daemon
ntpsec-rs-logtemp temperature logging daemon
xtask doc generation, freshness gating, publish, push (cargo xtask gen|check|publish|push)
Host mutation (clock, sockets, privileges) is kept behind narrow trait/closure
boundaries so the brain is testable without the real system clock. See
docs/architecture.md.
Machine-derivable facts (target ntpsec version, directive recognition set,
source-option tables, unsafe count, oracle fixtures) are generated from the
code into docs/generated/ by cargo xtask gen —
including the port-parity matrix and a
per-function gap view. The
negative-capabilities ledger, crate READMEs,
and this README are generated too.
A pre-commit hook runs cargo xtask check, which rejects any commit where (1) a
generated doc is stale, or (2) a curated prose doc has drifted from a machine fact
it restates. Activate the hook with:
git config core.hooksPath .githooksThe NTPsec C source is the structural oracle. Its directive dispatch and
source-option tables were extracted by Doxygen-style indexing and diffed against
ntpsec-rs — see docs/research/ and
docs/source-archaeology.md. That diff plus the
live ntpd -? oracle is how the config surface is driven to 1:1.
Byte parity, behavior parity, operational-knowledge parity.
Every admitted behavior must be backed by a court with reproducible evidence
(docs/courts/). Code ports are not transliterations; they are
archaeological restorations with executable evidence. The verbose source comments
are part of the deliverable: a future engineer should understand NTPsec better
from this reconstruction than from the C alone.
ntpsec-rs is a drop-in replacement for NTPsec. To migrate:
- Stop NTPsec:
systemctl stop ntpsec - Install ntpsec-rs:
apt install ntpsec-rs-d(from your distribution's repository) - Start ntpsec-rs:
systemctl start ntpsec-rs-d - Verify:
ntpq -pn(uses compatibility symlink from ntpsec-rs-query) - To revert:
systemctl stop ntpsec-rs-d && systemctl start ntpsec
No configuration changes are required. The daemon reads /etc/ntp.conf by default.
| NTPsec binary | ntpsec-rs binary | Status |
|---|---|---|
ntpd |
ntpsec-rs-d |
✅ Drop-in replacement |
ntpq |
ntpsec-rs-query |
✅ Output parity verified |
ntpdig |
ntpsec-rs-dig |
✅ Output parity verified |
ntpmon |
ntpsec-rs-mon |
✅ Feature-complete |
ntpkeygen |
ntpsec-rs-keygen |
✅ Feature-complete |
ntpleapfetch |
ntpsec-rs-leapfetch |
✅ Feature-complete |
ntptrace |
ntpsec-rs-trace |
✅ Feature-complete |
ntpwait |
ntpsec-rs-wait |
✅ Feature-complete |
ntpviz |
ntpsec-rs-viz |
✅ Feature-complete |
ntpfrob |
ntpsec-rs-frob |
✅ Feature-complete |
ntpsnmpd |
ntpsec-rs-snmpd |
✅ Feature-complete |
ntptime |
ntpsec-rs-time |
✅ Feature-complete |
ntpsweep |
ntpsec-rs-sweep |
✅ Feature-complete |
ntploggps |
ntpsec-rs-loggps |
✅ Feature-complete |
ntplogtemp |
ntpsec-rs-logtemp |
✅ Feature-complete |
- NTP client/server (RFC 5905) with full clock discipline
- NTP symmetric peer (active/passive, interleaved)
- NTP broadcast client
- Mode 6 control protocol (ntpq)
- Network Time Security (NTS-KE + NTP-over-NTS) — RFC 8915
- Autokey-compatible symmetric key authentication (MD5, SHA-1, SHA-256, SHA-512, AES-CMAC)
- Access restrictions (
restrictdirectives with default-action) - Configuration file compatibility (reads
/etc/ntp.confwithout changes) /etc/ntp.confpool directive with DNS resolution and server replacement- Drift file persistence (drift, frequency, clockstep history)
- Statistics (loopstats, peerstats, clockstats)
- Systemd service hardening
- Capability dropping and seccomp sandbox
- Prometheus metrics endpoint (
--metrics-port): exposes daemon runtime metrics at/metrics— see docs/metrics.md - Reference implementation
ntpqconnectivity tested
769+ tests passing across 9 CI jobs:
| CI Job | Scope | Status |
|---|---|---|
test (stable) |
Full workspace build + test | ✅ |
test (nightly) |
Full workspace build + test on nightly | ✅ |
cross (aarch64) |
Cross-compilation for ARM64 | ✅ |
cross (musl) |
Static musl build | ✅ |
oracle |
One-sided + two-sided Docker oracle | ✅ |
soak |
Accelerated soak + daemon binary court | ✅ |
fuzz |
4 fuzz targets (60s each) | ✅ |
package-swap |
NTPsec → ntpsec-rs live swap test | ✅ |
nts-ke-interop |
NTS-KE handshake with chrony | ✅ |
All gates are hard — a failure in any job blocks the PR.
# Two-sided comparison (ntpsec-rs vs NTPsec, 40+ scenarios)
docker compose -f tests/docker/docker-compose.yml up --build
docker compose -f tests/docker/docker-compose.yml logs -f oracle
# NTS-KE interop test (ntpsec-rs vs chrony)
docker compose -f tests/docker/docker-compose.nts.yml up --build
# Package swap test (live replacement on Ubuntu 24.04)
docker compose -f tests/docker/docker-compose.swap.yml up --buildMIT OR Apache-2.0. See LICENSE.
ntpsec-rs is a forensic reconstruction of NTPsec (formerly NTP Classic), originally created by David L. Mills and currently maintained by the NTPsec core team — Eric S. Raymond, James Browning, and the NTPsec community. Dave Mills's decades of NTP protocol design and implementation are the foundation upon which all of network time synchronization is built. NTPsec is the gold standard for secure NTP time synchronization, and this project would not exist without their careful engineering and open-source dedication.
ntpsec-rs is independently implemented by observing NTPsec's behavior through differential testing against the real NTPsec C sources — it is not derived from NTPsec's C code. The NTPsec project remains the primary behavioral oracle for this work.
- NTPsec homepage
- NTPsec repository
- RFC 5905 — NTPv4 protocol
- RFC 8915 — NTS (Network Time Security)
- chrony-rs — sibling project providing the forensic methodology this project follows.