Network Time Security with Chrony on Linux
Network Time Security (NTS) provides cryptographic authentication and integrity verification for the Network Time Protocol (NTP), protecting Linux systems against time spoofing and man-in-the-middle attacks. This article explains how the NTS protocol functions within Chrony—the default NTP client and server on modern Linux distributions—detailing its two-phase architecture, client and server configuration, and the commands required to verify secure time synchronization.
Understanding NTS Architecture in Chrony
Traditional NTP relies on unencrypted UDP packets sent over port 123, leaving network systems vulnerable to packet alteration and replay attacks. NTS resolves this by combining public key infrastructure (PKI) with symmetric cryptography. Chrony implements NTS through two distinct phases:
- NTS Key Establishment (NTS-KE): The Chrony client establishes a standard TLS connection to an NTS-KE server over TCP port 4460. During this handshake, the client validates the server's identity using standard TLS certificates. Once verified, the server generates symmetric encryption keys and encapsulates them inside cryptographic cookies, which are then passed back to the client over TLS. The TLS session is closed once this exchange completes.
- NTS-Secured NTP: The Chrony client sends standard NTP packets over UDP port 123, supplemented with NTS extension fields. These extensions include one of the received cookies and a cryptographic authentication code (AEAD). The server uses its master key to decrypt the cookie, retrieve the symmetric key, verify packet integrity, and attach a fresh cookie to the response.
This dual-stage mechanism enables stateless operation on the server side, ensuring high scalability while guaranteeing that the Linux host only synchronizes with authenticated time sources.
Configuring Chrony as an NTS Client
Most modern Linux distributions, such as Debian, Ubuntu, Fedora, and
RHEL, ship with Chrony versions supporting NTS (version 4.0 and newer).
To enable NTS, adjust Chrony’s primary configuration file, typically
located at /etc/chrony.conf or
/etc/chrony/chrony.conf.
1. Define NTS Time Sources
Add NTS-capable time servers by appending the nts
directive to the server declaration:
server time.cloudflare.com iburst nts
server ptbtime1.ptb.de iburst nts
server nts.netnod.se iburst nts
2. Specify Trusted Certificates
Chrony must validate the TLS certificates presented during the NTS-KE
handshake. You can declare the path to the system CA bundle using the
ntstrustedcerts directive:
- RHEL/CentOS/Fedora:
ntstrustedcerts /etc/pki/tls/certs/ca-bundle.crt - Debian/Ubuntu:
ntstrustedcerts /etc/ssl/certs/ca-certificates.crt
If no certificate path is explicitly defined, Chrony attempts to use the default system trust store automatically.
3. Apply Configuration
Restart the Chrony service via systemctl to apply
changes:
sudo systemctl restart chronyd(On Debian/Ubuntu systems, the service name may be
chrony instead of chronyd.)
Configuring Chrony as an NTS Server
To configure a Linux machine as an NTS server for local or network clients, Chrony requires valid TLS certificates (such as those obtained via Let's Encrypt):
# NTP server settings
local stratum 2
allow 192.168.1.0/24
# NTS server settings
ntsservercert /etc/ssl/certs/ntp-server.crt
ntsserverkey /etc/ssl/private/ntp-server.key
Chrony will automatically bind to TCP port 4460 to serve NTS-KE requests and UDP port 123 for secure NTP transactions.
Verifying NTS Operation
To confirm that Chrony is actively communicating via NTS, execute the
chronyc command-line utility.
Run the authdata command:
chronyc authdataIn the output table, observe the KeyID and Type columns:
- NTS should appear in the
Typecolumn. - An active key identifier, cookie counts, and verification statuses should be visible. A non-zero number of cookies demonstrates that key rotation is functioning correctly.
Run the sources command:
chronyc sources -vLook for the state flag next to the configured server. A
* indicates that the clock is actively synchronizing with
that authenticated source. If authentication fails, Chrony rejects the
response and refuses to adjust the system clock, preventing unauthorized
network manipulations from compromising system logs, cryptographic
tokens, or scheduled tasks.