top of page
Search

In the interest of Time

  • Sep 14
  • 7 min read

How to create a secure Network Time Server (NTP) & configure NTP clients


ree

Build Document:

Category

Requirement

 Document Build Number

SOS230625V01

 Document Type

NTP Server & NTP Client installation

 Operating System

Ubuntu Server 24.04 LTS (Minimal Install)


The accuracy of a device's time settings is often underrated. All independent clocks drift over time and become inaccurate. Essential logs which are utilized to troubleshoot problems and used forensically to examine security incidents are heavily dependent having accurate time stamps. In addition it is more secure to create a local NTP server on your network and have NTP clients connect to it rather than have each client on your network connect to the Internet for time services.


First step install chrony, the modern network time server.

$  sudo apt update && apt -y install chrony

Next configure chrony to pull time from secure, trusted public NTP servers - To configure chrony in this way we need to edit /etc/chrony/chrony.conf - Backup /etc/chrony/chrony.conf then comment out the default NTP servers to make chrony.conf appear similar to the below. -


sosuser@opensosntp:/etc/chrony$ sudo cp /etc/chrony/chrony.conf   /etc/chrony/chrony.conf_ORIG

sosuser@opensosntp:/etc/chrony$ sudo nano /etc/chrony/chrony.conf

# Welcome to the chrony configuration file. See chrony.conf(5) for more
# information about usable directives.

# Include configuration files found in /etc/chrony/conf.d.
confdir /etc/chrony/conf.d

# This will use (up to):
# - 4 sources from ntp.ubuntu.com which some are ipv6 enabled
# - 2 sources from 2.ubuntu.pool.ntp.org which is ipv6 enabled as well
# - 1 source from [01].ubuntu.pool.ntp.org each (ipv4 only atm)
# This means by default, up to 6 dual-stack and up to 2 additional IPv4-only
# sources will be used.
# At the same time it retains some protection against one of the entries being
# down (compare to just using one of the lines). See (LP: #1754358) for the
# discussion.

# About using servers from the NTP Pool Project in general see (LP: #104525).
# Approved by Ubuntu Technical Board on 2011-02-08.
# See http://www.pool.ntp.org/join.html for more information.

#pool ntp.ubuntu.com        iburst maxsources 4
#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
#pool 2.ubuntu.pool.ntp.org iburst maxsources 2


# Use secure public NTP servers (choose a trusted pool or specific servers)
server time.cloudflare.com iburst
server time.google.com iburst
server time.facebook.com iburst
server time.windows.com iburst

# Allow internal network to sync time from this server, add YOUR networks
# allow 10.0.0.0/8
allow 192.168.6.0/24

# Listen for incoming NTP requests
bindaddress 0.0.0.0

# Optional: local stratum fallback if no external servers are reachable
local stratum 10

####
# Use time sources from DHCP.
sourcedir /run/chrony-dhcp

# This directive specify the location of the file containing ID/key pairs for
# NTP authentication.
keyfile /etc/chrony/chrony.keys

# This directive specify the file into which chronyd will store the rate
# information.
driftfile /var/lib/chrony/chrony.drift

# Save NTS keys and cookies.
ntsdumpdir /var/lib/chrony

# Uncomment the following line to turn logging on.
#log tracking measurements statistics

# Log files location.
logdir /var/log/chrony

# Stop bad estimates upsetting machine clock.
maxupdateskew 100.0

# This directive enables kernel synchronisation (every 11 minutes) of the
# real-time clock. Note that it can't be used along with the 'rtcfile' directive.
rtcsync

# Step the system clock instead of slewing it if the adjustment is larger than
# one second, but only in the first three clock updates.
makestep 1 3

# Get TAI-UTC offset and leap seconds from the system tz database.
# This directive must be commented out when using time sources serving
# leap-smeared time.
leapsectz right/UTC



  • In the above /etc/chrony/chrony.conf file remember to change "allow 192.168.6.0"

    to a value that represents the network(s) you will allow NTP clients to connect from.


Before proceeding, ensure that your system’s local clock is accurately configured. If the NTP server we are configuring is unable to reach upstream time sources, it will fall back on the local clock—so it must be correct to maintain reliable time across clients.

 
sosuser@opensosntp:/etc/chrony$ timedatectl status
			   Local time: Sun 2025-06-29 22:20:04 UTC
		   Universal time: Sun 2025-06-29 22:20:04 UTC
                 RTC time: Sun 2025-06-29 22:20:04
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
  • Lets change the local clock to the correct time, by setting the correct time zone. For us to be able to change the local clock we will need to disable time synchronization (sudo timedatectl set-ntp false) so that we can force changes to the time on the local clock.


$ sudo timedatectl set-timezone America/New_York
$ sudo timedatectl set-ntp false 
$ sudo timedatectl set-time "2025-06-29 17:52:00"                   

$ timedatectl status
Local time: Sun 2025-06-29 17:54:50 EDT
Universal time: Sun 2025-06-29 21:54:50 UTC
RTC time: Sun 2025-06-29 21:54:51
Time zone: America/New_York (EDT, -0400)
System clock synchronized: no
NTP service: inactive
RTC in local TZ: no

Now that local time on the server is correctly configured and verified its time to start chrony and verify the status of the chrony client.

 $ sudo systemctl start chrony
 $ sudo systemctl enable chrony

 $ systemctl status chrony
● chrony.service - chrony, an NTP client/server
Loaded: loaded (/usr/lib/systemd/system/chrony.service; enabled                                                        Active: active (running) since Sun 2025-06-29 18:03:54 EDT; 1h 1min ago

$ chronyc activity
200 OK
4 sources online
0 sources offline
0 sources doing burst (return to online)
0 sources doing burst (return to offline)
0 sources with unknown address



$ chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^+ time.cloudflare.com           3   7   373   113  -2899us[-2899us] +/-   31ms
^* time4.google.com              1   6   377   114  +2791us[+2617us] +/-   24ms
^+ time4.facebook.com            1   7   377   115  -3115us[-3289us] +/-   31ms
^+ 40.119.6.228                  3   6   377    47  +1798us[+1798us] +/-   66ms

$ chronyc tracking

Reference ID    : D8EF230C (time4.google.com)
Stratum         : 2
Ref time (UTC)  : Sun Jun 29 23:25:02 2025
System time     : 0.000044235 seconds fast of NTP time
Last offset     : +0.000120695 seconds
RMS offset      : 0.000237082 seconds
Frequency       : 5.118 ppm slow
Residual freq   : -0.000 ppm
Skew            : 0.110 ppm
Root delay      : 0.047045529 seconds
Root dispersion : 0.000417993 seconds
Update interval : 129.5 seconds
Leap status     : Normal

Below we will first add a Windows NTP client to the NTP server, then add an Ubuntu client to the server.

Windows 11 NTP client
Windows 11 NTP client
  • On the above Windows 11 computer open services, find the Windows Time service, start it and set it's Startup Type to "Automatic"


Next right click the Windows command prompt to open it with "Run as administrator" permissions and run the following commands to connect to the Open Source NTP server we created on the server with IP address "192.168.6.196"

Windows 11 NTP client
Windows 11 NTP client

The following steps will add a Linux computer running Ubuntu 24.04 as a NTP client. The first step is to install chrony.


sosuser@Ubuntu22Desktop:~$ hostname
Ubuntu22Desktop

sosuser@Ubuntu22Desktop:~$ sudo apt update && apt install -y chrony
Hit:1 http://security.ubuntu.com/ubuntu jammy-security InRelease
Hit:2 https://dl.google.com/linux/chrome/deb stable InRelease                                           
Hit:3 http://pe.archive.ubuntu.com/ubuntu jammy InRelease                                               
Hit:4 http://pe.archive.ubuntu.com/ubuntu jammy-updates InRelease                
Hit:5 http://pe.archive.ubuntu.com/ubuntu jammy-backports InRelease
Hit:6 https://ppa.launchpadcontent.net/mozillateam/ppa/ubuntu jammy InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
195 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages will be REMOVED:
  systemd-timesyncd
The following NEW packages will be installed:
  chrony
0 upgraded, 1 newly installed, 1 to remove and 195 not upgraded....

Next backup the original /etc/chrony/chrony.conf file. Then edit the live chrony.conf by commenting out the original pool of NTP servers and adding the IP address of the new NTP server, similar to below.

sosuser@Ubuntu22Desktop:~$ sudo cp /etc/chrony/chrony.conf /etc/chrony/chrony.conf_ORIG

sosuser@Ubuntu22Desktop:~$ sudo nano /etc/chrony/chrony.conf

# Welcome to the chrony configuration file. See chrony.conf(5) for more
# information about usable directives.

# Include configuration files found in /etc/chrony/conf.d.
confdir /etc/chrony/conf.d

# This will use (up to):
# - 4 sources from ntp.ubuntu.com which some are ipv6 enabled
# - 2 sources from 2.ubuntu.pool.ntp.org which is ipv6 enabled as well
# - 1 source from [01].ubuntu.pool.ntp.org each (ipv4 only atm)
# This means by default, up to 6 dual-stack and up to 2 additional IPv4-only
# sources will be used.
# At the same time it retains some protection against one of the entries being
# down (compare to just using one of the lines). See (LP: #1754358) for the
# discussion.
#
# About using servers from the NTP Pool Project in general see (LP: #104525).
# Approved by Ubuntu Technical Board on 2011-02-08.
# See http://www.pool.ntp.org/join.html for more information.
#pool ntp.ubuntu.com        iburst maxsources 4
#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
#pool 2.ubuntu.pool.ntp.org iburst maxsources 2
server 192.168.6.182

  • You can leave all the other entries of the chrony.conf with their defaults

  • Save the /etc/chrony/chrony.conf file and restart chrony

  • Also make sure that chrony starts after a reboot by enabling the chrony service.

sosuser@Ubuntu22Desktop:~$ sudo systemctl restart chrony

sosuser@Ubuntu22Desktop:~$ sudo systemctl enable chrony

Synchronizing state of chrony.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable chrony

 

Finally verify that the chrony client on Linux is working and pulling time from the NTP server:



sosuser@Ubuntu22Desktop:~$ sudo chronyc tracking
[sudo] password for sosuser: 
Reference ID    : C0A806B6 (192.168.6.182)
Stratum         : 3
Ref time (UTC)  : Mon Jul 07 17:33:07 2025
System time     : 0.000015730 seconds fast of NTP time
Last offset     : +0.000036781 seconds
RMS offset      : 0.000041848 seconds
Frequency       : 5.050 ppm slow
Residual freq   : +0.005 ppm
Skew            : 0.286 ppm
Root delay      : 0.047718432 seconds
Root dispersion : 0.000613245 seconds
Update interval : 259.5 seconds
Leap status     : Normal
sosuser@Ubuntu22Desktop:~$ sudo chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 192.168.6.182                 2   8   377   236    +23us[  +59us] +/-   24ms
sosuser@Ubuntu22Desktop:~$ 
  • Above you should see your internal NTP server listed with a * indicating it's the selected source:

  • If however you get the below question mark give it sometime and try again, if the question mark is a ! you have a communication problem.


Conclusion

Establishing accurate and reliable time synchronization across all systems is a foundational step in gaining full control of your network infrastructure. Inconsistent or drifting system clocks can lead to a range of issues, from troubleshooting difficulties to critical security vulnerabilities. By implementing open-source NTP servers, organizations gain a high degree of control and flexibility, ensuring consistent timekeeping that supports operational integrity and enhances incident response capabilities.





 
 

Recent Posts

See All
  • Grey Twitter Icon
  • Grey LinkedIn Icon
  • Grey Facebook Icon

© 2035 by Talking Business. Powered and secured by Wix

bottom of page