Who queries a public NTP server? 6 million addresses in 5 days
A public NTP server knows nothing about its clients except their address and how many packets they send. We recorded those two facts every hour for five days on the 18 servers of the RDEM Systems NTP fleet: the 16 Stratum 2 servers and our two Stratum 1 servers, all of them in the NTP pool. Here is what those 117 readings say about who asks for the time.
Method and limits
- One reading per hour, from 28 October 2026 at 10:00 to 2 November at 06:00 (UTC): 117 readings,
none missed. Each reading takes chrony's client table (
chronyc clients) and its counters (chronyc serverstats) on every server. - A client is active in a given hour if its packet counter has increased since the previous reading. chrony keeps an address in its table long after its last request: being listed proves nothing.
- Addresses are never written down. Each one is replaced on reading by a fingerprint (HMAC-SHA256) whose key is held in memory, never on disk, and will be destroyed when this edition closes: the fingerprints can then no longer be matched to any address.
- Our own traffic is removed: our servers querying each other, and our probes.
- An address is not a device. Behind a shared IPv4 address (corporate NAT, carrier-grade NAT) there can be thousands of devices. In IPv6, a device changes temporary address over the days (RFC 8981), so we group those by /64 prefix. We talk about addresses, never devices.
- The figures are minimums. chrony occasionally overwrites entries in its table; an overwritten client that comes back is recreated and counted, but part of the activity between two readings can be missing.
- A configuration changed along the way. On 29 and 30 October, a new configuration (diversified sources, rate limiting) was deployed on the fleet, with a chrony restart on every server. Counters are added up across the restart; rate limiting is dealt with separately.
- We measure our servers, not NTP in general. What a pool server receives depends on its zones (Europe and France for ours) and on the share the pool gives it.
IPv4 and IPv6: 16% of addresses, 7% of requests
Over the window we saw 6,053,669 addresses: 5,078,898 over IPv4 and 974,771 over IPv6. Grouped by /64, the latter make 935,414 clients, or 6,014,312 distinct clients in total. Each full day counts 1.7 to 1.9 million. These addresses sent 71,901,008 requests.
IPv6 weighs half as much in requests as in addresses: its clients do not stay. Even grouped by /64, 91% of IPv6 clients are seen during a single hour only, so the rotation of temporary addresses does not explain it all. Another feature: a server's IPv6 volume varies sevenfold from one day to the next, depending on the share the pool sends it. The IPv6 figures of any single day describe the pool's distribution more than the demand; we only quote averages over the window.
Regular clients and passing clients
Two populations share our servers. One-off clients are active during a single hour out of 117: a device asking for the time at boot, a script, a test tool. Regular clients come back hour after hour, typically a synchronisation daemon (chrony, ntpd, systemd-timesyncd) polling its sources at a fixed interval.
37% of IPv4 addresses send 91% of IPv4 requests. Regular clients stay a median 49 hours between their first and last request seen. One-off clients are the majority by number (62.9%) and almost invisible in load: three quarters send a single packet. Over IPv6 the imbalance is stronger still: 9% regular clients, who send 74.1% of IPv6 requests.
| Time seen | IPv4 (per address) | IPv6 (per /64) |
|---|---|---|
| a single hour | 62.9% | 91% |
| under 6 h | 4.2% | 3.9% |
| 6 to 24 h | 6.3% | 2.5% |
| 24 h or more | 26.7% | 2.6% |
The daily rhythm
The number of active addresses follows the European day: about 104,000 per hour in the dead of night (between 02:00 and 04:00), 168,000 at the 17:00 peak, a factor of 1.6. Requests vary by a factor of only 1.26 (from 542,000 to 683,000 per hour): regular clients, which make most of the volume, run day and night; it is the passing clients that follow office hours.
The window covered the All Saints' Day weekend, with no marked dip: on average 147,000 active addresses per hour on Thursday, 141,000 on Friday, 140,000 on Saturday and 137,000 on Sunday.
One client, how many servers?
The pool spreads clients by giving each DNS query a few servers picked at random within a zone. Seen from our fleet, the spreading works: 72.4% of addresses query only one of our 18 servers over five days.
At the other end, 198 addresses query all 18 of our servers, all over IPv6, active a median 116 hours out of 117, with thousands of packets each. These are addresses that would appear to be, for the most part, the monitors of the NTP pool, the public and collaborative pool, which continuously measure each server to compute its score: over a hundred monitors follow each of the two servers we checked.
The small peak at 17 servers has a simple explanation: over IPv4, only 17 of our servers can be reached, because ntp-0-gps has no public IPv4 address (the site's single IPv4 serves ntp-0-gnss). Of these 16,320 addresses, about 1,000 are active nearly every hour, like the previous ones. The others are active only every other hour in the median, with few packets: most likely addresses shared by many devices, which the pool's rotation ends up sending to each of our servers.
NTS: around one percent
All our servers serve NTS, authenticated time. Excluding our own traffic, the share of client
requests authenticated with NTS is around one percent. The public pool pool.ntp.org does
not publish NTS: its zones return a different machine on each lookup, run by a different operator, whereas NTS requires
a certificate bound to the name queried (see NTS end to end). An NTS client has
therefore been configured on purpose, with the name of a specific server or of an NTS pool: our private pool,
ntp-pool.rdem-systems.com, is configured with NTS, and an experimental public NTS pool exists, sectime.org
(see NTS on chrony).
Rate limiting
A public server also gets overly chatty clients: firmware polling in a loop, badly written scripts. chrony can limit the rate per address and stop answering those above the threshold. On our fleet, this limit was deployed during the measurement, on 29 and 30 October, so we keep the two regimes apart.
| Requests dropped | Before | After |
|---|---|---|
| All families | 0.03% | 4.8% |
| IPv4 | 0.03% | 5.2% |
| Depending on the server | 0 to 0.1% | 2.8% to 7.1% |
About one request in twenty is now dropped, almost only over IPv4: over IPv6, just 174 requests were in five days. We name no address and no operator. The behaviours involved and the operator-side countermeasures are described in running a pool server.
What we take from it
- Load comes from daemons, numbers come from passers-by. Sizing a server on the number of addresses overestimates it; the share of regular clients is what makes the rate.
- IPv6 is here, but passing through. 16% of addresses, 7% of requests: lasting IPv6 clients remain rare.
- NTS is still a matter of hand-configured clients, around one percent of requests.
- Rate limiting costs little and filters one request in twenty, without touching IPv6.
We will run this measurement again. Each edition will have its own dated section on this page, and earlier ones will stay online for comparison.
Sources
- chronyc documentation (4.6.1) —
clientsandserverstatscommands - chrony.conf documentation (4.6.1) —
ratelimitandclientloglimitdirectives - RFC 8981 — IPv6 temporary addresses
- pool.ntp.org — the public and collaborative NTP pool
- Internal — our infrastructure, why contribute to the pool, running a pool server