Recent versions of NTP include a “pool” automatic discovery mode, which can used neatly with the pool.ntp.org project. To use this mode, rather than defining multiple individual server
associations in your NTP configuration, you use one pool
definition instead:
This single association declaration tells ntpd
to make multiple DNS requests to pool.ntp.org
, which results in associations for multiple participating servers. Check out the results of host pool.ntp.org
to see the mechanism in action. ntpd
also intelligently detects duplicate servers, and polls enough candidates to maintain accuracy in case any peers go rogue.
However, when changing /etc/ntp.conf/
on macOS Sierra I found that the pool
association wasn’t working: ntpq -p
would never show any real associations:
$ ntpq -pn
remote refid st t when poll reach delay offset jitter
==============================================================================
pool.ntp.org .POOL. 16 p - 64 0 0.000 0.000 0.001
It turns out that Apple’s default NTP configuration needs a couple of tweaks to get this working. The first trick is knowing how to modify \etc\ntp.conf
without the System Preferences GUI overwriting it. It turns out that adding a blank comment line to the file is enough - the GUI will only update the first line in the file, and leave everything else alone. Here’s an example:
server time.asia.apple.com.
#
pool pool.ntp.org
Line 1 is maintained by System Preferences, but line 3 and beyond is left alone thanks to the dividing comment. Easy.
Now, back to my initial problem: the pool
declaration not having the expected result. It turns out that this is down to the restrict
settings in ntp-restrict.conf
. Here’s what an out-of-the-box copy of \etc\ntp-restrict.conf
looks like in macOS 10.12.4:
# Access restrictions documented in ntp.conf(5) and
# http://support.ntp.org/bin/view/Support/AccessRestrictions
# Limit network machines to time queries only
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
# localhost is unrestricted
restrict 127.0.0.1
restrict -6 ::1
includefile /private/etc/ntp.conf
includefile /private/etc/ntp_opendirectory.conf
Note the “nopeer” flags. Here’s what the NTP documentation has to say about this, emphasis mine:
Deny packets that might mobilize an association unless authenticated. This includes broadcast, symmetric-active and manycast server packets when a configured association does not exist. It also includes pool associations, so if you want to use servers from a pool directive and also want to use nopeer by default, you’ll want a “restrict source …” line as well that does not include the nopeer directive.
So there’s the answer: add a restrict source
line somewhere in the configuration which relaxes the nopeer
directive. Here’s my line:
restrict source nomodify notrap noquery
I figured that because of it’s use by System Preferences, \etc\ntp.conf
is less likely to be overwritten by software updates than \etc\ntp-restrict.conf
is, so I’ve added the new line to ntp.conf
. But shrug. My final configuration can therefore be boiled down to this:
server time.asia.apple.com.
pool pool.ntp.org
restrict default limited kod nomodify notrap nopeer noquery
restrict -6 default limited kod nomodify notrap nopeer noquery
restrict source nomodify notrap noquery
restrict 127.0.0.1
restrict -6 ::1
(The “kod” flag is meaningless without the “limited” flag, so I’ve fixed that as well.)
I spent longer troubleshooting this than I would have liked, mainly because an identical NTP configuration on an up-to-date Debian server didn’t exhibit the same problem. It turns out that there was a change in NTP version 4.2.7 which resulted in the “nopeer” directive disabling pool associations. Debian currently uses version 4.2.6 of NTP, while macOS Sierra is 4.2.8. It was this section from a post to the NTP mailing list that finally set me off in the right direction:
“restrict source” establishes a prototype restriction automatically added for each association’s IP address. Previously using the pool interfered with some locked-down restriction scenarios because the IP addresses of the pool servers used for a given run of ntpd were not predictable, so the default restriction had to be loose enough to allow retrieving time. “restrict source” allows the operator to configure looser restrictions automatically applied to each association address and tighter “restrict default”.