systemd-timesyncd requires incoming ephemeral ports opened

I'm trying to get some sort of time synchronization configured for a Ubuntu server. The server is behind a cloud-provider-stateless firewall. Through some trial and error I found out that in order for ntp to work, I have to open the incoming UDP port 123.

Then I read that using systemd-timesyncd is preferred nowadays, so I tried switching over to that. But that did not work. The service log was full of

systemd-timesyncd[2656121]: Timed out waiting for reply from 91.189.89.199:123 (ntp.ubuntu.com).
systemd-timesyncd[2656121]: Timed out waiting for reply from 91.189.94.4:123 (ntp.ubuntu.com).

Only after I also whitelisted the ephemeral UDP ports 32768–65535 in the firewall did this start to work:

systemd-timesyncd[2656121]: Initial synchronization to time server 91.189.91.157:123 (ntp.ubuntu.com).

Is opening that range of ports really necessary to operate systemd-timesync?


Edit in response to @Jesus-Loves-You's response below. The higher ports should not be necessary, but in my case, for some reason, they clearly are. See the log of the systemd-timesync service (annotated by me with #):

# Before I enabled the 32786+ ports
May 21 11:49:21 myhost systemd-timesyncd[2656121]: Timed out waiting for reply from 91.189.89.198:123 (ntp.ubuntu.com).

# After I enabled the ports
May 21 11:49:06 myhost systemd-timesyncd[2656121]: Initial synchronization to time server 91.189.91.157:123 (ntp.ubuntu.com).

# After I disabled them again. Note that there are no log entries inbetween for almost
# three days. This, imo, pretty much proves that the ports are required.
May 24 09:29:34 myhost systemd-timesyncd[2656121]: Timed out waiting for reply from 91.189.91.157:123 (ntp.ubuntu.com).

Further information about the port:

root@host:/# netstat -ulpvn | grep systemd
udp        0      0 127.0.0.53:53           0.0.0.0:*                           2218041/systemd-res
udp        0      0 0.0.0.0:42212           0.0.0.0:*                           2656121/systemd-tim

Looks like 42212 is the port where the service expects the communication to happen. But after a couple of minutes, when the next polling occurs:

root@host:/# netstat -ulpvn | grep systemd
udp        0      0 127.0.0.53:53           0.0.0.0:*                           2218041/systemd-res
udp        0      0 0.0.0.0:37240           0.0.0.0:*                           2656121/systemd-tim

Now the port changed. And after a couple of minutes it changed again to 51120. So from that I conclude that the service really tries to communicate on random ports each time it attempts the sync.


Solution 1:

It really does use ephemeral ports.

Upon some more research I came across these:

SNTP (RFC 4330) which allows (the more usual) ephemeral source port number

https://iec61850.tissue-db.com/tissue/630

The UDP port number assigned by the IANA to NTP is 123. The SNTP client should use this value in the UDP Destination Port field for client request messages. The Source Port field of these messages can be any nonzero value chosen for identification or multiplexing purposes. The server interchanges these fields for the corresponding reply messages.

This differs from the RFC 2030 specifications, which required both the source and destination ports to be 123.

https://datatracker.ietf.org/doc/html/rfc4330#section-4

So the answer to this whole thing seems to be that systemd-timesyncd is implementing the SNTP protocol, not NTP, and as such uses ephemeral source UDP ports. That is by design. The question now becomes "how to handle ephemeral ports on a stateless firewall" /shrug.