== After NTP Comes NTS. After NTS comes sdwdate. Well for this one I will be talking a bit about NTP and NTS. Unlike the DNS post there isn’t much going on here. NTP is plain-text, NTS uses TLS so if our requests are tampered with, we can know. There is the "`oooh, you cant see what I’m sending now`" but in this case its NTP so the content being secret is not necessarily more important than making sure the content has not been modified(guarantee of integrity). So far so good. But before we go any further, lets talk about what we are trying to achieve here, in other works, what requirements are we trying to satisfy here: * REQ-001: The NTP(NTS) requests shall be anonymous * REQ-002: It shall be evient when an NTP(NTS) requests has been tampered with * REQ-003: It should not be known which time servers are being used upstream by the client If you are wondering why any of this even matters you can have a look https://www.whonix.org/wiki/Time_Attacks[here]. Now talk about the problem. The protocol is fine. We are sending TCP with TLS here. That’s brilliant. We get all this: .... * Identity: Through the use of a X.509 public key infrastructure, implementations can cryptographically establish the identity of the parties they are communicating with. * Authentication: Implementations can cryptographically verify that any time synchronization packets are authentic, i.e., that they were produced by an identified party and have not been modified in transit. * Confidentiality: Although basic time synchronization data is considered nonconfidential and sent in the clear, NTS includes support for encrypting NTP extension fields. * Replay prevention: Client implementations can detect when a received time synchronization packet is a replay of a previous packet. * Request-response consistency: Client implementations can verify that a time synchronization packet received from a server was sent in response to a particular request from the client. * Unlinkability: For mobile clients, NTS will not leak any information additional to NTP which would permit a passive adversary to determine that two packets sent over different networks came from the same client. * Non-amplification: Implementations (especially server implementations) can avoid acting as distributed denial-of-service (DDoS) amplifiers by never responding to a request with a packet larger than the request packet. * Scalability: Server implementations can serve large numbers of clients without having to retain any client-specific state. * Performance: NTS must not significantly degrade the quality of the time transfer. The encryption and authentication used when actually transferring time should be lightweight. .... Excerpt from https://www.rfc-editor.org/rfc/rfc8915[RFC 8915] If we find a client that lets us use a SOCKS5 proxy, then we can send our NTS requests over Tor and then call it a day. REQ-002 and REQ-003 are being satisfied by using TLS. The missing piece is REQ-001, anonymizing the requests. This is not something for the protocol to handle so then we have to look for a client that support a SOCKS5 proxy. Unfortunately https://gitlab.com/chrony/chrony[chrony] and https://github.com/pendulum-project/ntpd-rs[ntpd-rs] do not support SOCKS5 proxies. * for ntpd-rs look https://github.com/pendulum-project/ntpd-rs/discussions/1365[here] Which means our setup is not complete. === Implementation We will be using ntpd-rs as the client. We will also setup one NTS server using https://gitlab.com/NTPsec/ntpsec[ntpsec]. [source,toml] ---- [observability] log-level = "info" observation-path = "/var/run/ntpd-rs/observe" [[source]] mode = "nts" address = "virginia.time.system76.com" [[source]] mode = "nts" address = "mmo1.nts.netnod.se" [[source]] mode = "nts" address = "ntppool1.time.nl" [[source]] mode = "nts" address = "ntp1.glypnod.com" [[source]] mode = "nts" address = "ntp3.fau.de" [synchronization] single-step-panic-threshold = 1800 startup-step-panic-threshold = { forward="inf", backward = 1800 } minimum-agreeing-sources = 3 accumulated-step-panic-threshold = 1800 [[server]] listen = "127.0.0.1:123" [[server]] listen = "172.17.0.1:123" [[server]] listen = "192.168.121.1:123" [[server]] listen = "10.167.131.1:123" [[server]] listen = "[::1]:123" ---- [source,conf] ---- nts enable nts key /etc/letsencrypt/live/nts.dehein.org/privkey.pem nts cert /etc/letsencrypt/live/nts.dehein.org/fullchain.pem mintls TLS1.3 nts cookie /var/lib/ntp/nts-keys nts-listen-on 4460 server 0.0.0.0 prefer server ntpmon.dcs1.biz nts # Singapore server ntp1.glypnod.com nts # San Francisco server ntp2.glypnod.com nts # London tos maxclock 5 restrict default kod limited nomodify noquery restrict -6 default kod limited nomodify noquery driftfile /var/lib/ntp/ntp.drift statsdir /var/log/ntpstats/ ---- [source,yaml] ---- version: "3.9" services: filebrowser: image: ntpsec build: context: . deploy: resources: limits: memory: 128M logging: driver: "json-file" options: max-size: "50m" networks: - ntsnet ports: - "4460:4460/tcp" restart: unless-stopped entrypoint: ["ntpd"] command: ["-n", "-I", "0.0.0.0", "-d", "5"] volumes: - ./ntp.conf:/etc/ntp.conf:ro - /etc/letsencrypt/live/nts.dehein.org/fullchain.pem:/etc/letsencrypt/live/nts.dehein.org/fullchain.pem:ro - /etc/letsencrypt/live/nts.dehein.org/privkey.pem:/etc/letsencrypt/live/nts.dehein.org/privkey.pem:ro - vault:/var/lib/ntp cap_drop: - ALL cap_add: - SYS_NICE - SYS_RESOURCE - SYS_TIME networks: ntsnet: volumes: vault: ---- === What comes after NTS Above we looked at NTP and NTS. We failed to find a client that supports SOCKS5 but that’s a trivial matter. What is not trivial, however, is how NTS and NTP work, and by that I mean you will still have to ask a server to tell you the time. Doing so over Tor or other anonymizing networks should be fine but we can choose to try out another method of doing things. Enter `+sdwdate+` ==== sdwdate It still has the same flaw as NTP/NTS as in we still have to trust a server not to lie https://www.kicksecure.com/wiki/Sdwdate#sdwdate_Source_Pools[please look here]. Personally, It is a bit of a disappointment that the protocol that’s supposed to be oh-so-much-shinier and newer than NTP has the same flawed mechanism as NTP. Now granted having hardware that tells you the time so that you can share that with everyone else is not something trivial or readily-available but this only makes sdwdate desirable in the absence of an NTS client that support SOCKS5 proxy. Once that is done, the larger user pool of NTS/NTP will offer more protection against the smaller userbase of sdwdate. sdwdate gives a table of comparison between itself and NTP. Let’s take at look at that: Let’s take a look at `+sdwdate+`. It is a roller-coaster. And I do mean that. So don’t make up your mind until the very end. There is a comparison between NTP and sdwdate made https://www.kicksecure.com/wiki/Sdwdate#Sdwdate_vs_NTP[here] by kicksecure themselves. [cols=",,",options="header",] |=== |category |sdwdate |ntp |written in memory-safe language |Yes |No |distributed trust |Yes |No |secure connection by default |Yes |No |gradual clock adjustments |Yes |Yes |daemon |Yes |Yes |functional over tor |Yes |No |tor not required |No |Yes |client, time fetcher |Yes |Yes |Server, time provider |No |Yes |AppArmor profile |Yes |Yes |systemd security hardening,seccomp |Yes |? |drop-in config folder |Yes |No |proxy support |Yes |No |possible to secure by default on GNU/Linux distribution level |Yes |No |secure |Yes |No |optional GUI |Yes |No |=== * memory-safety: I mean its good and all that sdwdate uses a memory-safe language(python) but NTP is a protocol. Not sure how NTP is bound to a single programming language. The one client we mentioned before uses rust which guarantees memory safety. * secure connection by default: NTS uses TLS v1.3 . Not sure why sdwdate is being compared against NTP and not NTS. * functional over Tor: again, NTS uses TCP which can pass through a SOCKS5 proxy as is implemented by the current incarnation of Tor. Also, not sure, but are we comparing against the NTP protocol or a specific implementation? * Tor not required: what if I want to use https://github.com/PurpleI2P/i2pd[i2p] or https://github.com/yggdrasil-network/yggdrasil-go[yggdrasil] to sync time over? Why does it have to be Tor? * apparmor profile: not sure why this is even included. You can write one for NTP implementations. * systemd security hardening, seccomp: same as above. You can do it for NTP/NTS implementations as well. * drop-in config folder: what’s a folder? Is that supposed to be a directory? Second, what does that even mean? And third, who is writing these? The only kind of people who make this sort of mistake are people who use MS Windows more than Linux. This is official kicksecure documentation. You have Windows users writing these for the ultra secure and hardened "`Linux`", I’ll say it again, "`Linux`", distro? * proxy support: again, NTS uses TCP so it supports SOCKS5 proxies as well but for whatever reason we are comparing against NTP(though whether we are comparing against the protocol or an implementation is something left to be decided by the next generation of humans) * possible to secure by default on GNU/Linux distribution level: whats the GNU/Linux distribution level? What does this even mean? You can secure it on the OS level? I mean it’s software so I would hope that it would be possible to secure it on the software level. * secure: what are the criteria? Secure against what? And again, why are we comparing to NTP and not NTS? * optional GUI: again not sure why we keep zig-zagging between comparing implementations and the protocols. In conclusion, why is that table even there? What purpose does it even serve? If we were going to base our judgement on the documentation provided on kicksecure’s website, I am sorry to say that `+sdwdate+` does a very poor job but fortunately that’s not all there is to it. Now let’s go take a look at the github README for the project: [source,txt] ---- At randomized intervals, sdwdate connects to a variety of webservers and extracts the time stamps from http headers (RFC 2616)) ---- This is our first spark of brilliance. The second spark is when we consider the practical meaning of only being able to use Tor v3 addresses. Like a wise man once said: [source,txt] ---- amateurs practice something until they can get it right. pros practice something until they can't get it wrong. ---- The result of using only Tor v3 addresses is that you cannot leak your real IP address no matter what happens. You either have a working Tor proxy in which case the IP address will be that of the exit node or none at all. Now we know we definitely are dealing with a very promising solution. '`sdwdate`' extracts the time stamp in the http header so we are not asking a known NTP server about the time, we are just doing a normal http request. === DISCLAIMER Although unrelated, it is worth noting that the kicksecure docs are pretty good even if you are not planning on using kicksecure. === Links * https://www.rfc-editor.org/rfc/rfc8915[RFC 8915] * https://github.com/jauderho/nts-servers[Here] you can find a list of publicly available servers that support NTS * https://github.com/Kicksecure/sdwdate[sdwdate’s github page] * https://www.kicksecure.com/wiki/Sdwdate[sdwdate doc] * https://www.rfc-editor.org/rfc/rfc2616[RFC 2616] timestamp:1713478033 version:1.1.0 https://blog.terminaldweller.com/rss/feed https://raw.githubusercontent.com/terminaldweller/blog/main/mds/NTP.md