The configuration of NTP deviates from what I'd call intuitive. It installs, by default, a client which reads and writes the system's clock and starts listening on all interfaces and bridges and eagerly uses them to provide informations about its status without authentication.
I had a hard time gathering all informations and documentation to get this (hopefully) right. Even the default configuration file contained several statements that aren't covered by the man-pages.
The following configuration seems to work fine without providing excessive informations and services.
This is the configuration to be installed on the host machine to enforce a client-only operation:
>> my-host:/etc/ntp.conf
# stop listening for incoming connections an all interfaces including 0.0.0.0 and [::]
interface ignore all
interface ignore wildcard
# only allow listening on the interface used to contact the time servers
interface listen 10.2.20.2
# your pools or servers
pool 0.debian.pool.ntp.org iburst
pool 1.debian.pool.ntp.org iburst
pool 2.debian.pool.ntp.org iburst
pool 3.debian.pool.ntp.org iburst
# by default drop all incoming connections on all interfaces
restrict default ignore
# unrestriced control for local connections
restrict 127.0.0.1
restrict ::1
# Needed for adding pool entries
restrict source notrap nomodify noquery
Restarting the service gives us a comprehensible list of listening sockets. (my-host:ntp
cannot be avoided because of the way NTPd works.)
my-host:# netstat -a|grep ntp
udp 0 0 my-host:ntp 0.0.0.0:*
udp 0 0 localhost:ntp 0.0.0.0:*
udp6 0 0 localhost:ntp [::]:*
This is the configuration to be installed on the router-container to enforce a server-only operation (backed by the system's clock as source of time, thanks to @BillThor):
>> router:/etc/ntp.conf
# don't update the system's clock
disable kernel
# local clock as preferred and only source
server 127.127.1.0 prefer
# stop listening for incoming connections an all interfaces including 0.0.0.0 and [::]
interface ignore all
interface ignore wildcard
# whitelist addresses to listen on for NTP clients
interface listen 10.1.2.1
interface listen 10.2.2.2
interface listen 10.3.2.3
interface listen 10.4.2.4
interface listen 10.5.2.5
# set "serve" as the only permission given to all listening interfaces per default
restrict default kod notrap nomodify nopeer noquery limited
# unrestriced control for local connections
restrict 127.0.0.1
restrict ::1
# broadcast time (optional)
broadcast 10.1.255.255
broadcast 10.2.255.255
broadcast 10.3.255.255
broadcast 10.4.255.255
broadcast 10.5.255.255
Restarting the service gives us the local clock as preferred source and a list of (optional) broadcast targets
router:# ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
*LOCAL(0) .LOCL. 5 l 16 64 3 0.000 0.000 0.000
10.1.255.255 .BCST. 16 B - 64 0 0.000 0.000 0.000
10.2.255.255 .BCST. 16 B - 64 0 0.000 0.000 0.000
10.3.255.255 .BCST. 16 B - 64 0 0.000 0.000 0.000
10.4.255.255 .BCST. 16 B - 64 0 0.000 0.000 0.000
10.5.255.255 .BCST. 16 B - 64 0 0.000 0.000 0.000
... and a comprehensible list of listening sockets to serve the local network.
router:# netstat -a|grep ntp
udp 0 0 router-lan5:ntp 0.0.0.0:*
udp 0 0 router-lan4:ntp 0.0.0.0:*
udp 0 0 router-lan3:ntp 0.0.0.0:*
udp 0 0 router-lan2:ntp 0.0.0.0:*
udp 0 0 router-lan1:ntp 0.0.0.0:*
udp 0 0 localhost:ntp 0.0.0.0:*
udp6 0 0 localhost:ntp [::]:*
The disable kernel
(thanks to @PaulGear) prohibits the daemon from setting the system's clock which isn't allowed within a typical container. Otherwise it floods the log with:
ntpd[1568]: adj_systime: Operation not permitted
On startup there are still some harmless glitches, I don't know how to get rid of:
ntpd[1568]: start_kern_loop: ntp_loopfilter.c line 1119: ntp_adjtime: Operation not permitted
ntpd[1568]: set_freq: ntp_loopfilter.c line 1082: ntp_adjtime: Operation not permitted