© Copyright 2014, Christophe Wolfhugel
Last update: December 23 2015 (new GQ key for ntp.sentrion.eu)
This NTP autokey experimentation lasted nearly two years and I have decided to put an end to it: actually either the implementation is so complex that I fail to understand its logic, or it is so broken that I do not wish to spend the time fixing it. I would have been fully happy with the Public Certificate scheme, which is easy to setup server side, but for which validation does not seem implemented on the client side.
The documentation and keys provided below are given for education purposes only but can no longer be used. You can still query my NTP servers as they are public. I have switched to using symetric keys for my internal network and clients.
After having spent several pair of days over the last years by reading, re-reading available documentation, and then exprimenting again and again, I have come to a rather disappointing conclusion regarding the use of the autokey feature in the NTP implementation: the only autokey identity scheme I have been able to configure and use is GQ (Guillou-Quisquater). Note to readers: I did not try to configure MV identity scheme.
This short article will give you some insight on how I did configure my own
strtum 2 reference time servers (
ntp.wolfhugel.eu), and how I configured my NTP client nodes (with
this article showing
smile.wolfhugel.eu as an example) to
get authenticated timestamps from the reference servers. Feel free to replicate
this configuration and use it for yourself to get time from my machines.
Note to software, hardware and boxes vendors: due to the quantities you sell or distribute, I am sorry, but you are not welcome to synchronize time on these servers as they do not have the capacity to handle thousands or millions or client devices: create your own infrastructure for your customers, this documentation might help you doing so.
All my experimentations were made with NTP 4.2.6, all being issued from several quite recent Debian distributions.
If you just want to fetch authenticated timestamps from my servers without knowing the internals, just jump to this section and taylor the instructions to your own NTP server and hopefully it will work!
Comments are more than welcome, please send them to chris at wolfhugel dot eu.
This is one of my reference time servers, the second being
which is configured in a similar way. Both servers take time from stratum 1 and stratum 2
servers on the Internet (and these sessions are unfortunately not authenticated). The
peer each other in an authenticated manner and they serve time
to my internal network, as well as as to any Internet user wishing to fetch time, be it
authenticated or not. The public service would cease should it become abused.
I do use "/usr/local/etc/ntp" to store all keys material.
First, I will need to generate a trusted certificate and the GQ key and parameters on this node:
$ cd /usr/local/etc/ntp $ ntp-keygen -T -G -m 2048Parameter "-T" is for trusted self signed certificate, "-G" is for the GQ authentication model, and finally "-m 2048" indicates a 2048-bit key size. Once this has been generated the directory looks like this:
-rw-r--r-- 1 root staff 490 Aug 4 14:47 ntpkey_GQkey_ntp.sentrion.eu.3616152474 -rw-r--r-- 1 root staff 1203 Aug 4 14:47 ntpkey_RSA-MD5cert_ntp.sentrion.eu.3616152474 -rw-r--r-- 1 root staff 1901 Aug 4 14:47 ntpkey_RSAhost_ntp.sentrion.eu.3616152474 lrwxrwxrwx 1 root staff 45 Aug 4 14:47 ntpkey_cert_ntp.sentrion.eu -> ntpkey_RSA-MD5cert_ntp.sentrion.eu.3616152474 lrwxrwxrwx 1 root staff 39 Aug 4 14:47 ntpkey_gqkey_ntp.sentrion.eu -> ntpkey_GQkey_ntp.sentrion.eu.3616152474 lrwxrwxrwx 1 root staff 41 Aug 4 14:47 ntpkey_host_ntp.sentrion.eu -> ntpkey_RSAhost_ntp.sentrion.eu.3616152474The "ntp-keygen" command automatically generates timestamps and symbolic links. Once you have these you need to extract the GQ public parameters to be given via any means (HTTP is OK) to remote parties:
$ ntp-keygen -e > ntpkey_gqpar_ntp.sentrion.eu $ ls -l ntpkey_gqpar_ntp.sentrion.eu -rw-r--r-- 1 root staff 279 Aug 4 14:48 ntpkey_gqpar_ntp.sentrion.euThis file will have to be distributed to all machines who are going to take time from you and who wish to authenticate your timestamps.
Excerpts from the configuration file:
leapfile /usr/local/etc/ntp/leap-seconds.3535228800 statsdir /var/log/ntpstats/ statistics cryptostats filegen cryptostats file cryptostats type week enable ## Crypto stuff. keysdir /usr/local/etc/ntp crypto ## My servers. peer ntp.wolfhugel.eu autokey ## tea (eth1) server x.y.z.t ## my non authenticated external source # By default, exchange time with everybody, but don't allow configuration. restrict -4 default kod notrap nomodify nopeer noquery restrict -6 default kod notrap nomodify nopeer noquery restrict 172.20.19.0 mask 255.255.255.0 kod notrap nomodify nopeer restrict 2001:41d0:2:c731:: mask ffff:ffff:ffff:ffff:: kod notrap nomodify nopeer restrict 172.20.19.5 kod notrap notrust restrict 2001:41d0:2:c731:1::5 kod notrap notrust # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1
Only "cryptostats" configuration is shown above. Feel free to use additional log or statistics files as permitted by NTP. The "cryptostats" file allows you to check that the GQ parameter files are correctly used and read when needed.
For the ease of management, I do use a dedicated keys directory configured in "keysdir", and then with the "crypto" keyword I will enable cryptography, and this assumes the server name is actually the system's real hostname (i.e. "hostname" gives you the long host name).
When defining a "server" or a "peer" the important keyword here is "autokey" which indicates NTP to use the autokey feature, and in this example I will use autokey with my other server "ntp.wolfhugel.eu". Of course both servers need to be configured to use the same mechanism, i.e. GQ in this particular case.
Furthermore, the "restrict" configuration allows to enforce NTP authentication, i.e. non authenticated packets would be rejected. My restrict clauses have several levels:
Leapfile: according to all documentation read, each time autokey was involved authors
indicated that a
leapfile configuration option must be present. I did find no
explanation as to why this is required for autokey and not when using unauthenticated
connections. The current leapfile can be downloaded at
This section suggests how you could configure your own NTP server in order to
synchronize to both
and authenticate the timestamps. The client machine used in this example is
smile.wolfhugel.eu and takes its time only from my own
servers - I could of course add additional time sources.
We will assume following in this section:
ntpddaemon was compiled with cryptography enabled.
Once your NTP daemon is properly installed and running, you want to ensure you can synchronize un-authenticated with my servers by adding following lines to your configuration file:
server ntp.sentrion.eu server ntp.wolfhugel.euThen restart your
ntpdserver and ensure it synchronizes properly to the newly added nodes. If this fails, you first need to understand why and eventually fix it. Please note that my NTP servers do not respond to queries made with
If not already done, you need to create the directory which will be
containing NTP keys:
/usr/local/etc/ntp. Then you will
need to retrieve my GQ parameter files (using
any similar tool):
pub 4096R/0xF00AF6EAC245D20B 2013-09-24 [expires: 2023-09-22] uid [ultimate] Christophe WolfhugelYou may also download it here. To verify the signature, once you have imported my PGP public key, the commands will be similar to these:
sub 4096R/0x886383DAB10C092F 2013-09-24 [expires: 2023-09-22]
$ gpg --verify ntpkey_gqpar_ntp.sentrion.eu.asc ntpkey_gqpar_ntp.sentrion.eu $ gpg --verify ntpkey_gqpar_ntp.wolfhugel.eu.asc ntpkey_gqpar_ntp.wolfhugel.euAnd it will tell you if the signature is valid or not.
At this stage the content of your
/usr/local/etc/ntp/keys directoryshould be similar
-rw-r--r-- 1 root staff 279 Aug 4 15:56 ntpkey_gqpar_ntp.sentrion.eu -rw-r--r-- 1 root staff 284 Aug 4 15:54 ntpkey_gqpar_ntp.wolfhugel.eu
Next step for you is to generate your own certificate and key files as well as your GQ private key (even if you won't authentify with me). Unlike what I have found in other documentation, I cam to the conlusion that even your client node will need to have its own trusted certificate with the GQ private key:
$ cd /usr/local/etc/ntp $ ntp-keygen -T -G -m 2048
Parameter "-T" is for trusted self signed certificate, "-G" is for the GQ identiy scheme, and finally "-m 2048" indicates a 2048-bit key size. Once this has been generated the directory will contain these new files and links (in addition to the GQ parameter files previously downloaded):
-rw-r--r-- 1 root staff 493 Aug 4 15:58 ntpkey_GQkey_smile.wolfhugel.eu.3616153122 -rw-r--r-- 1 root staff 1214 Aug 4 15:58 ntpkey_RSA-MD5cert_smile.wolfhugel.eu.3616153122 -rw-r--r-- 1 root staff 1904 Aug 4 15:58 ntpkey_RSAhost_smile.wolfhugel.eu.3616153122 lrwxrwxrwx 1 root staff 48 Aug 4 15:58 ntpkey_cert_smile.wolfhugel.eu -> ntpkey_RSA-MD5cert_smile.wolfhugel.eu.3616153122 lrwxrwxrwx 1 root staff 42 Aug 4 15:58 ntpkey_gqkey_smile.wolfhugel.eu -> ntpkey_GQkey_smile.wolfhugel.eu.3616153122 lrwxrwxrwx 1 root staff 44 Aug 4 15:58 ntpkey_host_smile.wolfhugel.eu -> ntpkey_RSAhost_smile.wolfhugel.eu.3616153122(You may wish to change permissions on the private key files, but ensure
ntpdcan still read them).
You do not need to extract your GQ public parameters here, unless you wish to provide authenticated time stamps to your own client machines.
Final steps in your configuration are to modify
ntp.conf in order to configure
the use of authentication. Add following two lines:
keysdir /usr/local/etc/ntp cryptoThis will tell
ntpdto enable cryptography as well as where to search for key files.
If you wish to log the
cryptostats data, which I do strongly recommend, also
add or ensure your configuration file contains something similar to this:
statsdir /var/log/ntpstats/ statistics cryptostats filegen cryptostats file cryptostats type day enable
Do change the configuration to reach my servers by adding the
server ntp.sentrion.eu autokey server ntp.wolfhugel.eu autokey
Lastly, ensure you have the right
restrict configuration lines
in order to enforce NTP authentication when fetching time from my machines
notrust tells NTP to ignore unauthenticated packets):
restrict ntp.wolfhugel.eu noquery notrust restrict ntp.sentrion.eu noquery notrust
As a complete example you will find here the actual
file I use on my client machine:
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help driftfile /var/lib/ntp/ntp.drift keysdir /usr/local/etc/ntp crypto # Enable this if you want statistics to be logged. statsdir /var/log/ntpstats/ statistics loopstats peerstats clockstats cryptostats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable filegen cryptostats file cryptostats type day enable ## My servers server ntp.wolfhugel.eu iburst maxpoll 7 autokey server ntp.sentrion.eu iburst maxpoll 7 autokey # By default, exchange time with everybody, but don't allow configuration. restrict -4 default ignore restrict -6 default ignore # My restrictions. Enforce authentification. restrict ntp.wolfhugel.eu noquery notrust restrict ntp.sentrion.eu noquery notrust # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1
If everything has been configured correctly, your NTP server should start, synchronize time and validate authentication of the remote parties:
$ ntpq ntpq> rv associd=0 status=0615 leap_none, sync_ntp, 1 event, clock_sync, version="ntpd email@example.com Wed Jul 16 16:56:23 UTC 2014 (1)", processor="x86_64", system="Linux/3.14-2-amd64", leap=00, stratum=3, precision=-23, rootdelay=12.727, rootdisp=29.154, refid=126.96.36.199, reftime=d78a2e4f.8ba0179c Mon, Aug 4 2014 17:07:43.545, clock=d78a302e.b72107e2 Mon, Aug 4 2014 17:15:42.715, peer=35375, tc=7, mintc=3, offset=0.072, frequency=44.817, sys_jitter=0.332, clk_jitter=0.231, clk_wander=0.063, tai=35, leapsec=201207010000, expire=201506280000, host="smile.wolfhugel.eu", group="smile.wolfhugel.eu", flags=0x80043, digest="md5", signature="md5WithRSAEncryption", update=201408041545, cert="smile.wolfhugel.eu ntp.wolfhugel.eu 0x5", until=201508041509, cert="smile.wolfhugel.eu ntp.sentrion.eu 0x5", until=201508041508, cert="ntp.sentrion.eu ntp.sentrion.eu 0x5", until=201608031447, cert="ntp.wolfhugel.eu ntp.wolfhugel.eu 0x5", until=201608031453, cert="smile.wolfhugel.eu smile.wolfhugel.eu 0x1", until=201508041458 ntpq> pe remote refid st t when poll reach delay offset jitter ============================================================================== *tea.wolfhugel.e 188.8.131.52 2 u 35 128 377 11.903 0.092 0.736 +ntp.sentrion.eu 184.108.40.206 2 u 99 128 377 11.927 0.612 7.824This shows the synchronization as well as information about the certificates but nothing to prove authentication was successful. You would check associations to get the authentication status:
ntpq> as ind assid status conf reach auth condition last_event cnt =========================================================== 1 35375 f61a yes yes ok sys.peer sys_peer 1 2 35376 f464 yes yes ok candidate reachable 6And you can look at the
authcolumn. The most difficult part if to ensure that the actual GQ public parameters are being used to ensure proper authentication (otherwise you would trust any self signed certificate), this can be found in the "cryptostats" log file:
56873 54395.759 0.0.0.0 ntpkey_RSAhost_smile.wolfhugel.eu.3616153122 mod 2048 56873 54395.842 0.0.0.0 ntpkey_RSA-MD5cert_smile.wolfhugel.eu.3616153122 0x1 len 796 56873 54395.856 0.0.0.0 ntpkey_GQkey_smile.wolfhugel.eu.3616153122 mod 256 56873 54395.856 0.0.0.0 setup 0x80041 host smile.wolfhugel.eu md5WithRSAEncryption 56873 54396.546 2001:41d0:2:c731:1::5 assoc 35375 35375 host ntp.wolfhugel.eu md5WithRSAEncryption 56873 54397.546 2001:41d0:2:c731:1::e1 assoc 35376 35376 host ntp.sentrion.eu md5WithRSAEncryption 56873 54398.547 2001:41d0:2:c731:1::5 cert ntp.wolfhugel.eu ntp.wolfhugel.eu 0x5 md5WithRSAEncryption (8) fs 3616152782 56873 54399.547 2001:41d0:2:c731:1::e1 cert ntp.sentrion.eu ntp.sentrion.eu 0x5 md5WithRSAEncryption (8) fs 3616152474 56873 54400.565 2001:41d0:2:c731:1::5 ntpkey_gqpar_ntp.wolfhugel.eu.3616152782 mod 256 56873 54400.581 2001:41d0:2:c731:1::5 gq ntp.wolfhugel.eu fs 3616152782 56873 54401.535 2001:41d0:2:c731:1::e1 ntpkey_gqpar_ntp.sentrion.eu.3616152474 mod 256 56873 54401.551 2001:41d0:2:c731:1::e1 gq ntp.sentrion.eu fs 3616152474 56873 54402.553 2001:41d0:2:c731:1::5 cook 2994d0d2 ts 3616153602 fs 3616153532 56873 54403.549 2001:41d0:2:c731:1::e1 cook 26557ee5 ts 3616153603 fs 3616153559First lines indicate your own server is properly loading its own key, certificate and GQ private key. Then you see it receiving remote self-signed certificates, and finally it will load the corresponding GQ parameter files for each remote server.
If at this stage the GQ parameter files are not loaded, you may be time synchronized,
but it is likely that authentication is not fully done. One way to test failure is to
change the GQ parameter file locally and observe the behaviour. Here I did change the
ntp.sentrion.eu GQ parameter file, so it does not correspond anymore to the remote
private GQ key (watch out not to alter the ASN.1 syntax of the parameter file, so not
all changed are equal):
56873 59044.240 0.0.0.0 ntpkey_RSAhost_smile.wolfhugel.eu.3616153122 mod 2048 56873 59044.241 0.0.0.0 ntpkey_RSA-MD5cert_smile.wolfhugel.eu.3616153122 0x1 len 796 56873 59044.242 0.0.0.0 ntpkey_GQkey_smile.wolfhugel.eu.3616153122 mod 256 56873 59044.242 0.0.0.0 setup 0x80041 host smile.wolfhugel.eu md5WithRSAEncryption 56873 59045.249 2001:41d0:2:c731:1::5 assoc 23144 23144 host ntp.wolfhugel.eu md5WithRSAEncryption 56873 59046.250 2001:41d0:2:c731:1::e1 assoc 23145 23145 host ntp.sentrion.eu md5WithRSAEncryption 56873 59047.251 2001:41d0:2:c731:1::5 cert ntp.wolfhugel.eu ntp.wolfhugel.eu 0x5 md5WithRSAEncryption (8) fs 3616152782 56873 59048.251 2001:41d0:2:c731:1::e1 cert ntp.sentrion.eu ntp.sentrion.eu 0x5 md5WithRSAEncryption (8) fs 3616152474 56873 59049.238 2001:41d0:2:c731:1::5 ntpkey_gqpar_ntp.wolfhugel.eu.3616152782 mod 256 56873 59049.265 2001:41d0:2:c731:1::5 gq ntp.wolfhugel.eu fs 3616152782 56873 59050.238 2001:41d0:2:c731:1::e1 ntpkey_gqpar_ntp.sentrion.eu.3616152474 mod 256 56873 59050.253 2001:41d0:2:c731:1::e1 82080150 23145 10e bad_or_missing_group key 56873 59051.258 2001:41d0:2:c731:1::5 cook 2994d0d2 ts 3616158251 fs 3616155829 56873 59052.269 2001:41d0:2:c731:1::e1 82080150 23145 10e bad_or_missing_group key 56873 59054.274 2001:41d0:2:c731:1::e1 82080150 23145 10e bad_or_missing_group key 56873 59056.254 2001:41d0:2:c731:1::e1 82080150 23145 10e bad_or_missing_group keyAs you can read from here, the
bad_or_missing_group keyerror message clearly identified an issue, and you could use
ntpqto ensure you do not synchronize to
Thanks to Bertrand Petit for having asked the right question: what is the impact of authentication in the precision of the time synchronization? Unfortunately I do not have the knowledge nor tools to make any analysis or comment on this issue.
This section could also be called summary of all my other failures in trying to use NTP authentication. Please note that I did not test the MV scheme.
I did generate private certificates on both ends, time synchrnized and parties were authenticated. But I did not find a way to indicate each server to verify the actual identify of the remote party. Debug mode does not show the "ntpd" server trying to validate the certificate anywhere.
Same result as with Private Certificates.
Whilst I had no issue configuring the IFF scheme, signature verification on the client always failed. This makes me wonder if I failed the configuration or if the implementation of the algorithms is not correct.
Some documentation seems to tell that using certificates from external authorities was an option, but my experiments always ended up in something like "self-signed" certificate not found.
Following documentations did help me setting up my NTP authentication configuration:
|https://www.hauke-lampe.de/ntp/||Simple step by step guide, unfortunately, I have not been able to authentify with them.|
|http://support.ntp.org/bin/view/Support/ConfiguringAutokey||The reference documentation.|
|https://www.eecis.udel.edu/~mills/ident.html||Autokey Identity Schemes.|
|http://archi.laurent.perso.neuf.fr/Doc_reseauNTP.html||La documentation NTP de Laurent Archambault (avec une section sur autokey).|