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 wurdeErgebnis
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.

Comments

No comments yet. Why don’t you start the discussion?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert