TOTP-Login schlägt fehl? Serverzeit ist das Problem
Der Google Authenticator zeigte den richtigen Code an – aber der Login schlug trotzdem fehl. Immer wieder. Kein Hinweis auf den eigentlichen Fehler, einfach „ungültiger Code“.
Der Grund: Mein vServer lief mit einer Zeitabweichung von knapp 5 Minuten. TOTP-Codes (das Verfahren hinter Google Authenticator) sind zeitbasiert und nur für ein Fenster von etwa 30 Sekunden gültig. Bei 5 Minuten Abweichung ist jeder Code schon längst abgelaufen, bevor er den Server erreicht.
chronyc makestep half nicht, die Uhr blieb falsch. Nach etwas Debugging stellte sich heraus: Das Problem lag gar nicht bei chrony selbst, sondern bei der Firewall des Providers. Hier ist der Weg zur Lösung.
Schritt 1: Diagnose – was sagt chrony überhaupt?
Zuerst prüfen, ob chrony überhaupt etwas synchronisiert:
chronyc tracking
chronyc sources -v
timedatectl status
Die Ausgabe von chronyc sources ist dabei am aufschlussreichsten. Entscheidend ist die Spalte Reach – sie zeigt, ob chrony eine NTP-Quelle tatsächlich erreichen konnte. Bei mir sah es so aus:
MS Name/IP address Stratum Poll Reach LastRx Last sample
================================================================
^? time.cloudflare.com 0 7 0 - +0ns
^? 185.252.140.125 0 7 0 - +0ns
Reach: 0 bei allen Quellen bedeutet: chrony hat noch nie ein einziges NTP-Paket zurückbekommen. Das ist kein chrony-Problem – das ist ein Netzwerk-Problem.
timedatectl status zeigte außerdem:
System clock synchronized: no
RTC time: 15:11:50 ← RTC läuft 5 Minuten vor
Local time: 16:06:40
Schritt 2: Liegt es an der lokalen Firewall?
UFW prüfen:
ufw status verbose | head -5
Ausgabe:
Default: deny (incoming), allow (outgoing), deny (routed)
Outgoing ist allow – UFW blockiert also nichts. Die Ursache muss woanders liegen.
Schritt 3: Kann der Server NTP-Server überhaupt erreichen?
Jetzt den eigentlichen UDP-Test. nc ist bei UDP nicht zuverlässig – besser das richtige Werkzeug nutzen:
apt install ntpsec-ntpdate
ntpdate -qd time.cloudflare.com
Solange UDP 123 geblockt ist, kommt nur das hier:
ntpdig: querying 162.159.200.1 (time.cloudflare.com)
ntpdig: no eligible servers
Das ist das entscheidende Ergebnis: NTP-Pakete kommen nicht durch – auf keinem Server, weder IPv4 noch IPv6.
Schritt 4: Ursache – Provider blockiert UDP 123
Das Problem ist eine ausgehende Firewall-Regel auf vServer-Ebene. Viele Provider haben in ihrer Cloud-Konsole eine eigene Firewall, die unabhängig von UFW greift. UDP Port 123 (NTP) war dort nicht als erlaubte ausgehende Verbindung eingetragen.
Lösung: In der Provider-Konsole eine Outbound-Regel für UDP Port 123 anlegen.
Danach den Test wiederholen:
ntpdate -qd time.cloudflare.com
Erfolgreiche Ausgabe sieht dann so aus:
2026-03-21 16:24:40.130972 (+0100) +310.751100 +/- 0.001970 time.cloudflare.com
Der Offset von +310 Sekunden (~5 Minuten) bestätigt: Verbindung klappt, die Abweichung wurde erkannt.
Schritt 5: chrony neu starten und Zeit synchronisieren
systemctl restart chronyd
sleep 20
chronyc sources
chronyc tracking
Jetzt sollte bei einer Quelle ein * erscheinen (= aktiv genutzt) und chronyc tracking eine sinkende Abweichung zeigen.
Zusammenfassung
| Was geprüft wurde | Ergebnis |
|---|---|
| chrony läuft? | Ja, seit Wochen – trotzdem keine Sync |
| UFW blockiert UDP 123? | Nein, Outgoing ist allow |
| NTP-Pakete kommen durch? | Nein – ntpdate -qd zeigt no eligible servers |
| Provider-Firewall? | Ja – UDP 123 outbound fehlte |
Wenn chronyc sources nur ? und Reach: 0 zeigt und UFW unauffällig ist, lohnt sich immer ein Blick in die Firewall der Provider-Konsole. NTP braucht UDP Port 123 outbound – das wird leicht vergessen, weil es kein üblicher Web-Port ist.