#networking #time #ntp

bin+lib rkik

Rusty Klock Inspection Kit - NTP Query and Compare Tool

17 releases (9 stable)

Uses new Rust 2024

new 2.2.1 May 13, 2026
2.1.0 Jan 24, 2026
2.0.0 Dec 16, 2025
1.2.1 Nov 25, 2025
0.6.0 Jul 30, 2025

#464 in Network programming

Download history 294/week @ 2026-01-21 153/week @ 2026-01-28 188/week @ 2026-02-04 266/week @ 2026-02-11 255/week @ 2026-02-18 446/week @ 2026-02-25 469/week @ 2026-03-04 396/week @ 2026-03-11 421/week @ 2026-03-18 670/week @ 2026-03-25 701/week @ 2026-04-01 471/week @ 2026-04-08 721/week @ 2026-04-15 745/week @ 2026-04-22 1028/week @ 2026-04-29 696/week @ 2026-05-06

3,241 downloads per month

MIT license

125KB
3K SLoC

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 and NTS 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 Rust implementation of RFC 8915 verified against real public servers (time.cloudflare.com, nts.ntp.se). Older tools either skip authentication or implement it wrong.
  • Two protocols, one tool. NTP over IPv4/IPv6 and NTS with full TLS diagnostics — compare mode, JSON output, and Nagios/Centreon plugin support included.
  • The only NTS-aware monitoring plugin for Nagios, Centreon and Zabbix

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.2.0-1_amd64.deb

# Fedora / RHEL / Alma / Rocky
sudo dnf install rkik-2.2.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.


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.

Dependencies

~11–26MB
~272K SLoC