NTPD: Setting up an NTP server on DD-WRT or OpenWRT
Recent power outages and ISP outages left my network without a proper internal NTP server which was, coincidently, installed on an ESXi host. Having to revert to an external NTP server for the time being, a recent outage with my ISP highlighted the fact that even that isn't enough. The ISP outage () made it clear I need a solution that is:
- Sitting on a lower power device and external to my LAB, so isolated from any large server hosted device.
- Doesn't depend on DNS to syn cup time in case an ISP is offline.
- Maintain an accurate time on it's own so it itself will be a reliable source of time when everything is offline.
So went with an OpenWRT and a Raspberry Pi device for just this very thing. This is super simple:
opkg update
opkg install ntpd
/etc/init.d/sysntpd disable
/etc/init.d/ntpd enable
/etc/init.d/ntpd start
netstat -l | grep ntp
Configure the external NTP servers to use ( NOTE: See additional information below in the EDIT section for extra iptions or the configuration will not work. ):
root@OWRT01:~# cat /etc/config/system
config system
option ttylogin '0'
option log_size '64'
option urandom_seed '0'
option hostname 'OWRT01'
option log_proto 'udp'
option conloglevel '8'
option cronloglevel '5'
option timezone 'EST5EDT,M3.2.0,M11.1.0'
option zonename 'America/Toronto'
option log_ip 192.168.0.14
option log_port 514
option log_proto udp
config timeserver 'ntp'
list server '0.ca.pool.ntp.org'
list server '1.ca.pool.ntp.org'
list server '2.ca.pool.ntp.org'
root@OWRT01:~#
Set the time manually, in the event the system can't sync it's time with an external server:
# date
# date -k
So our brand new NTP server is sitting on:
192.168.0.12
Let's now set the Date / Time to sync from this NTP server. For Cisco switches:
mdscisco01#conf t
Enter configuration commands, one per line. End with CNTL/Z.
mdscisco01(config)#ntp server 192.168.0.12
mdscisco01(config)#end
mdscisco01#show run
mdscisco01#show running-config
Ensure local time is also set correctly:
mdscisco02#
mdscisco02#conf t
Enter configuration commands, one per line. End with CNTL/Z.
mdscisco02(config)#clock timezone EST -5
mdscisco02(config)#end
mdscisco02#clock set 11:52:00 July 10 2022
mdscisco02#copy run
mdscisco02#copy running-config startup-config
Destination filename [startup-config]?
Building configuration…
Compressed configuration from 7043 bytes to 2639 bytes[OK]
mdscisco02#
For Linux Servers:
[root@mbpc-pc ~]# cat /etc/ntp.conf|grep -Eiv "^#"
driftfile /var/lib/ntp/drift
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict -6 ::1
server 192.168.0.12
server idmipa01.nix.mds.xyz prefer
server idmipa02.nix.mds.xyz prefer
server 0.rhel.pool.ntp.org iburst
server 1.rhel.pool.ntp.org iburst
server 2.rhel.pool.ntp.org iburst
server 3.rhel.pool.ntp.org iburst
includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
For DD-WRT, configure via the basic config to use the OpenWRT NTP server:
Configure ESXi hosts you may have:
REF: https://openwrt.org/docs/guide-user/services/ntp/client-server
REF: https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst3750x_3560x/software/release/12-2_55_se/configuration/guide/3750xscg/swadmin.html
REF: https://wiki.dd-wrt.com/wiki/index.php/Network_Time_Protocol#:~:text=You%20cannot%20set%20your%20time,to%20match%20your%20local%20time.
EDIT: Aug 17 2022
An additional option is required to make this a server:
root@OWRT01:/tmp/log# cat /etc/config/system
config system
option ttylogin '0'
option log_size '64'
option urandom_seed '0'
option hostname 'OWRT01'
option log_proto 'udp'
option conloglevel '8'
option cronloglevel '5'
option timezone 'EST5EDT,M3.2.0,M11.1.0'
option zonename 'America/Toronto'
option log_ip 192.168.0.14
option log_port 514
option log_proto udp
config timeserver 'ntp'
list server '0.ca.pool.ntp.org'
list server '1.ca.pool.ntp.org'
list server '2.ca.pool.ntp.org'
option enable_server '1'
root@OWRT01:/tmp/log#
Restart the service:
root@OWRT01:/tmp/log# service ntpd restart
The above results in:
root@OWRT01:/tmp/log# cat /var/etc/ntpd.conf
driftfile /var/lib/ntp/ntp.drift
restrict default limited kod nomodify notrap nopeer
restrict -6 default limited kod nomodify notrap nopeer
restrict source noquery
# No limits for local monitoring
restrict 127.0.0.1
restrict -6 ::1
server 0.ca.pool.ntp.org iburst
server 1.ca.pool.ntp.org iburst
server 2.ca.pool.ntp.org iburst
root@OWRT01:/tmp/log#
Without the above, errors such as these will be shown:
Jan 1 03:51:00 DD-WRT-BEESWAX user.info : [ntpclient] : Network Time Protocol client trying to stop
Jan 1 03:51:00 DD-WRT-BEESWAX daemon.info process_monitor[1824]: _evalpid:ntpclient 192.168.0.12
Jan 1 03:51:00 DD-WRT-BEESWAX daemon.debug ntpclient[7036]: Connecting to 192.168.0.12 [192.168.0.12] …
Jan 1 03:51:03 DD-WRT-BEESWAX daemon.debug ntpclient[7036]: Timed out waiting for 192.168.0.12 [192.168.0.12].
Jan 1 03:51:03 DD-WRT-BEESWAX daemon.err process_monitor[1824]: cyclic NTP Update failed (servers 192.168.0.12)
Jan 1 03:51:33 DD-WRT-BEESWAX daemon.info process_monitor[1824]: _evalpid:stopservice ntpc -f
Jan 1 03:51:33 DD-WRT-BEESWAX user.info : _evalpid:/sbin/service ntpc stop
Without the server line, the NTP server will receive the request but will refuse to send the client time. A few typical messages:
root@OWRT01:~# strace -s 256 -f -p 701
[pid 701] _newselect(59, [48 49 50 51 53 54 55 56 57 58], NULL, NULL, NULL) = 1 (in [54])
[pid 701] clock_gettime(CLOCK_REALTIME, {tv_sec=1660757832, tv_nsec=325460418}) = 0
[pid 701] recvmsg(54, {msg_name={sa_family=AF_INET, sin_port=htons(34957), sin_addr=inet_addr(“192.168.0.21″)}, msg_namelen=28->16, msg_iov=[{iov_base=”\33\0\4\372\0\1\0 \0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\203\252\360=\246>\215\323”, iov_len=2120}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_TIMESTAMPNS, cmsg_data={tv_sec=1660757832, tv_nsec=324808641}}], msg_controllen=20, msg_flags=0}, 0) = 48
[pid 701] recvmsg(54, {msg_namelen=28}, 0) = -1 EAGAIN (Resource temporarily unavailable)
[pid 701] _newselect(59, [48 49 50 51 53 54 55 56 57 58], NULL, NULL, NULL) = 1 (in [54])
[pid 701] clock_gettime(CLOCK_REALTIME, {tv_sec=1660757833, tv_nsec=286244526}) = 0
[pid 701] recvmsg(54, {msg_name={sa_family=AF_INET, sin_port=htons(44107), sin_addr=inet_addr(“192.168.0.19″)}, msg_namelen=28->16, msg_iov=[{iov_base=”\33\0\4\372\0\1\0 \0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\203\252\202\264\200\n\215\34”, iov_len=2120}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_TIMESTAMPNS, cmsg_data={tv_sec=1660757833, tv_nsec=285534936}}], msg_controllen=20, msg_flags=0}, 0) = 48
[pid 701] recvmsg(54, {msg_namelen=28}, 0) = -1 EAGAIN (Resource temporarily unavailable)
REF: https://oldwiki.archive.openwrt.org/doc/howto/ntp.client
REF: https://forum.openwrt.org/t/ntp-server-through-busybox-ntp/91344/6
HTH