Project Awesome project awesome

rkik

CLI tool designed for stateless and passive NTP inspection, just as dig or ping are for DNS and ICMP. It supports async requests and continuous monitoring.

Package 56 stars GitHub

rkik - Rusty Klock Inspection Kit

Build & Tests crates.io Packaging status

Think dig, but for time sources. No daemon, no root, no config to touch.

rkik queries NTP, NTS, and PTP servers and tells you what they say — offset, RTT, stratum, authentication status. One shot, stateless, done.


Why rkik?

  • Passive by design. It never touches your system clock unless you explicitly ask (--sync). Run it anywhere, as anyone.
  • NTS that actually works. rkik-nts 1.0.0 is the first CLI implementation of RFC 8915 verified against real public servers (time.cloudflare.com, nts.ntp.se). Older tools either skip authentication or implement it wrong.
  • Three protocols, one tool. NTP over IPv4/IPv6, NTS with full TLS diagnostics, and PTP/IEEE 1588 — all with compare mode, JSON output, and Nagios/Centreon plugin support.

Demo

asciicast

$ rkik --nts time.cloudflare.com -v

Server: time.cloudflare.com [NTS Authenticated]
IP: 162.159.200.1:123
UTC Time: Tue, 28 Apr 2026 14:32:10 +0000
Local Time: 2026-04-28 16:32:10
Clock Offset: 1.243 ms
Round Trip Delay: 14.871 ms

=== NTS-KE Diagnostics ===
Handshake Duration: 87.342 ms
Cookies Received:   8 cookies
AEAD Algorithm:     AEAD_AES_SIV_CMAC_256
NTP Server:         162.159.200.1:123

=== TLS Certificate ===
Subject:    CN=time.cloudflare.com
Issuer:     C=US, O=DigiCert Inc, CN=GeoTrust TLS ECC CA G1
Valid:      2025-02-10 → 2026-03-12
Fingerprint (SHA-256): 4b060f4d...462119
SANs:       time.cloudflare.com

Installation

cargo install rkik

Arch Linux (AUR):

yay -S rkik-git

Nix / NixOS:

nix shell nixpkgs#rkik

DEB / RPM / tar.gz: grab the latest from GitHub Releases.

# Debian / Ubuntu
sudo apt install ./rkik_2.1.0-1_amd64.deb

# Fedora / RHEL / Alma / Rocky
sudo dnf install rkik-2.1.0-1.x86_64.rpm

Packaging status


Quick start

# Basic NTP probe
rkik pool.ntp.org

# NTS — cryptographically authenticated
rkik --nts time.cloudflare.com

# Compare a few servers side by side
rkik --compare pool.ntp.org time.google.com time.cloudflare.com

# Plugin output for Nagios / Centreon / Zabbix
rkik pool.ntp.org --plugin --warning 50 --critical 200

# JSON, prettified
rkik pool.ntp.org --json --pretty

NTP

rkik time.google.com              # basic probe
rkik time.google.com -v           # adds stratum, ref ID
rkik time.google.com --count 10 --interval 2   # repeat 10 times
rkik -6 pool.ntp.org              # IPv6-only resolution

Output:

Server: time.google.com
IP: 216.239.35.4:123
UTC Time: Tue, 28 Apr 2026 14:32:08 +0000
Local Time: 2026-04-28 16:32:08
Clock Offset: 0.312 ms
Round Trip Delay: 9.449 ms

NTS — Network Time Security ★

NTS (RFC 8915) is authenticated NTP — every packet is verified with AEAD encryption, so you know the response hasn't been tampered with.

rkik --nts time.cloudflare.com          # authenticated probe
rkik --nts time.cloudflare.com -v       # with TLS/KE diagnostics
rkik --nts --compare nts.ntp.se time.cloudflare.com

When something goes wrong, rkik tells you what kind of failure it is:

Kind Meaning
aead_failure AEAD verification failed — possible tampering
missing_authenticator Authenticator extension absent in response
unauthenticated_response Server completed NTS-KE but sent plain NTP
ke_handshake_failed TLS or NTS-KE handshake failed
timeout Connection timed out

Security-critical failures (aead_failure, missing_authenticator, unauthenticated_response, invalid_unique_id, invalid_origin_timestamp) exit with code 2 in plugin mode.

See docs/user-guide.md#nts for the full error reference.


PTP — Precision Time Protocol

PTP mode (IEEE 1588-2019) is Linux-only and requires the ptp feature (on by default).

rkik --ptp 192.0.2.10
rkik --ptp --ptp-domain 24 --ptp-event-port 3319 --ptp-general-port 3320 127.0.0.1
rkik --ptp --compare 192.168.1.100 192.168.1.101 --format json

See docs/user-guide.md#ptp for flags and output format.


Plugin mode

rkik time.google.com --plugin --warning 50 --critical 200
# → RKIK OK - offset 4.006ms rtt 9.449ms from time.google.com (216.239.35.4) | offset_ms=4.006ms;50;200;0; rtt_ms=9.449ms;;;0;

Exit codes: 0 OK · 1 WARNING · 2 CRITICAL · 3 UNKNOWN (request failed or security error)


Debugging a time issue

Your monitoring fires a time alert on ntp.server.local. You don't know yet whether the problem is that server or its upstream.

$ rkik ntp.server.local -v
Clock Offset: 5000.145 ms
Reference ID: 145.238.80.80

Five seconds of drift, and you can see the upstream. Check it directly:

$ rkik 145.238.80.80
Clock Offset: 5001.531 ms

Same offset upstream. The problem isn't your server — it's the reference. Time to point it somewhere else.


For developers

rkik is split into a library and a CLI. The library has no clap, no process::exit, no terminal code — just async functions you can call directly.

[dependencies]
rkik = { version = "2", default-features = false, features = ["json"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
use rkik::query_one;
use std::time::Duration;

let r = query_one("time.google.com", false, Duration::from_secs(3), false, 4460).await?;
println!("{}: offset={:.3}ms", r.target.name, r.offset_ms);

Full API reference, architecture overview, and contribution guide: docs/developer-guide.md

To contribute, see CONTRIBUTING — issues labelled good first issue are a good starting point.

Back to Rust