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”.