1 Punkte von GN⁺ 21 일 전 | 1 Kommentare | Auf WhatsApp teilen
  • Der TCP-Zeitstempelzähler (tcp_now) von macOS stoppt nach etwa 49,7 Tagen Laufzeit durch einen 32-Bit-Overflow, wodurch die interne TCP-Uhr stehen bleibt
  • Dadurch laufen Verbindungen im Zustand TIME_WAIT nicht ab und sammeln sich an, sodass temporäre Ports nicht freigegeben werden
  • Mit der Zeit führen erschöpfte Ephemeral Ports dazu, dass alle neuen TCP-Verbindungen fehlschlagen und nur bestehende Verbindungen erhalten bleiben
  • ICMP (ping) funktioniert weiterhin normal, aber die gesamte TCP-Funktionalität wird lahmgelegt, und eine Wiederherstellung ist nur per Neustart möglich
  • In dauerhaft laufenden macOS-Servern, Build-Maschinen und CI-Umgebungen tritt dieses Problem im Zyklus von 49 Tagen und 17 Stunden auf; bis zu einer Kernel-Korrektur sind regelmäßige Neustarts erforderlich

Hintergrund: Grundkonzepte von TCP

  • TCP-Verbindungen verschwinden beim Beenden nicht sofort, sondern gehen in den Zustand TIME_WAIT über; das ist ein Schritt zur Verarbeitung verzögerter Pakete und für ein zuverlässiges Verbindungsende
    • So wird verhindert, dass alte Pakete fälschlich als Teil einer neuen Verbindung interpretiert werden, und es ermöglicht Neuübertragungen bei verlorenem letztem ACK
  • Die Dauer von TIME_WAIT ist als 2 × MSL (Maximum Segment Lifetime) definiert und ist unter macOS auf etwa 30 Sekunden gesetzt
  • MSL ist die maximale Zeit, die ein TCP-Segment im Netzwerk überleben kann; in RFC 793 wurde sie mit 2 Minuten definiert, in modernen Systemen ist sie jedoch deutlich kürzer eingestellt
  • Ein 32-Bit-Unsigned-Integer-Overflow ist das Phänomen, bei dem ein Wert nach Überschreiten des Maximums (4.294.967.295) wieder auf 0 zurückspringt; der TCP-Zeitstempel tcp_now von macOS ist ein 32-Bit-Zähler in Millisekunden seit dem Boot, bei dem der Overflow nach 49 Tagen 17 Stunden 2 Minuten 47,296 Sekunden auftritt

Entdeckung: Ausfall neuer TCP-Verbindungen nach 49,7 Tagen

  • Die für das iMessage-Monitoring eingesetzten Mac-Server von Photon laufen 24/7; am 30. März 2026 trat exakt 49,7 Tage nach dem Boot das Phänomen auf, dass alle neuen TCP-Verbindungen fehlschlugen
    • Bestehende Verbindungen und ICMP (ping) funktionierten weiter, aber neue TCP-Sockets konnten nicht mehr erzeugt werden
  • Ursache ist ein Overflow des TCP-Zeitstempelzählers (tcp_now) im XNU-Kernel; die Logik zur Prüfung monoton steigender Werte blockiert nach dem Wraparound weitere Updates, sodass die interne TCP-Uhr stehen bleibt
  • TIME_WAIT-Verbindungen laufen nicht mehr ab, Ephemeral Ports werden nicht freigegeben und sammeln sich an; eine Wiederherstellung ist letztlich nur per Neustart möglich
  • Nach dem Neustart wiederholte sich dasselbe Verhalten im Abstand von jeweils 49,7 Tagen

Versuchsaufbau: Vergleich des TCP-Verhaltens vor und nach dem Overflow

  • Hypothese: Wenn die Garbage Collection von TIME_WAIT nach dem Overflow stoppt, muss sich das Muster kurzlebiger TCP-Verbindungen vor und nach dem Overflow unterscheiden
    • Vor dem Overflow: TIME_WAIT läuft nach 30 Sekunden regulär ab
    • Nach dem Overflow: TIME_WAIT bleibt unbegrenzt bestehen
  • Es wurde ein dreistufiges Testskript ausgeführt
    1. Monitoring-Phase: Von 35 Minuten bis 5 Minuten vor dem Overflow wurde die Anzahl der TIME_WAIT-Verbindungen alle 10 Sekunden protokolliert
    2. Burst-Phase: In den 10 Minuten rund um den Overflow wurden alle 2 Sekunden etwa 15 kurze TCP-Verbindungen erzeugt
    3. Beobachtungsphase: Nach dem Stoppen der Verbindungserzeugung wurden die Veränderungen bei TIME_WAIT weiter überwacht

Ergebnis: TIME_WAIT-Stau nach dem Overflow

  • Vor dem Overflow pendelte die Anzahl der TIME_WAIT-Verbindungen stabil zwischen 0 und 200; ein normales Aufräumverhalten war klar erkennbar
  • Unmittelbar nach dem Overflow nahm die Zahl der TIME_WAIT-Verbindungen kontinuierlich zu und lief nicht mehr ab
  • Bei Machine B wurden 2.828 TIME_WAIT-Verbindungen auch nach 84 Sekunden nicht einmal teilweise bereinigt und sammelten sich danach weiter an
  • Auch bei Machine A zeigte die manuelle Prüfung, dass die Zahl der TIME_WAIT-Verbindungen monoton anstieg und sich der Zustand nicht selbst erholte

Grundursache: 32-Bit-Overflow von tcp_now im XNU-Kernel

  • tcp_now ist ein in bsd/netinet/tcp_var.h definierter 32-Bit-Zähler in Millisekunden, der die seit dem Boot vergangene Zeit verfolgt
  • In der Funktion calculate_tcp_clock() überschreitet die Berechnung (uint32_t)now.tv_sec * 1000 nach 49,7 Tagen den Maximalwert, wodurch ein Wraparound auftritt
  • Aufgrund der Bedingung if (tmp < current_tcp_now) ist beim Overflow der bestehende Wert größer als der neue; dadurch wird das Update blockiert und tcp_now bleibt dauerhaft stehen
  • Die Prüfung des TIME_WAIT-Ablaufs basiert auf tcp_now; bleibt diese Uhr stehen, ist die Ablaufbedingung immer falsch, sodass keine Bereinigung mehr möglich ist

Ketteneffekt: Ausweitung zum vollständigen Stillstand von TCP

  • Nach wenigen Minuten: TIME_WAIT wird nicht mehr bereinigt, bei Workloads mit vielen kurzlebigen Verbindungen treten schrittweise Probleme auf
  • Nach einigen Stunden: Tausende TIME_WAIT-Verbindungen sammeln sich an, Ephemeral Ports erschöpfen sich
  • Nach Port-Erschöpfung: Neue TCP-Verbindungen scheitern im Zustand SYN_SENT, nur bestehende Verbindungen bleiben erhalten
  • Stark erhöhte CPU-Last: Der Kernel scannt die TIME_WAIT-Queue fortlaufend weiter, wodurch die Last steigt
  • Ergebnis ist ein vollständiger TCP-Ausfall, während nur ICMP weiterhin normal funktioniert
  • Die einzige Wiederherstellungsmethode ist ein Neustart; danach beginnt der 49,7-Tage-Zähler erneut

Weitere Belege und verwandte Fälle

  • RFC 7323 weist darauf hin, dass bei 32-Bit-Zeitstempeln mit 1-ms-Auflösung das Vorzeichenbit etwa alle 24,8 Tage umklappt
    • Im Fall von macOS geht es jedoch um einen vollständigen 32-Bit-Overflow nach 49,7 Tagen und damit um einen lokalen Kernel-Fehler, getrennt von den in der RFC behandelten Problemen mit entfernten Zeitstempeln
  • In Apple-Communities und Open-Source-Projekten wurden viele Berichte mit demselben Symptom gefunden
    • Keine TCP-Verbindungen möglich, ping funktioniert, nur ein Neustart hilft, Auftreten nach mehreren Wochen Laufzeit
    • Dasselbe Muster ist auch in Podman issue #12495 zu sehen
  • Gemeinsame Merkmale: Nur TCP fällt aus, ICMP funktioniert, Neustart erforderlich, Auftreten im Abstand von mehreren Wochen

Betroffener Bereich

  • Kann auf macOS-Systemen auftreten, die länger als 49 Tage und 17 Stunden ohne Unterbrechung laufen
  • Normale Nutzer sind wegen regelmäßiger Updates und Neustarts meist kaum betroffen
  • Hochrisiko-Umgebungen
    • Langlaufende Server-Flotten
    • macOS-basierte CI/CD-Build-Server
    • Mac Pro-Workstations
    • Per Remote verwaltete Colocation-Macs
    • Mac-mini-Cluster für Build-Farmen und Testinfrastruktur

Reproduktionsschritte

  • Den erwarteten Overflow-Zeitpunkt aus der Boot-Zeit berechnen
  • Die Anzahl der TIME_WAIT-Verbindungen vor und nach dem Overflow überwachen
  • Zum Zeitpunkt des Overflows viele kurze TCP-Verbindungen erzeugen
  • Wenn die Zahl der TIME_WAIT-Verbindungen nach 2 Minuten nicht sinkt, wurde der Bug erfolgreich reproduziert

Nach 9,5 Stunden beobachteter Systemzustand

  • Keine einzige TIME_WAIT-Verbindung wurde bereinigt; die Zahl stieg weiter an
  • Mehr als 3.000 fehlgeschlagene Verbindungen im Zustand SYN_SENT hatten sich angesammelt
  • Bestehende Verbindungen blieben erhalten, neue Verbindungen waren nicht mehr möglich
  • Die durchschnittliche Last von Machine B stieg auf 49,74, weil der Kernel übermäßig viel CPU für das Scannen der TIME_WAIT-Queue verbrauchte

Fazit

  • Ein einzelner 32-Bit-Integer und die Bedingung if (tmp < current_tcp_now) wirken als Zeitbombe, die nach 49,7 Tagen den gesamten TCP-Stack stoppt
  • Es handelt sich um eine Art von Fehler, die in Entwicklung, Tests und Code-Review nur schwer auffällt und sich erst in realen Produktionsumgebungen zeigt
  • Photon konnte das gleiche Verhalten auf mehreren Servern reproduzieren und klar nachweisen: Vor dem Overflow wurde normal bereinigt, danach sammelte sich TIME_WAIT an
  • Wenn tcp_now stehen bleibt, stoppt die TCP-Uhr des Kernels; das System wirkt äußerlich noch normal, aber alle TCP-Ports sind erschöpft
  • Administratoren langlaufender macOS-Systeme sollten sich 49 Tage 17 Stunden 2 Minuten 47 Sekunden merken; bis zu einer Anpassung des Neustart-Zyklus oder einem Kernel-Fix sind regelmäßige Neustarts nötig
  • Photon arbeitet derzeit an einer Umgehungslösung, die tcp_now ohne Neustart wiederherstellen soll

1 Kommentare

 
GN⁺ 21 일 전
Hacker-News-Kommentare
  • Jetzt verstehe ich endlich, warum mein iMac manchmal überhaupt keine Verbindungen mehr hatte.
    Ich hatte keine Ahnung, dass es an der Uptime lag.

  • Beim Lesen hatte ich stark den Eindruck, dass der Text von einer AI geschrieben wurde, und habe mich gefragt, ob Apple tatsächlich kontaktiert wurde.
    Der Bug ist natürlich wichtig, aber es wirkte auf mich, als gäbe es viele übertriebene Formulierungen.
    Die meisten Nutzer dürften kaum betroffen sein.
    Wenn man den Mac in den Ruhezustand versetzt, wird der TCP-Stack zurückgesetzt, wodurch sich das Problem womöglich vermeiden lässt.
    Apple wird das am Ende sicher beheben, aber in Panik geraten muss man deswegen jetzt nicht.

    • Ich glaube, ich hatte dieses Problem auch.
      Mein MacBook mit deaktiviertem automatischem Ruhezustand lief etwa 50 Tage durch, und ping funktionierte, aber TCP-Verbindungen überhaupt nicht mehr.
      Weder ein Wechsel des Wi‑Fi noch eine kabelgebundene Verbindung halfen, und nach einem Neustart war sofort wieder alles normal.
    • Apple wurde nicht kontaktiert; es wirkt so, als wolle der Blogautor das selbst beheben.
      Er sagte wohl, dass er an einer alternativen Lösung arbeitet, die besser ist als ein Neustart, und dass man bis dahin regelmäßig neu starten solle.
    • Ich lasse meinen Mac Mini auch rund um die Uhr laufen, und wenn das Netzwerk gelegentlich hängen bleibt, hilft es, den Wi‑Fi-Adapter aus- und wieder einzuschalten.
      Das ist dann ein guter Zeitpunkt für einen Neustart.
    • Es wurde tatsächlich an Apple gemeldet und im internen System erfasst.
  • Von AI geschriebene Blogposts sind in letzter Zeit wirklich schwer zu lesen.
    Der Stil ist unnatürlich, und es dauert viel zu lange, bis man zum Kern kommt.

    • Geht mir genauso. Von AI geschriebene Texte zu lesen ist anstrengend, und ich kann mich schlecht darauf konzentrieren.
    • Wenn man nur die AI-Zusammenfassung liest, ist es simpel — das Problem ist, dass der Mac beim Overflow der tcp_now-Uhr keinen Rollover zulässt.
  • Ich stimme der Aussage „Kein Entwickler wird 50 Tage lang testen“ nicht zu.
    In der Praxis kann man einfach die Zeit beschleunigen und einen Simulationstest durchführen.

    • Im Linux-Kernel wird, um solche Probleme zu finden, der jiffies-Zähler beim Booten auf einen Wert kurz vor dem Overflow initialisiert.
    • macOS verwendet eine Hardware-Uhr, die im Sleep anhält.
      In so einem Fall könnte man eine Funktion wie calculate_tcp_clock anpassen und die Uptime als Argument übergeben, um das zu verifizieren.
    • Solche Methoden werden auch bei Videospiel-Tests häufig eingesetzt.
  • Dieser Bug betrifft nicht nur OpenClaw, sondern alle TCP-Verbindungen.

    • Eine einzelne Verbindung muss dafür nicht lange bestehen.
      Sobald die macOS-Uptime 49,7 Tage überschreitet, sind alle TCP-Verbindungen betroffen.
    • Es gab auch den Scherz: „Jetzt wirkt OpenClaw wie das wichtigste Ding der Welt.“
  • Mehrere meiner macOS-Geräte laufen seit über 600 bis 1000 Tagen, und TCP-Verbindungen laufen dort normal ab.
    Die Kernel-Versionen sind 20.6.0 bzw. 17.7.0.
    Daher scheint dieser Bug erst ab einer bestimmten Version aufzutreten.

    • Der Analyse zufolge bleibt der Wert von tcp_now kurz vor dem Overflow stehen, und durch einen fehlerhaften Wraparound in der Timer-Berechnung wird er negativ, wodurch Vergleiche fehlschlagen.
      Für kurze Zeit können sich zwar TIME_WAIT-Verbindungen ansammeln, aber der Originaltext reagierte übertrieben und wirkte wie ein von einem LLM geschriebener Beitrag.
    • Tatsächlich soll dieser Bug aus neuem Code stammen, der letztes Jahr in macOS 26 eingeführt wurde.
      Relevanter GitHub-Link
  • Solche Probleme tauchen in verschiedenster Software immer wieder auf.
    Früher gab es etwas Ähnliches auch bei den Guild-Wars-Servern; dort wurde zum Testen ein bestimmter Wert zu GetTickCount() addiert, um einen Overflow schneller auszulösen.

    • Systeme, die mit Overflow umgehen müssen, sollten direkt nach dem Start so getestet werden, dass sofort ein Overflow ausgelöst wird.
  • Dieser Bug erinnert an den 49,7-Tage-Bug von Windows 95.
    Zugehöriger Artikel

    • Ich habe auch versucht, mich daran zu erinnern, wo ich diese magische Zahl schon einmal gesehen hatte.
    • Es wirkt buchstäblich wie ein „neues altes Problem“.
    • Auch das 51-Tage-Stromneustartproblem der Boeing 787 ist ein ähnlicher Fall.
    • Deshalb kam mir die Zahl 49,7 Tage so bekannt vor.
  • Ich frage mich, was OpenClaw überhaupt mit diesem Bug zu tun hat.

  • Dieses Problem erinnert mich an den 208-Tage-Bug des Linux-Kernel-Schedulers.
    Referenzlink