Skip to content

Conversation

squell
Copy link

@squell squell commented Sep 18, 2025

This is intended to eventually close #9481

Some comments:

  • To keep the modification well-separated, the additions to timesyncd are split up two clearly distinguishable parts:

    • The NTS logic itself; these were developed first in the repo https://github.com/squell/nts
    • Modifications to integrate those into the timesyncd sources.
  • Currently, to select an "NTS server" an NTS= line needs to be added to the configuration; because the intent is "secure time", enabling it will ignore all other NTP servers (except for the FallbackNTP). Maybe in the future (if NTS gains traction) it might be wise to configure this differently (e.g. RequireSureTime=yes or something).

  • The function manager_nts_obtain_agreement currently does busy-waiting (which has the advantage of making it perhaps a bit easier to follow the logic). This still should be integrated in the async event loop! (hence the "draft" status of this PR).

  • The current meson build system modifications take some pains to make the selection of TLS and crypto backends flexible. I've learned from @poettering that the intent is to consolidate on OpenSSL; so that part can be simplified. Do note that the minimum required OpenSSL version is v3.5 due to a bug in OpenSSL (and a workaround for that bug not being universally compatible with existing NTS servers). In any case, this PR still allows selecting gnutls for TLS and nettle and gcrypt as alternative crypto backends. Not included in this PR (but available if desired) is a crypto backend that relies on libaes_siv, which would allow using older OpenSSL versions.

  • I'm not 100% sure I didn't miss some config file for integrating the tests and fuzzing code; if there's anything missing, a PR on our forked repo is appreciated!

  • To get in the weeds on NTS protocol details:

    • This patch set supports plenty of AEAD choices. This PR will signal a preference for AES-GCM-SIV crypto (because it is most space-efficient). This will only work with up-to-date Chrony implementations (4.6.1 or later, for annoying reasons). In my practical tests I haven't found any NTS servers running an older Chrony version, and I don't think it's very useful to make this fresh NTS implementation "bug-compatible" with older Chrony versions. By the time NTS lands in timesyncd I would hope that this issue is long forgotten. But if this is seen as problematic, it's very easy to make the default AES-SIV-CMAC.
    • In case there are missing cookies, the code will only ever replenish these "one cookie at a time". I've discovered (and been advised by @davidv1992) that many routers don't like large NTP packets, so this is the more robust option.


int flags;
if((flags = fcntl(sock, F_GETFL)) < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
return close(sock), -2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ever use raw close() in our codebase. use safe_close().

and usually you don't want to use that either, use _cleanup_close_.

finally, please just create the socket with O_NONBLOCK right-away, u.e. use SOCK_NONBLOCK.

continue;
}

int sock = socket(cur->ai_family, type, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all our fds must have O_CLOEXEC set, except if it's clear they should not use it. hence please use SOCK_CLOEXEC

}

int status = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &status, sizeof(status));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please debug log about unexpected failures at least. also, use setsockopt_bool()

hints.ai_socktype = type;

struct addrinfo *info;
if (getaddrinfo(host, NULL, &hints, &info) != 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please never use a blocking call like this in an event-loop based serice such as timesyncd. use sd_resolve_xyz

assert_return(nts_handshake, -ENOMEM);

while ((r = NTS_TLS_handshake(nts_handshake)) > 0 && tls_patience_msec-- > 0)
usleep_safe(USEC_PER_MSEC);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's this?

no blocking calls like this. this is event loop driven...

@poettering
Copy link
Member

i did some initial review now. please have a closer look at the coding style docs.

@poettering poettering added the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Sep 18, 2025
@squell
Copy link
Author

squell commented Sep 19, 2025

Thanks for the quick initial review!

Note that the tcp_connect will eventually be completely removed as it's only part of the blocking handshake, which as mentioned needs to be rewritten to fit inside the event system.

hmm, what's the license of the code you are copying in in the first commit? we really want spdx headers.

They're LGPL2.1+ licensed (since they're specifically targetted for timesyncd).

@squell
Copy link
Author

squell commented Sep 19, 2025

For my own reference, I'm tracking more general issues that still need attention on the forked repo: https://github.com/pendulum-project/nts-timesyncd/issues

option('openssl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
description : 'openssl support')
option('cryptolib', type : 'combo', choices : ['auto', 'openssl', 'gcrypt'], deprecated : true)
option('timesync-nts', type : 'combo', choices : ['auto', 'enabled', 'disabled'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be of type "feature" rather than a manual combo


if conf.get('ENABLE_TIMESYNC_NTS') == 1

executables += [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation and whitespace above

org.freedesktop.timesync1.Manager.SystemNTPServers
org.freedesktop.timesync1.Manager.RuntimeNTPServers
org.freedesktop.timesync1.Manager.FallbackNTPServers
org.freedesktop.timesync1.Manager.NTSKeyExchangeServers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't, add to the version history instead

<filename>systemd-timesyncd.service</filename>.</para>

<para>The <filename>systemd-timesyncd.service</filename> service supports the Network Time Security (NTS)
mechanism for NTP. These allow for authentication of the time source and protect against spoofing attacks.</para>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the plural here refer to?

Suggested change
mechanism for NTP. These allow for authentication of the time source and protect against spoofing attacks.</para>
mechanism for NTP. This allows for authentication of the time source and protect against spoofing attacks.</para>

<command>systemd-timesyncd</command> will contact all configured servers in turn, until one responds.
When the empty string is assigned, the list of NTS servers is reset, and
all prior assignments will have no effect. This setting defaults to an empty list.
If NTS severs have been configured, any other configured NTP servers (including per-interface NTP servers acquired
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If NTS severs have been configured, any other configured NTP servers (including per-interface NTP servers acquired
If NTS servers have been configured, any other configured NTP servers (including per-interface NTP servers acquired

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Network Time Security (NTS) support
6 participants