How To Setup an NTS Server
In the video below, we show you how to setup an NTS server using Debian or Ubuntu
What we’ll be covering is how to set up a NTS server
Normally you would set up your own Network Time Protocol (NTP) server to get time from the Internet and point your internal computers to that
But NTP wasn’t designed with security in mind and so now we have Network Time Security (NTS) in its place
Install Chrony
Now because this video is about NTP and NTS, I’m going to assume that you already know how to install Ubuntu or Debian to save time
But to build our own time server we want to install chrony which is a popular solution for NTP, but it also supports NTS
Because I want to cover both Debian and Ubuntu, we’ll first switch to the root account
On Ubuntu you could use
sudo su -
On Debian you could use
su -
We want to make sure that the package information is up to date before installing anything
apt update
Then we’ll install chrony
apt install chrony -y
Configure NTP Server:
We want to setup the computer to update its own clock using NTS
But by default, chrony will be configured to synch to some NTP servers
In which case, We’ll edit the config file
nano /etc/chrony/chrony.conf
Comment out any lines referencing NTP pools/servers by prepending the line with a #, for example
#pool 2.debian.pool.ntp.org iburst
And add the following line
server time.cloudflare.com iburst nts
At the time of recording, Cloudflare provide a Publicly available server which supports NTS
But it would be good to add others that you know of for redundancy, especially regional ones
The iburst option is intended to speed up the initial synchronisation which is benefical when a computer starts from cold for instance and it’s clock may have fallen behind a bit
The nts option is to request the use of NTS, otherwise it will just use NTP
Because most devices on your internal network will support NTP, and some may not support NTS, we’ll only configure this as an NTP server initially
It also makes sense to get NTP up and running first, before we add the NTS capabalities, to make sure this part is already working
By default, access to the NTP server will be blocked so we need to allow access but only for what’s necessary
And you can allow access by adding something like the following at the end of the config file
# Allow access to NTP server
allow 192.168.1.0/24
This line allows access to the NTP server for computers in the 192.168.1.0/24 network
Add additional lines for each internal network you want to access this
Now save the file and exit
Check if the NTP service is active
timedatectl status
If the output says that the NTP service is inactive, run the following command to activate it
timedatectl set-ntp true
Now restart the chrony service for the changes to take effect
systemctl restart chrony
Verify Chrony
We need to make sure the computer can synch its own time first
To view the time source servers being used by the computer, run the following command
chronyc sources -v
Assuming the computer’s clock is reasonably accurate, it should only take a brief amount of time for it to synchronise
When it does, you should see ^* at the start of the line. This is an easy way to see which server was chosen as the best, although in this example we’ve only told chrony about one server anyway
If all you see is ^? then the computer needs time to synchronise or cannot access that server
Running the following command will provide more details for the software clock and the synchronisation with the chosen server
chronyc tracking
While this command will provide further details on the time servers in terms of how close the clocks are to the computer’s for instance
chronyc sourcestats
And this command will let you confirm if you have an authenticated connection using NTS
chronyc -N authdata
In our case we’d expect to see the mode set to NTS for time.cloudflare.com
Once we know the server has been able to synch its clock with a time server, we can focus on internal clients
You can check NTP server statistics using the following command which can be useful to see NTP versus NTS use
chronyc -N serverstats
And the following command provides per client statistics, including details of if a specific device managed to connect using NTS
chronyc -N clients -k
NOTE: TLS, which is being used for NTS, relies on an accurate clock which puts us in a chicken and egg situation if your computer’s date and time is too far behind In which case check the date and time on the computer to make sure it’s up to date
date
If it’s not, we can fix this manually
We need to temporarily disable NTP to avoid an override
timedatectl set-ntp false
Then set the correct date and time, for instance
date -s '30 May 2023 13:05:00'
Now synch the hardware clock with the system clock we’ve just set
hwclock --systohc
And double check for good measure
hwclock
Now re-enable NTP
timedatectl set-ntp true
Configure UFW
It’s a good security practice to run a personal firewall such as UFW on Linux computers to further restrict access
In order to allow access to an internal NTP/NTS server add lines such as these
ufw allow proto udp from 192.168.1.0/24 to any port 123
ufw allow proto tcp from 192.168.1.0/24 to any port 4460
NOTE: If the server has more than one interface the rule should restrict the destination address as well to only the interface(s) NTP/NTS should be accessed on i.e. a non-management interface
Configure NTP Client
Internal clients will need to be reconfigured to use the NTP server as their source
For Linux clients, install chrony as before but use the server we’ve created as the source, for example
server 192.168.1.1 iburst
To view the time source servers being used by the computer, run the following command
sudo chronyc sources -v
NOTE: Because we have only setup NTP, you won’t see any authenticaion details if you check
Remove NTP Sources
On thing to point out is that a Linux distro may have its own NTP setup going on the background
On PoP!_OS for instance, I’ve noticed the computer tries to connect to several system76 servers using NTS
For security reasons this is being blocked by my firewall as the goal is for clients to connect to the internal server only and so only the NTP server has access to time servers on the Internet using TCP port 4460 and UDP port 123
If you see this and prefer for these other servers to not be used at all then remove any .sources file in the /etc/chrony/sources.d folder, for example
sudo rm /etc/chrony/sources.d/system76-nts.sources
Then restart chrony
sudo systemctl restart chrony
Configure NTS Server
If you have devices that support NTS and you can provide the server with a TLS certificate and private key that clients will trust, you can configure the NTP server to support NTS internally
How you do that depends on your circumstances, but you can set these up using OpenSSL for instance, just like you would for a web server
Bear in mind, you will then have to find a means to configure the client to trust the root CA
Once you have a certificate and private key, copy them to the /var/lib/chrony/ folder
And make sure these are readable by chrony, for example
chown _chrony:_chrony /var/lib/chrony/ntp1.key && chmod 0440 /var/lib/chrony/ntp1.key
chown _chrony:_chrony /var/lib/chrony/ntp1.crt && chmod 0440 /var/lib/chrony/ntp1.crt
Now edit the edit the config file
nano /etc/chrony/chrony.conf
And add the following lines for instance
ntsserverkey /var/lib/chrony/ntp1.key
ntsservercert /var/lib/chrony/ntp1.crt
While we’re here, check to make sure the following line is present higher up
ntsdumpdir /var/lib/chrony
If not, then add it
According to the chrony manual this is disabled by default, but I noticed the line was already there on a Debian server and is a recommendation from the likes of Red Hat who use chrony by default on their distros. This is THE Linux distro for enterprises so they must know something
This tells chrony where to save NTS cookies so that it doesn’t need to make an initial NTS-KE request when chronyd is started again
Restart the Chrony service for the changes to take effect
systemctl restart chrony
And check the service is working
systemctl status chrony
Bear in mind, NTS uses TCP port 4460 so if the server is behind a firewall, you will need to allow access to this. Access to UDP port 123 is still required as NTS-KE in the first phase and NTP in the second
Configure NTS Client
For NTS to work, the client needs to trust the Root CA that signed the TLS certificate
One option is to do this as part of the client setup of Chrony but rather than do this for one application/service I’d rather have the OS trust my Root CA so that this is a one off process
To do this on Debian based Linux distros, create a new folder for user provided certificates
sudo mkdir /usr/share/ca-certificates/extra
Copy the root CA certificate to this folder and make sure root owns this, for instance
sudo cp root-ca.crt /usr/share/ca-certificates/extra
sudo chown root:root /usr/share/ca-certificates/extra/root-ca.crt
Now edit the CA-certificates file
sudo nano /etc/ca-certificates.conf
Append the following line at the end
extra/root-ca.crt
For this to take effect update the CA certificates
sudo update-ca-certificates
You might get some feedback suggesting there was a problem, but if you run this command again it will no longer appear
You can then check if the connection works, by running this command for instance
chronyd -Q -t 3 'server ntp1.homelab.lan iburst nts maxsamples 1'
In this case we’re referencing the NTP server using its FQDN because that’s what the certificate was created for
Want you want to see is output like the following
2023-05-25T16:55:57Z chronyd version 4.2 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-05-25T16:55:57Z Disabled control of system clock
2023-05-25T16:56:00Z System clock wrong by -0.000494 seconds (ignored)
2023-05-25T16:56:00Z chronyd exiting
In other words, this is telling us that the connection worked, albeit the clock is slightly different
To use NTS, update the chrony file
sudo nano /etc/chrony/chrony.conf
Change the existing line by using its FQDN instead and also add the nts parameter, for instance
server ntp1.homelab.lan iburst nts
Now restart the Chrony service for the changes to take effect
sudo systemctl restart chrony
To view the time source servers being used by the computer, run the following command
sudo chronyc sources -v
And this command will let you confirm if the connection is authenticated
sudo chronyc -N authdata
TIP: If the mode isn’t showing as NTS, but the server does show NTS had been used, reboot the client
Check Server Connections
As a final check, it’s worth looking to see what the server is reporting
You can check NTP server statistics using the following command which can be useful to see NTP versus NTS use
chronyc -N serverstats
And the following command provides per client statistics, including details of if a specific device managed to connect using NTS
chronyc -N clients -k
Sharing is caring!