NTP (Network Time Protocol) mit chrony und aktivierter Firewall nutzen

  • Motivation: Aufgrund eines Problems mit 2FA (2 Faktor-Authentifizierung) bei einem meiner Services (https://dockhand.pro/) habe ich festgestellt, dass die Uhr auf meinem RS so weit abweicht (ca 60s), dass die zeitgesteuerte 2FA nur "manchmal" funktioniert und ansonsten den sechsstelligen Code nicht akzeptiert (wenn die 30 Sekundenfenster soweit auseinanderliegen, dass auf meinem Authenticator (der die richtige Zeit hat) kein gültiger Code für die falsche Zeit auf dem RS angezeigt wird.

    Natürlich will man NTP umsetzen. Dafür gibt es mehrere Optionen und man muss v.a. auch die NC Firewall konfigurieren (siehe unten). Dies betrifft sicherlich jegliche NTP Lösung, nicht nur die vorgeschlagene.

    Daher habe ich mich mit https://claude.ai/ Code hingesetzt und eine Lösung gesucht. Es hat mir https://chrony-project.org/ als robuste und genauere Lösung vorgeschlagen, das vorhandene systemd-timesyncd wird bei Umsetzung deaktiviert.

    Vielleicht wollt Ihr ja auch eine genaue(re) Uhrzeit auf Euerem Server haben ;) . Dann wäre hier das "Kochbuch", das mir Claude so schön übersichtlich geschrieben hat und das auch Claude Code vorgesetzt werden kann, um die Änderungen umsetzen zu lassen. Natürlich könnt Ihr die Schritte aber auch manuell umsetzen. Im Anhang das Markdown File für CC oder zur Ablage zum Download.

    Ich habe feste Quell IP Adressen konfiguriert, da man in der Firewall (Screenshots unten) den QUELLport 123 aufmachen muss (ein Zielport geht nicht, da der Zielport zufällig ist). Und das will man natürlich nur für wenige, vertrauenswürdige IPs erlauben. Daher sind hier sind die PTB IPs und das Google NTP Netzwerk fest konfiguriert und weiter unten auch in der Firewall frei gegeben. Die typischen *.pool.ntp.org DNS Namen funktionieren hier nicht, da sich die IP Adressen dahinter ständig ändern.

    Und hier die Firewallkonfiguration:

    Beschreibung Typ Aktion Protokoll Source(s) (IPs / Netzwerke) Source Port(s) Destination(s) (IPs / Netzwerke) Destination Port(s)
    1 123 UDP eingehend EINGEHEND ACCEPT UDP 192.53.103.108, 192.53.103.104, 216.239.35.0/24, 192.53.103.103 123 * *

    nc-chrony-fw.png

    nc-chrony-fw-regel.png

  • Schöne Beschreibung, aber ein paar Anmerkungen seien gestattet:

    IPv6 wird nicht berücksichtigt. Die verwendeten Zeitserver haben alle auch IPv6-Adressen und die müsste man konsequenterweise ebenfalls in der Firewall zulassen.

    Und das ist auch gleich ein weiterer Kritikpunkt: In der chrony-Konfiguration werden die DNS-Namen der Zeitserver verwendet, in der Firewall (notgedrungen) deren IP-Adressen. Bei einer eventuellen Änderung der im DNS hinterlegten IP-Adressen würden die Firewall-Regeln nicht mehr passen. Eine richtige Lösung zu diesem Dilemma kann ich leider auch nicht anbieten, ich habe daher keine IP-Adressen für NTP in meiner Firewall hinterlegt.

    Die Einstellung für makestep würde ich nicht so wählen, wie vorgeschlagen. Im Betrieb will man in der Regel keine Zeitsprünge zulassen - man denke an eine Datenbank, in der die zeitliche Abfolge von Ereignissen dokumentiert wird - sondern das schleichende Angleichen der Zeit durch Bremsen oder Beschleunigen der Systemuhr.

    P.S.: Kann es sein, dass systemd-timesyncd wegen fehlender Firewall-Regeln nicht funktioniert hatte?

  • Ich hab mir meinen eigenen Pool definiert "1.pool.ntp.domain.tld", das macht alle FW-Regeln und Configs eher trivial und ich hab sogar das Stratum im Griff.

    Ansonsten hab ich da ein gutes altes Skript, das löst alle Namen für die ursprünglichen NTP-Server im Pool auf, schreibt alles sortiert in eine Datei und checkt via git, ob sich was geändert hat. Wenn ja, kann ich die entsprechenden Korrekturen anstossen. Ist bei der Änderungshäufigkeit für NTP-Server echt vertretbar.

    | VPS: 28 | vCPU: 75 | Memory: 104 GB | Disk: 4012 GB |

  • welchen Vorteil bringt das, gegenüber einzelner pools?

    Kontrolle.

    Ich hab den Pool zu 100% im im Griff. Kenne genau die (handverlesenen) 5 oder 6 Server darinnen, kann die IPs auf v4 und v6 tracken und kenne das Stratum.

    Ich könnte natürlich auch in jeder Config die Servernamen eintragen, aber so hab ich Regelwerk und Server immer alles konsistent und kann Änderungen zentral monitoren und nachverfolgen.

    | VPS: 28 | vCPU: 75 | Memory: 104 GB | Disk: 4012 GB |

  • Aber dazu musst Du dann einen eigenen DNS-Server betreiben?

    Ne, musst du nicht. Ich hab meine Domains zwar nicht bei Netcup, aber ich kann in den Labels in der Regel einfach 1.pool.ntp eintragen, und mehrfache A und AAAA records sollten eingentlich überall gehen. Du musst hier keine Subzonen-Delegation oder sowas machen.

    | VPS: 28 | vCPU: 75 | Memory: 104 GB | Disk: 4012 GB |

  • Ich hab mir meinen eigenen Pool definiert "1.pool.ntp.domain.tld", das macht alle FW-Regeln und Configs eher trivial

    Die Idee finde ich elegant, allerdings hätte ich Bedenken, daß die Sudomain von DNS-Scannern gefunden wird und dann in irgendwelchen Listen oder Datenbanken landet. Ob da ein kryptischer Name helfen würde?

  • Die Idee finde ich elegant, allerdings hätte ich Bedenken, daß die Sudomain von DNS-Scannern gefunden wird und dann in irgendwelchen Listen oder Datenbanken landet. Ob da ein kryptischer Name helfen würde?

    Glaube nicht, denn da gibts ja noch passive Scanner, die auch schauen, was so vorbei kommt.

    Wenn du da paranoid bist musst du mit split horizon dns arbeiten und nur intern den Namen auflösen.

    | VPS: 28 | vCPU: 75 | Memory: 104 GB | Disk: 4012 GB |

  • Ja, ein interner Resolver wäre mir da lieber, wobei ich mit dem Gedanken spiele, die IP-Adressen direkt in die config einzutragen und dann bei Bedarf z. B. per ansible überall zu aktualisieren. Dann wäre DNS als potentielle Fehlerquelle auch raus.

  • Vielen Dank für die zahlreichen Rückmeldungen, war mir nicht klar, welch ausgefuchste NTP Setups es gibt.

    Laut chrony-Manual kann man den Port für ausgehende Verbindungen konfigurieren. Siehe acquisitionport auf https://chrony-project.org/doc/latest/chrony.conf.html

    Ah, nice. Könnte man evtl noch zusätzlich machen, dann wäre das ziemlich zugenagelt.

    IPv6 wird nicht berücksichtigt. Die verwendeten Zeitserver haben alle auch IPv6-Adressen und die müsste man konsequenterweise ebenfalls in der Firewall zulassen.

    Das stimmt. Wobei eine IP Version ja imho reicht um den Zweck zu erfüllen. Wenns über IPv4 geht, braucht es ja imho nicht noch IPv6. Ich nutze das ja nur als Client, nicht als Server, der ggfalls über IPv6 ansprechbar sein sollte.

    In der chrony-Konfiguration werden die DNS-Namen der Zeitserver verwendet, in der Firewall (notgedrungen) deren IP-Adressen. Bei einer eventuellen Änderung der im DNS hinterlegten IP-Adressen würden die Firewall-Regeln nicht mehr passen. Eine richtige Lösung zu diesem Dilemma kann ich leider auch nicht anbieten, ich habe daher keine IP-Adressen für NTP in meiner Firewall hinterlegt.

    Ja, das stimmt, einige Lösungen wurden ja schon diskutiert. Ich gehe einfach mal davon aus, dass die PTB ihre IP Adressen eben nicht dauernd ändern werden. Ungeeignet ist, wie gesagt die Nutzung der Pool DNS Namen, da es da definitiv keine Kontinuität gibt. Keine IP Adressen zu hinterlegen würde bedeuten, dass jeder Rechner im Internet über Port 123 mit meinem Server kommunizieren könnte. Hm, wollte ich jetzt nicht.

    Die Einstellung für makestep würde ich nicht so wählen, wie vorgeschlagen. Im Betrieb will man in der Regel keine Zeitsprünge zulassen - man denke an eine Datenbank, in der die zeitliche Abfolge von Ereignissen dokumentiert wird - sondern das schleichende Angleichen der Zeit durch Bremsen oder Beschleunigen der Systemuhr.

    Das hat Claude gemacht, um eine zügige Zeiteinstellung herbeizuführen. Kann man gerne weglassen. In meinem Fall würde ich davon ausgehen, dass ich keine Probleme mit dem Sprung hatte (andersrum hatte ich Probleme wegen der falschen Zeit). Aber das hängt natürlich davon ab was drauf läuft. Die vorsichtige Variante ist definitiv Dein Vorschlag.

    P.S.: Kann es sein, dass systemd-timesyncd wegen fehlender Firewall-Regeln nicht funktioniert hatte?

    Jep. ;)

    Bei der Analyse und Behebung hat mir Claude die beiden Optionen timesyncd und chrony vorgeschlagen. Chrony scheint das "bessere" zu sein, daher hab ich das gewählt. Siehe auch https://www.baeldung.com/linux/chrony-vs-systemd-timesyncd . Chrony synct anscheinend mit mehreren Servern, timesyncd nur mit einem.

    RS 2000 G12 Pro BW25 (8C EPYC 9645, 16GB, 1TB) | RS 500 G12 BW25 (2C EPYC 9645, 4GB, 128GB) | RS Cyber Quack (1C,2GB,40GB)

  • Keine IP Adressen zu hinterlegen würde bedeuten, dass jeder Rechner im Internet über Port 123 mit meinem Server kommunizieren könnte.

    Dazu müsste er aber erst einmal Pakete mit Source Port 123 verschicken und könnte damit potentiell andere Dienste, die per UDP erreichbar sind, auf deinem System stören. Im Vergleich zum Betrieb ohne die SCP-Firewall wird die Angriffsfläche auch ohne Hinterlegung der IP-Adressen schon deutlich reduziert. Aber klar, die Adressen der Zeitserver werden sich in der Praxis eher selten ändern und daher kann man sie schon in der Firewall eintragen.

    Wenns über IPv4 geht, braucht es ja imho nicht noch IPv6

    Wenn auf deinem Server kein IPv6 läuft, ist das okay. Ansonsten wird aber IPv6 in der Regel gegenüber IPv4 bevorzugt und somit laufen die Anfragen bei NTP-Servern per Name ggf. auf Timeouts, weil die Antworten per IPv6 nicht durch die Firewall kommen. Alternativ könnte man - wie zuvor schon angesprochen wurde - die IPv4-Adressen explizit in der chrony-Konfiguration eintragen.