
Im ersten Teil dieser kleinen ADS-B-Saga hatte ich am Ende eine Sache offen gelassen und sie sogar fett in die Was-noch-kommt-Liste geschrieben: MLAT aktivieren, sobald Flightradar24 den NTP-Bug fixt. Heute ist es soweit. Der Fix ist da, er kam mit Version 1.0.57, und er kam ganz anders als ich erwartet hätte. Statt den kaputten NTP-Client zu reparieren, hat FR24 ihn einfach rausgeworfen.
Wer den ersten Teil noch nicht kennt, holt das am besten kurz nach: Eigener ADS-B Feeder: Flugzeuge tracken mit Raspberry Pi, RTL-SDR und selbstgebauter Antenne. Dort steht das komplette Setup, die selbstgebaute Antenne und eben die Geschichte mit dem NTP-Bug, der meinen Feeder über Wochen am Online-Gehen gehindert hat. Den Bug selbst erkläre ich hier nur noch in ein paar Sätzen, die lange Version steht drüben.
Worum es ging, ganz kurz
Seit Version 1.0.55 hatte der fr24feed-Daemon einen internen NTP-Client, der schlicht nichts tat. Kein einziges Paket auf Port 123, also keine Zeitsynchronisation, und ohne synchronisierte Zeit lässt FR24 den Feeder nicht online gehen. Man hängt in einer Endlosschleife aus Failed to synchronize fest und kommt nie über dieses Sync-Gate hinaus. Mein Workaround war die letzte funktionierende Version 1.0.54 mit apt-mark hold festzunageln und auf einen Fix zu warten.
Im März hatte ich FR24 einen Bug-Report mit strace- und tcpdump-Belegen geschickt. Die Antwort von Muazzam aus dem Support: auf ihrer Seite nicht reproduzierbar, Verdacht auf eine Regression durchs Build-System und nicht durch eine Änderung am NTP-Client selbst. Ich blieb hartnäckig, lieferte am 6. Juni eine syscall-genaue A/B-Analyse nach, und am 8. Juni kam die erlösende Mail (Ticket #741092): „should be fixed in v 57 which will be released later today“. War es dann auch, noch am selben Tag lag 1.0.57-1 im Repo.
Warum ich nicht einfach apt upgrade tippe
fr24feed ist closed-source, proprietär, kein GitHub, keine Quellen. Ich kann ein Release also nicht am Code beurteilen, sondern nur an seinem Verhalten. Und ein blindes Upgrade auf dem laufenden Produktiv-Feeder kam nicht in Frage. Wenn 1.0.57 genauso kaputt gewesen wäre wie 1.0.56, hätte ich mir den Feeder zerschossen und müsste erst wieder zurückrollen, bevor überhaupt wieder Daten fliessen.
Die saubere Variante: das Binary aus dem .deb extrahieren und als isolierte Wegwerf-Instanz gegen eine Wegwerf-Config unter strace laufen lassen. Eigener Fake-Key, ein toter Receiver-Port, der echte Feeder läuft dabei unberührt weiter. Erst wenn der Testlauf sauber durchkommt, fasse ich die Produktion an.
Der Testaufbau, eine Wegwerf-Instanz unter strace
Die Test-Config ist bewusst minimal gehalten. Sie muss nur weit genug kommen, dass der Feeder die Zeitsynchronisation versucht, alles danach interessiert für diesen Test nicht:
fr24key=0123456789abcdef receiver=beast-tcp host=127.0.0.1:39999 # absichtlich toter Port, fuer die NTP-Phase egal bs=no raw=no mlat=no logmode=0
Dann sehen, ob der Pi die neue Version überhaupt schon sieht, und das Paket herunterladen ohne es zu installieren:
apt-cache policy fr24feed # Installed: 1.0.54-0 # Candidate: 1.0.57-1 # 1.0.57-1 500 https://repo-feed.flightradar24.com flightradar24/raspberrypi-stable arm64 apt-get download fr24feed dpkg-deb -x fr24feed_1.0.57-1_arm64.deb extract57
Erst die Toolchain vergleichen
Bevor ich überhaupt gestartet habe, ein kurzer Blick in die .comment-Section der ELF-Binaries. Die verrät, mit welchem Compiler gebaut wurde, und genau das war FR24s Verdacht:
readelf -p .comment extract57/usr/bin/fr24feed | grep -i gcc # GCC: (Debian 14.2.0-19) 14.2.0 1.0.57 (und 1.0.56) readelf -p .comment /usr/bin/fr24feed | grep -i gcc # GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 1.0.54 (funktioniert)
Das ist der interessante Punkt: 1.0.57 ist mit derselben GCC-14-Toolchain gebaut wie das kaputte 1.0.56. „Neu kompiliert“ allein ist also noch kein Fix, sonst wäre 1.0.56 ja schon heil gewesen. Genau das machte den strace-Test erst spannend, denn ich konnte nicht aus der Versionsnummer ableiten, ob sich am Verhalten wirklich etwas geändert hat. Der Sprung von GCC 11 auf 14 plus der Distro-Wechsel von Ubuntu 22.04 auf Debian ist gross. GCC 14 ist deutlich strenger bei Undefined Behaviour und uninitialisierten Daten, und ein latenter Bug im NTP-Transmit-Pfad konnte unter GCC 11 unsichtbar bleiben und unter GCC 14 dann brechen. FR24s Build-System-Theorie war im Nachhinein also gar nicht so abwegig.
Der A/B-Lauf
Beide Versionen, die neue 1.0.57 und die installierte 1.0.54 als Kontrolle, laufen durch denselben Harness, auf derselben Maschine, am selben Tag. Ich tracke nur die Netzwerk-Syscalls, das reicht um zu sehen ob da etwas auf Port 123 geht:
timeout -s INT 125 strace -f -tt -e trace=%network -yy -o v57_today.strace extract57/usr/bin/fr24feed --config-file=test.ini > v57_today.log 2>&1
Das Ergebnis, und es überrascht
Mein Abnahmekriterium war simpel formuliert: sendto auf Port 123 muss wieder feuern, dann ist der NTP-Client repariert. Das Ergebnis war eine kalte Dusche und gleichzeitig die ganze Pointe dieser Geschichte:
| 1.0.54 (Kontrolle) | 1.0.56 (kaputt) | 1.0.57-1 (neu) | |
|---|---|---|---|
NTP sendto auf Port 123 | 3x (eigener Client) | 0x | 0x, Client entfernt |
| Source-Address-Discovery | ja | ja | ja (Rest-Code) |
| Zeitsync-Log | offset +0.001 s | Failed to synchronize | confirmed with timesyncd |
| Failed-to-synchronize-Loop | nein | ja, endlos | nein |
| Kommt über das Sync-Gate? | ja | nein | ja |
| Toolchain | GCC 11.4.0 | GCC 14.2.0 | GCC 14.2.0 |
Über den gesamten 125-Sekunden-Lauf von 1.0.57 hinweg gab es kein einziges Paket auf Port 123. Null. Genau wie beim kaputten 1.0.56. Nach meinem ursprünglichen Kriterium hätte ich das Release durchfallen lassen müssen. Und trotzdem war der Bug weg. Der entscheidende Hinweis steht eine Zeile vorher im Log:
[time][i]Time synchronization confirmed with timesyncd [feed][i]Downloading configuration [main][i]Feed Network client started [feed][d]Fetching configuration [feed][e]Result: failure, message: Not found, check your key!
Der einzige Fehler im ganzen Testlauf ist „check your key!“, und der ist erwartet, weil meine Test-Config absichtlich den Fake-Key 0123… benutzt. Das heisst: der Feeder läuft komplett durch bis zur Feed-Registrierung. Genau vor diesem Punkt hingen 1.0.55 und 1.0.56 endlos in ihrer Sync-Schleife fest. Bug also weg, nur eben nicht so, wie ich gedacht hatte.
Zum Vergleich der Beweis aus dem 1.0.54-Kontrolllauf, wo der eigene NTP-Client noch feuert. Hier sieht man das sendto auf Port 123 schwarz auf weiss:
sendto(5<UDP:[25798]>, "33...", 48, 0,
{sa_family=AF_INET, sin_port=htons(123),
sin_addr=inet_addr("85.10.204.50")}, 16) = 48
[time][i]Time synchronized correctly, offset +0.001 seconds
Pragmatischer Workaround statt echtem Fix
Was FR24 gemacht hat, ist kein Reparieren des NTP-Clients, sondern ein Umgehen des Problems auf Architektur-Ebene. Der kaputte interne Client ist raus, übrig geblieben ist nur noch etwas Rest-Code für die Source-Address-Discovery. Die eigentliche Zeitsynchronisation delegiert der Feeder jetzt an systemd-timesyncd, also an den NTP-Dienst des Betriebssystems. Statt selbst Pakete auf Port 123 zu schicken, fragt er das OS einfach: ist deine Zeit synchron? Und wenn ja, geht es weiter.
Ehrlich gesagt finde ich das eine vernünftige Entscheidung. Ein eigener NTP-Client in einer Feeder-Software war ohnehin Reinventing the Wheel, das Betriebssystem kann das besser und macht es sowieso schon. Dass der eigentliche Bug damit nie wirklich gefunden wurde, ist aus Ingenieurssicht ein kleiner Wermutstropfen, aber für den Anwender zählt nur, dass der Feeder läuft. Und das tut er.
Das Upgrade mit Sicherheitsnetz
Erst nachdem der Testlauf sauber durch war, ging es an die Produktion. Vorher noch das alte Paket und die Config wegsichern, damit ein Rollback jederzeit ein Einzeiler bleibt:
cp /var/cache/apt/archives/fr24feed_1.0.54-0_arm64.deb /tmp/fr24test/rollback/ sudo cp /etc/fr24feed.ini /etc/fr24feed.ini.bak-20260608-161113 sudo apt-mark unhold fr24feed sudo apt-get install -y --only-upgrade fr24feed # 1.0.54-0 auf 1.0.57-1 # Stolperstein: das Paket STOPPT den Dienst beim Upgrade, startet ihn aber nicht neu sudo systemctl start fr24feed # Wieder pinnen, jetzt auf die verifiziert gute Version sudo apt-mark hold fr24feed
Der Stolperstein mit dem nicht neu gestarteten Dienst ist eine Kleinigkeit, kostet aber Nerven wenn man es nicht weiss und sich wundert warum der Feeder nach dem Upgrade tot ist. Ein systemctl start später lief alles. Die Verifikation kam aus der monitor.json und dem Journal:
"build_version":"1.0.57-1" "feed_status":"connected" "feed_num_ac_tracked":"92" [time][i]Time synchronization confirmed with timesyncd [reader][i]Timestamp source changed from UNKNOWN to SYSTEM-VALIDATED [feed][n]connected via UDP (fd 6) [feed][n]working [feed][i]sent 46,0 AC
feed_status: connected und 92 getrackte Flugzeuge. Nach Wochen auf der festgenagelten 1.0.54 ist der Feeder endlich wieder auf einer aktuellen Version und kommt sauber über das Sync-Gate. Genau das wollte ich.
Die Kehrseite, eine neue Abhängigkeit
Wer einen eigenen Feeder betreibt, sollte das hier auf dem Schirm haben: 1.0.57 spricht selbst kein NTP mehr, also braucht es jetzt einen laufenden NTP-Dienst im Betriebssystem. Auf dem Standard-Pi24-Image ist das systemd-timesyncd, und damit funktioniert es out of the box. Kurz prüfen schadet trotzdem nicht:
systemctl is-active systemd-timesyncd # active timedatectl show -p NTPSynchronized # NTPSynchronized=yes
Wer timesyncd oder chrony bewusst deaktiviert hat, oder ein abgespecktes Image ganz ohne NTP-Daemon fährt, könnte mit 1.0.57 jetzt ein neues Sync-Problem bekommen. Das ist der Preis des pragmatischen Fixes: FR24 hat die Verantwortung fürs Zeit-Setzen ans OS abgegeben, und damit muss das OS sie auch wahrnehmen.
Bonus-Fund: 1.0.57 bringt native GPS-Unterstützung
Beim Stöbern im neuen Binary ist mir noch etwas aufgefallen, das für die MLAT-Frage aus Teil 1 hochinteressant ist: 1.0.57 bringt einen PositioningNmeaDecoder und eine ganze Reihe neuer gps--Direktiven mit. Das könnte heissen, dass sich der VK-162 endlich für das MLAT-Timing nutzen lässt, das ja bislang auf NOT-PERMITTED stand.
strings /usr/bin/fr24feed | grep -oE 'gps-[a-z-]+' | sort -u # gps-altitude gps-antenna-connected gps-base-timestamp gps-ip gps-latitude # gps-longitude gps-mode gps-status gps-time ... # Welcher gps-mode-Wert ist gueltig? Durchprobiert: # gps-mode=serial -> [e]Unsupported gps-mode=serial! # gps-mode=nmea -> akzeptiert (einziger gueltiger Wert)
So weit, so vielversprechend. Mit gps-mode=nmea plus mlat-without-gps=no öffnet das Binary dann aber /dev/ttyACM0 nicht selbst, sondern loggt nur stoisch:
[main][i]Waiting for GPS time
An der Hardware liegt es nicht, die liefert nachweislich einen sauberen Fix mit 9 Satelliten, parallel mitgelesen:
$GPGGA,161727.00,5034.69002,N,00656.93035,E,1,09,0.86,384.0,M,... # Fix, 9 Sat, 384 m
Meine vorsichtige Interpretation, und das ist ausdrücklich nur eine Vermutung: 1.0.57 erwartet die NMEA-Daten offenbar gepusht, also entweder über die Beast- und Decoder-Strecke oder über eine Netzwerkquelle per gps-ip, und nicht über ein direktes Serial-Open des Dongles. Die genaue Verdrahtung ist für ein brandneues Release noch undokumentiert. Auf der Produktion rate ich da bewusst nicht herum. Ich habe FR24 stattdessen direkt nach der korrekten fr24feed.ini-Verdrahtung für einen seriell angeschlossenen NMEA-GPS gefragt, also welche Schlüssel zu gps-mode gehören, Device-Pfad, Baudrate und so weiter. Sobald die Antwort da ist, gibt es vielleicht einen dritten Teil mit MLAT. Schade, aber besser undokumentiert offen lassen als die Produktion mit Raten zerlegen.
Fazit, und die eigentliche Lehre
Die schönste Lektion steckt nicht in der Versionsnummer, sondern in meinem Abnahmekriterium. Ich war so auf den einen Syscall fixiert, dass ich beinahe das richtige Ergebnis als Fehlschlag abgehakt hätte. sendto auf Port 123 war nie das eigentliche Ziel, das war nur die zufällige Art, wie 1.0.54 die Zeit synchronisiert hat. Das richtige Erfolgskriterium war die ganze Zeit ein anderes: kommt der Feeder über das Sync-Gate, ja oder nein. Ein bestimmter Syscall ist Mittel zum Zweck, nicht der Zweck selbst. Wer Verhalten testet statt Implementierung, läuft seltener in so eine Falle.
FR24 bekommt von mir Lob für die schnelle Reaktion am Ende und einen pragmatischen Fix, der das Problem zuverlässig erledigt. Ein kleiner Kritikpunkt bleibt, dass der eigentliche Bug nie gefunden wurde, sondern nur umgangen. Aber Hand aufs Herz: ein funktionierender Feeder ist mir lieber als ein vollständig aufgeklärter, der nicht läuft. Mein Beitrag war am Ende vor allem die Reproduktion auf genau der arm64-Hardware, die FR24 im März nicht zum Fehler bringen konnte. Dass der Fix jetzt auf eben dieser Maschine hält, habe ich dem Support noch einmal zurückgemeldet, damit sie die Regression sauber abschliessen können. Manchmal ist der wertvollste Teil eines Bug-Reports, dass man hartnäckig bleibt und sauber misst.
Siehe auch:
- Eigener ADS-B Feeder: Flugzeuge tracken mit Raspberry Pi, RTL-SDR und selbstgebauter Antenne (Teil 1, die Vorgeschichte)
- Raspberry Pi als serieller Konsolenserver (noch ein Pi mit neuer Aufgabe)
- Billiger VGA-USB-Capture-Stick seziert: MS2109-Firmware, EDID-Hack und die 1080p-Lüge (noch eine closed-source-Hardware seziert)
Betreibt ihr selbst einen FR24-Feeder und seid über den NTP-Bug gestolpert, oder habt ihr die GPS-Verdrahtung in 1.0.57 schon zum Laufen gebracht? Dann lasst es mich gerne wissen, ihr dürft mich jederzeit fragen.
Schreibe einen Kommentar