IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Schlagwort: Raspberry Pi

ADS-B-Feeder, Teil 2: der NTP-Bug in fr24feed ist in 1.0.57 gefixt, nur anders als gedacht

Raspberry Pi mit RTL-SDR-Stick und ADS-B-Antenne vor einer Flugradar-Karte. Das Beitragsbild thematisiert die Behebung des NTP-Problems in fr24feed 1.0.57 und die erfolgreiche Wiederanbindung eines Flightradar24-Feeders.

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 1233x (eigener Client)0x0x, Client entfernt
Source-Address-Discoveryjajaja (Rest-Code)
Zeitsync-Logoffset +0.001 sFailed to synchronizeconfirmed with timesyncd
Failed-to-synchronize-Loopneinja, endlosnein
Kommt über das Sync-Gate?janeinja
ToolchainGCC 11.4.0GCC 14.2.0GCC 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 erste Vermutung war, dass 1.0.57 die NMEA-Daten gepusht erwartet, also über die Beast- und Decoder-Strecke oder über eine Netzwerkquelle per gps-ip statt über ein direktes Serial-Open des Dongles. Statt auf der Produktion herumzuraten habe ich FR24 aber lieber direkt gefragt, welche fr24feed.ini-Schlüssel zu einem seriell angeschlossenen NMEA-GPS gehören, Device-Pfad, Baudrate und so weiter.

Update vom 9. Juni 2026: Die Antwort von Muazzam aus dem Support (weiterhin Ticket #741092) kam am nächsten Tag und war kurz, aber unmissverständlich:

No, a local gps won’t help with mlat. For good mlat you need nano second timestamps that fpga provides. Also, we dont have an support for it.

Damit ist die Frage abschliessend beantwortet, wenn auch anders als erhofft. Ein lokal angeschlossener Serial- oder NMEA-GPS ist für MLAT schlicht keine gültige Timing-Quelle, und fr24feed unterstützt diesen Fall auch gar nicht. Der Grund steckt in der Physik der Multilateration: MLAT rechnet Flugzeugpositionen aus den Laufzeitunterschieden desselben Signals an mehreren Empfängern aus. Damit das aufgeht, müssen die Empfänger ihre Empfangszeitpunkte im Nanosekunden-Bereich stempeln, und solche Zeitstempel liefert nur dedizierte FPGA-Hardware der Radarcape-Klasse. Ein NMEA-GPS über USB-Serial hat dagegen Jitter im Millisekunden-Bereich, aus der USB-Latenz und dem Timing der NMEA-Sätze. Das sind gut sechs Grössenordnungen daneben, und selbst mit einem sauberen PPS-Signal kommt man an die FPGA-Genauigkeit nicht heran.

Das ordnet auch mein gps-mode=nmea-Experiment von oben sauber ein. Die GPS-Direktiven in 1.0.57 dienen faktisch nur der Positionsangabe, nicht dem MLAT-Timing. Das beobachtete [main][i]Waiting for GPS time, ohne dass der Feeder /dev/ttyACM0 überhaupt öffnet, war also kein Konfigurationsfehler meinerseits, sondern schlicht fehlender Support für genau diesen Anwendungsfall.

Für mich heisst das, der GPS-Dongle der seit März für genau diesen Moment bereitliegt, bleibt vorerst in der Schublade. Etwas schade, aber die Begründung ist nachvollziehbar und technisch sauber. Und für alle mit dem gleichen Setup ist die Lehre eindeutig: mit einem reinen RTL-SDR plus USB-GPS lässt sich MLAT bei FR24 nicht aktivieren, egal welche fr24feed.ini-Verdrahtung man probiert. MLAT bleibt dauerhaft auf NOT-PERMITTED. Wer MLAT wirklich will, kommt um Timing-Hardware mit FPGA nicht herum.

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:

Betreibt ihr selbst einen FR24-Feeder und seid über den NTP-Bug gestolpert, oder lasst ihr MLAT über dedizierte Timing-Hardware mit FPGA laufen? Dann lasst es mich gerne wissen, ihr dürft mich jederzeit fragen.

Eigener ADS-B Feeder: Flugzeuge tracken mit Raspberry Pi, RTL-SDR und selbstgebauter Antenne

Flugzeuge senden permanent ihre Position, Höhe und Geschwindigkeit auf 1090 MHz. Einfach so, unverschlüsselt, für jeden empfangbar. Das Ganze nennt sich ADS-B (Automatic Dependent Surveillance-Broadcast) und ist seit Jahren Standard in der Luftfahrt. Man braucht nur einen günstigen SDR-Empfänger und eine passende Antenne, um das Signal zu dekodieren. Und weil Dienste wie Flightradar24 auf Daten von freiwilligen Feedern angewiesen sind, bekommt man als Gegenleistung einen Business-Account, der sonst knapp 500 Euro im Jahr kostet.

Beitragsbild zum ADS-B-Feeder: Raspberry Pi mit RTL-SDR-Dongle und selbstgebauter 1090-MHz-Groundplane-Antenne, kombiniert mit einer Karte von Mitteleuropa mit zahlreichen Flugzeugsymbolen und einem Flightradar24-Dashboard-Overlay.

Ich wollte das schon länger mal ausprobieren. Ein Raspberry Pi lag noch herum, ein billiger RTL-SDR-Stick war schnell bestellt, und die Antenne habe ich selbst gebaut. Nach längerem Betrieb kann ich sagen: Das Projekt macht erstaunlich viel Spaß und liefert faszinierende Ergebnisse. Bis zu 335 km Reichweite mit einer Antenne aus Kupferdraht und einer N-Buchse für unter 10 Euro.

Was ist ADS-B eigentlich?

ADS-B steht für Automatic Dependent Surveillance-Broadcast. Jedes moderne Verkehrsflugzeug sendet damit periodisch seine GPS-Position, Flughöhe, Geschwindigkeit, ICAO-Kennung und Squawk-Code auf 1090 MHz. Das Signal ist nicht verschlüsselt und nicht authentifiziert. Jeder mit einem passenden Empfänger kann es dekodieren. Der Empfang ist legal und rein passiv, man sendet nichts.

Die Reichweite hängt von der Sichtlinie (Line of Sight) ab. Flugzeuge in großer Höhe sind über hunderte Kilometer empfangbar. Tieffliegende Maschinen oder Flugzeuge hinter Bergen dagegen nicht. Topografie spielt eine große Rolle.

Warum ein eigener Feeder?

Flightradar24 lebt von den Daten freiwilliger Feeder weltweit. Je mehr Stationen, desto besser die Abdeckung. Als Gegenleistung gibt es einen kostenlosen Business-Account. Der kostet regulär knapp 500 Euro pro Jahr und bietet unter anderem erweiterte Filter, historische Flugdaten und eine werbefreie Oberfläche. Für Hardware im Wert von 100 bis 150 Euro ein ziemlich guter Deal.

Geöffneter Filterdialog einer Flightradar24-App. Der Empfänger T-EDKB55 ist ausgewählt, Filterung ist aktiviert und ein benutzerdefinierter Filter (ICH) gesetzt. Unten Schaltfläche zum Hinzufügen weiterer Filter.

Nebenbei kann man die empfangenen Daten auch parallel an andere Dienste wie FlightAware oder ADS-B Exchange schicken. Und natürlich ist es einfach ein tolles Bastelprojekt mit sofort sichtbarem Ergebnis. Man sieht in Echtzeit auf einer Karte, welche Maschinen gerade über einem fliegen.

Hardware

Das Setup ist überschaubar:

KomponenteModellHinweis
EinplatinencomputerRaspberry Pi 4 Model B4 GB RAM, 64 GB SD-Karte
BetriebssystemPi24 (offizielles FR24-Image)Debian Bookworm, Kernel 6.12
SDR-DongleRealtek RTL2838 (RTL-SDR)Günstiger DVB-T-Stick als SDR-Empfänger
GPS-DongleVK-162 (u-blox 7)USB, 3D-Fix, ~10 Satelliten
AntenneEigenbau: λ/4-GroundplaneFür 1090 MHz, siehe Abschnitt Antennenbau

Der Raspberry Pi 4 ist für die Aufgabe eigentlich überdimensioniert. Ein Pi 2 oder 3 würde ebenfalls reichen. Das Pi24-Image von Flightradar24 bringt alles mit: Betriebssystem, den Feeder-Client fr24feed, den ADS-B-Decoder dump1090 und ein lokales Web-Interface. SD-Karte flashen, WLAN oder Ethernet konfigurieren, fertig.

Der RTL-SDR-Dongle ist ein umfunktionierter DVB-T-Stick. Die Dinger kosten zwischen 10 und 25 Euro und können in einem breiten Frequenzbereich empfangen. Für ADS-B braucht man 1090 MHz, das schaffen die meisten RTL2832U-basierten Sticks problemlos.

Standort

Mein Feeder steht im Raum Bonn/Hangelar (Siegburg-Umgebung). Nicht gerade der ideale Standort für maximale Reichweite. Die Eifel im Süden blockiert einen Teil des Empfangs, und die Antenne steht aktuell nur am Fenster. Trotzdem sind die Ergebnisse beeindruckend, dazu gleich mehr.

Meine Radar-ID bei Flightradar24: T-EDKB55.

Antennenbau: λ/4-Groundplane für 1090 MHz

Die mitgelieferten DVB-T-Antennen sind für den Frequenzbereich um 500 MHz ausgelegt. Für ADS-B auf 1090 MHz sind sie schlicht ungeeignet. Ich habe drei verschiedene gekaufte DVB-T-Antennen getestet. Alle performten schlechter als die Original-Stummelantenne. Das war frustrierend, aber auch lehrreich.

Die Lösung: Selbst bauen. Nach einer hervorragenden Anleitung von weberblog.net habe ich eine λ/4-Groundplane-Antenne gebaut. Das ist im Prinzip ein vertikaler Strahler mit vier Radialen, abgestimmt auf 1090 MHz.

Die Physik dahinter ist simpel: Die Wellenlänge bei 1090 MHz beträgt λ = c / f ≈ 27,5 cm. Ein Viertel davon (λ/4) ergibt 68 mm. Das ist die Länge jedes Antennenelements.

Material:

  • N-Einbaubuchse (N-Flanschbuchse)
  • 2,5 mm² Kupferdraht (massiv)
  • Koaxialkabel (RG213 oder Satellitenkabel)
  • M4-Schrauben zur Montage
  • Adapter je nach SDR-Stick (MCX, SMA oder BNC)

Aufbau: Ein Strahler (68 mm Kupferdraht) wird vertikal am Center-Pin der N-Buchse angelötet. Vier Radiale (ebenfalls 68 mm) werden an der Masse befestigt und ca. 45 Grad nach unten gebogen. Alle Elemente exakt auf 68 mm kürzen, das ist wichtig. Optional kann man einen Wetterschutz drüber stülpen, ein altes CD-Spindelgehäuse oder ein Stück PVC-Rohr tut es.

Laut der Bauanleitung von weberblog.net bringt die selbstgebaute Antenne im Indoor-Test +61% mehr erkannte Flugzeuge (39 → 63 Aircraft). Andere Bastler berichten von bis zu 160 NM Reichweite mit acht Radialen und Mastmontage. Meine Erfahrung bestätigt das. Der Unterschied zur Stummelantenne war sofort sichtbar.

Software

Das Pi24-Image bringt alles mit. fr24feed ist der offizielle Feeder-Client von Flightradar24. Er startet intern dump1090-mutability als ADS-B-Decoder und schickt die empfangenen Daten per UDP an die FR24-Server. Dazu läuft ein lighttpd für die lokalen Web-Interfaces.

Die Konfiguration liegt in /etc/fr24feed.ini:

receiver=dvbt
fr24key=<sharing-key>
path=/usr/lib/fr24/dump1090
bs=no
raw=no
mlat=yes
mlat-without-gps=yes
lat=50.578167
lon=6.948833
alt=1261

Lokal gibt es drei Web-Interfaces: Die FR24 Status-GUI unter http://<IP>/, den JSON-Monitor unter http://<IP>:8754/monitor.json und die dump1090-Karte unter http://<IP>:8080/. Die Karte zeigt in Echtzeit alle empfangenen Flugzeuge auf einer OpenStreetMap-Karte. Das alleine ist schon faszinierend.

Ersteinrichtung

Nach dem Flashen des Pi24-Images musste ich noch ein paar Dinge anpassen:

  1. Hostname geändert: pi24-bookwormflightradar24
  2. Statische IP konfiguriert via NetworkManager (DHCP → feste Adresse)
  3. GPS-Koordinaten in fr24feed.ini eingetragen
  4. dump978-fr24 deaktiviert (UAT 978 MHz wird in Europa nicht verwendet)
  5. Bluetooth deaktiviert (nicht benötigt, erzeugte unnötige Fehlermeldungen)
  6. OS-Update: 232 Pakete aktualisiert, Kernel von 6.6.21 auf 6.12.62
  7. Boot-Fix: Bind-Mount /boot/boot/firmware (Pi24-Image-Kompatibilität)

Reichweite und Ergebnisse

Nach drei Wochen Betrieb, noch mit der Antenne am Fenster:

MetrikWert
Flugzeuge aktuell getrackt (Snapshot)74 (34 ADS-B + 40 Non-ADS-B)
Flugzeuge gesamt gesehen1.541
Nachrichten verarbeitet~8,9 Millionen
Maximale Reichweite~335 km (~181 NM)
Signal (Durchschnitt)-20,9 dBFS
SNR~14,8 dB
CPU-Temperatur47,2 °C
Uptime20 Tage
Dashboard eines privaten Flightradar24-Empfängers (T-EDKB55) mit Status online, IP-Adresse und Betriebsdaten. Angezeigt werden Kennzahlen wie Anzahl erfasster Flugzeuge, gemeldete Positionen und Treffer sowie Diagramme zur täglichen Verfügbarkeit, Reichweite (Polar-Plot), Ranking und Histogramme.

335 Kilometer Reichweite. Mit einer Indoor-Antenne aus Kupferdraht für unter 10 Euro. Das war ein Norwegian-Flug (NOZ1802) über der Nordsee auf FL360. Das hätte ich vorher nicht für möglich gehalten.

Die Hauptabdeckung geht nach Norden und Nordwesten. KLM-Flüge über den Niederrhein und die Niederlande sind in 250 bis 335 km Entfernung problemlos sichtbar. Nach Nordosten reicht es bis ins Münsterland und den Raum Osnabrück. Nach Süden ist die Abdeckung durch die Eifel-Topografie eingeschränkt, aber Flüge bis in den Raum Trier/Luxemburg (~100 km) kommen noch durch. Lokal sieht man natürlich alles, was sich im Raum Bonn/Hangelar bewegt, Privatflieger, Kleinflugzeuge, Hubschrauber.

Kartenansicht von Mitteleuropa mit zahlreichen gelben Flugzeugsymbolen, die aktuellen Flugverkehr anzeigen. Hohe Dichte über Nordrhein-Westfalen, Benelux und den Niederlanden; einzelne Flugzeuge auch über Norddeutschland und Südwestdeutschland verteilt.

Ein paar Beispiele vom Snapshot:

CallsignAirlineHöheEntfernung
NOZ1802NorwegianFL360~335 km
BTI859airBaltic10.600 ft~249 km
KLM96EKLM14.725 ft~232 km
SIA314Singapore AirlinesFL360~25 km
BAW169British AirwaysFL330~16 km
UAE62TEmiratesFL380~42 km

Singapore Airlines, Emirates und British Airways über dem Rheinland. Das hat was.

Bug: NTP-Client in fr24feed 1.0.55-0

Achtung, Falle: Version 1.0.55-0 von fr24feed ist defekt. Der Feeder bleibt in einer Endlosschleife mit [time][e]Failed to synchronize time hängen und geht nie online. Nicht nur MLAT funktioniert nicht, das gesamte Feeding ist tot.

Ich habe das mit strace und tcpdump analysiert. Der statisch kompilierte interne NTP-Client löst pool.ntp.org per DNS korrekt auf, sendet aber nie UDP-Pakete auf Port 123. Der Client ist schlicht kaputt. Kein Workaround hat funktioniert: weder Root-Rechte, noch CAP_NET_RAW, noch ein lokaler NTP-Server, noch nftables DNAT-Umleitung.

Die Lösung ist ein Downgrade:

# Downgrade auf funktionierende Version
sudo apt install fr24feed=1.0.54-0
# Version pinnen gegen Auto-Update
sudo apt-mark hold fr24feed

Ich habe den Bug direkt an den FR24-Support gemeldet, mit strace-Nachweis, tcpdump-Capture und der kompletten Liste getesteter Workarounds. Die Antwort war ernüchternd: Man könne den Bug nicht reproduzieren, vermutet aber eine Library-Regression durch einen Wechsel des Build-Systems. Der Bug ist seit Januar 2026 auch im FR24-Forum bekannt (Threads #186163 und #231707). Da fr24feed proprietär und Closed Source ist, kann man leider keinen Pull Request einreichen.

Das bedeutet auch: MLAT (Multilateration) funktioniert bei mir aktuell nicht. MLAT würde es ermöglichen, auch Flugzeuge ohne ADS-B-Transponder zu erfassen, indem mehrere Feeder-Stationen die Signallaufzeiten triangulieren. Dafür braucht der Feeder aber eine exakte Zeitbasis, und genau die liefert der kaputte NTP-Client nicht. Sobald FR24 eine gefixte Version veröffentlicht, werde ich das aktivieren.

Kosten

PostenKosten
Raspberry Pi 4 (4 GB)~60–75 EUR
RTL-SDR USB-Dongle~10–25 EUR
Antenne (Eigenbau) / Kabel~5–10 EUR
GPS-Dongle VK-162~15 EUR
SD-Karte 64 GB~10 EUR
Netzteil, Kabel, Gehäuse~15–20 EUR
Gesamt~115–155 EUR

Für 115 bis 155 Euro bekommt man einen funktionierenden ADS-B-Feeder und einen Flightradar24 Business-Account im Wert von knapp 500 Euro pro Jahr. Das Projekt amortisiert sich also ziemlich schnell.

Was noch kommt

  • MLAT aktivieren, sobald FR24 den NTP-Bug fixt. Update Juni 2026: der NTP-Bug ist mit fr24feed 1.0.57 gefixt, die ganze Auflösung steht in Teil 2.
  • Outdoor-Montage der Antenne mit Wetterschutz, das sollte die Reichweite nochmals deutlich verbessern
  • Parallel-Feeding an FlightAware, ADS-B Exchange und andere Dienste

Siehe auch:

Fragen, eigene Erfahrungen mit ADS-B oder Verbesserungsvorschläge? Gerne über das Kontaktformular.

Raspberry Pi als serieller Konsolenserver

Wir haben 2026. Alles wandert in die Cloud. Trotzdem will ich heute über serielle Konsolen schreiben. Klingt retro, ist es aber nicht. Wenn ein Switch sich verkonfiguriert hat und das Netzwerk weg ist, hilft kein Ansible und kein Dashboard in der Cloud. Dann hilft nur noch der serielle Konsolenport. Out-of-Band Management ist nicht tot. Es wurde nur teuer verpackt.

Kommerzielle Konsolenserver kosten gerne vierstellig. Oder man nimmt einen Raspberry Pi der noch herum liegt und auf eine neue Aufgabe wartet (ich habe hier ein paar Pi1 oder 2 herum liegen). Zusammen mit zwei USB Serial Adaptern hat man für unter 50 Euro einen Konsolenserver mit acht Ports. Das reicht für die meisten Setups locker aus.

Raspberry Pi als DIY-Konsolenserver mit USB-Serial-Adaptern zur Verwaltung serieller Konsolen von Netzwerkgeräten über SSH und ser2net

Wofür ein Konsolenserver

Der klassische Fall: Ein paar Switches im Rack, jedes Gerät hat einen seriellen Konsolenport. Im Normalbetrieb konfiguriert man über das Netzwerk. Aber wenn mal eine falsche Route das Management Interface unerreichbar macht oder ein VLAN Umbau schiefgeht, steht man vor dem Gerät und steckt ein Kabel rein. Wenn das im DC in Frankfurt ist, oder vielleicht irgendwo in China, dann kann das spannend werden.

Oder man hat vorgebaut.

Ein Konsolenserver hängt permanent an den seriellen Ports der Netzwerkgeräte. Man kommt per SSH auf den Konsolenserver und von dort auf die serielle Konsole des Zielgeräts. Ob das Netzwerk funktioniert oder nicht, spielt keine Rolle mehr. Öhm also ja, so grob. Der Pi sollte dann ja schon noch erreichbar sein. Aber man hat ja in einem entfernten DC auch eine Dailin Line oder ähnliches, richtig? Richtig?

Meme mit Anakin und Padmé: „Der Konsolenserver hängt an allen Switches – wir kommen immer auf die Konsole – der Raspi ist erreichbar über … die gleiche Strecke.“

Hardware

Ein Raspberry Pi. Es muss kein aktuelles Modell sein. Selbst ein alter Pi 2 reicht völlig aus. Das Ding muss ser2net laufen lassen und ein paar serielle Ports bedienen, dafür braucht man keinen Quad Core mit 8 GB RAM. Der Pi aus der Schublade bekommt endlich eine sinnvolle Aufgabe.

FTDI Quad Port USB Serial Adapter (Vendor 0403, Product 6011). Pro Adapter bekommt man vier serielle Ports. Mit zwei Adaptern hat man acht Ports. Die Dinger gibt es für kleines Geld.

RS232 Kabel zu den Console Ports der Netzwerkgeräte. Welcher Stecker passt, hängt vom Hersteller ab. RJ45 auf DB9, DB9 auf DB9, die üblichen Verdächtigen. Da muss man schauen was die eigenen Geräte mitbringen.

Stabile Gerätenamen mit udev

Das erste Problem nach dem Einstecken der USB Adapter: Linux vergibt die /dev/ttyUSBx Nummern nach Lust und Laune. Nach einem Reboot kann ttyUSB0 plötzlich ttyUSB4 sein. Wenn man wissen will welcher Port an welchem Gerät hängt, ist das unpraktisch.

Die Lösung sind udev Regeln. Jeder FTDI Adapter hat eine eigene Seriennummer. Die findet man so:

udevadm info -a -n /dev/ttyUSB0 | grep serial

Damit baut man sich Regeln die stabile Symlinks erzeugen. Datei /etc/udev/rules.d/99-serial-consoles.rules:

SUBSYSTEMS=="usb", ENV{.LOCAL_ifNum}="$attr{bInterfaceNumber}"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FT000001", SYMLINK+="quad0-%E{.LOCAL_ifNum}"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FT000002", SYMLINK+="quad1-%E{.LOCAL_ifNum}"

FT000001 und FT000002 ersetzt man durch die echten Seriennummern der eigenen Adapter. Das Ergebnis sind stabile Symlinks: /dev/quad0-00 bis /dev/quad0-03 für den ersten Adapter, /dev/quad1-00 bis /dev/quad1-03 für den zweiten. Acht Ports, immer gleich benannt. Egal wie oft man den Pi neustartet.

ser2net

ser2net bildet die seriellen Ports auf TCP Ports ab. Man kann dann per Telnet auf einen bestimmten Port zugreifen und landet direkt auf der seriellen Konsole des zugehörigen Geräts. Installieren mit apt install ser2net, dann die Konfiguration in /etc/ser2net.conf:

localhost,2001:telnet:600:/dev/quad0-00:9600 8DATABITS NONE 1STOPBIT banner
localhost,2002:telnet:600:/dev/quad0-01:9600 8DATABITS NONE 1STOPBIT banner
localhost,2003:telnet:600:/dev/quad0-02:9600 8DATABITS NONE 1STOPBIT banner
localhost,2004:telnet:600:/dev/quad0-03:9600 8DATABITS NONE 1STOPBIT banner
localhost,2005:telnet:600:/dev/quad1-00:9600 8DATABITS NONE 1STOPBIT banner
localhost,2006:telnet:600:/dev/quad1-01:9600 8DATABITS NONE 1STOPBIT banner
localhost,2007:telnet:600:/dev/quad1-02:9600 8DATABITS NONE 1STOPBIT banner
localhost,2008:telnet:600:/dev/quad1-03:9600 8DATABITS NONE 1STOPBIT banner

9600 8N1 ist der Standard bei den meisten Netzwerkgeräten. Falls ein Gerät eine andere Baudrate braucht, passt man die entsprechende Zeile an. Der Timeout von 600 Sekunden trennt die Verbindung nach zehn Minuten Inaktivität. Das verhindert dass ein vergessenes Telnet die Konsole dauerhaft blockiert.

Direkter Zugriff mit minicom

Wer ser2net nicht nutzen will oder schnell direkt auf einen Port muss, nimmt minicom:

minicom -D /dev/quad0-00 -b 9600

minicom ist gut für schnelle Tests und Debugging. Für den Dauerbetrieb mit mehreren Ports gleichzeitig ist ser2net die bessere Wahl.

Warum localhost

ser2net ist im gezeigten Setup bewusst auf localhost gebunden. Man muss sich erst per SSH auf den Pi einloggen und dann telnet 127.0.0.1 200x aufrufen. Das ist Absicht.

Man könnte ser2net auch auf 0.0.0.0 binden und die Ports direkt aus dem Netz erreichen. Davon rate ich ab. Telnet ist unverschlüsselt. Auch in einem Management VLAN hat das nichts verloren.

Bessere Alternativen wenn man ohne SSH auf den Pi will:

  • ser2net ab Version 4.x unterstützt SSL/TLS. Damit hat man verschlüsselte Verbindungen direkt zu den Console Ports.
  • stunnel vor ser2net schalten. stunnel terminiert TLS und reicht die Verbindung an den lokalen ser2net weiter.
  • Wer nativen SSH Zugriff direkt auf die seriellen Ports braucht, sollte sich conserver anschauen. ser2net kann kein SSH.

Für die meisten Setups ist SSH auf den Pi und dann Telnet auf localhost der einfachste und sicherste Weg.

Absichern

Ein paar Dinge die man auf dem Pi noch machen sollte:

Den Default Benutzer pi löschen. Einen eigenen Benutzer anlegen. SSH Key Authentifizierung einrichten und Login per Passwort deaktivieren. Das ist nicht optional.

NTP konfigurieren. Timestamps in Logs sind nutzlos wenn die Uhrzeit nicht stimmt.

Syslog an einen zentralen Logserver weiterleiten. Wenn man serielle Konsolen mitschneidet, will man die Logs nicht nur lokal auf dem Pi haben.

Workflow

Der Alltag sieht dann so aus:

  1. SSH auf den Pi: ssh admin@10.0.0.50
  2. Telnet auf den gewünschten Port: telnet 127.0.0.1 2003
  3. Man landet auf der seriellen Konsole von Switch 3

Alternativ direkt mit minicom: minicom -D /dev/quad0-02 -b 9600

Zum Trennen: Ctrl-] und dann quit bei Telnet. Ctrl-A gefolgt von X bei minicom.

Fazit

Ein alter Raspberry Pi, zwei USB Adapter, ein paar Kabel. Mehr braucht man nicht für einen funktionierenden Konsolenserver mit acht Ports. Die Einrichtung dauert vielleicht eine Stunde. Danach läuft das Ding und man muss nie wieder ein Konsolenkabel quer durch den Serverraum schleppen.

Und der alte Pi aus der Schublade hat endlich wieder eine Aufgabe.

Ihr habt Fragen, Anmerkungen oder baut das Setup selbst nach? Meldet euch gerne über die Kontaktseite oder direkt per E-Mail.

Siehe auch: DHT22 am Raspberry Pi

Kodi auf dem Raspberry Pi 4: Ruckelfreie Wiedergabe einrichten

Der Raspberry Pi 4 , egal ob mit 4GB oder 8GB RAM, ist in der Kombination mit Kodi eine wunderbare Erweiterung am Fernseher. Leider sorgte die letzte Version Kodi v19.3 (Matrix) bei mir für ein paar Problemchen. So stockte oder ruckelte die Wiedergabe von Videos oder die Wiedergabe lief für einige Minuten gut, dann wurde gebuffert, nur damit sich dieses Spielchen alle paar Minuten wiederholte. Egal ob im WLAN oder direkt am LAN.

Folgende Änderungen haben bei mir für eine Lösung der Probleme gesorgt:

  1. Erstellen einer XML Datei, welche die default Einstellungen des Cachings überschreibt.

    Speicherort und Dateiname ist: /storage/.kodi/userdata/advancedsettings.xml
<?xml version="1.0" encoding="utf-8"?>
<advancedsettings>
        <cache>
                <memorysize>524288000</memorysize>
                <buffermode>1</buffermode>
                <readfactor>6</readfactor>
        </cache>
</advancedsettings>

Achtung… Bei XML Dateien, spielt das richtige „Einrücken“ schon mal eine Rolle.

2. Erweitern des Arbeitsspeichers für die GPU, sowie das Erzwingen des „Turbo“ Modus.
Dafür einfach die Datei /flash/config.txt um folgende Zeilen erweitern/einpassen:

# Default GPU memory split, 76MB are needed for H264 decoder
gpu_mem=256
force_turbo=1

Wer dieses gerne per SSH machen möchte, muss das Volume /flash einmal schreibfähig mounten:

mount -o remount,rw /flash

Die Option gpu_mem setzt recht einfach den, für die Grafikkarte, reservierten Arbeitsspeicher fest auf 256MB. Dieses macht selbst bei der 4GB Raspberry PI 4 Version kein Problem.

force_turbo deaktiviert das dynamische, lastabhängige takten der CPU, GPU und des Arbeitsspeichers, sowie der Spannungen. Alles läuft daher auf Maximum, aber ohne zu übertakten. Dieses hat weniger Auswirkungen auf die Probleme bei der Wiedergabe, sorgt aber für ein allgemein „flüssigeres“ Verhalten. Dafür steigt die Stromaufnahme und die Temperatur. Da wir hier über einen Raspberry sprechen, ist es wohl für die Meisten zu vernachlässigen.

3. Um Temperatur und Geräuschpegel im Zaum zu halten, empfiehlt sich ein gutes passiv gekühltes Gehäuse. Folgendes kann ich empfehlen: https://amzn.to/3qF61pe

Das mitgelieferte Netzteil hat ausreichend Power, man kommt noch an „alles“ ran, das Gehäuse ist sehr massiv und selbst bei großer Last/langem Betrieb, wird alles nur handwarm.


Update Februar 2026 — Kodi 21 (Omega) / LibreELEC 12.x

Seit Kodi 21 (Omega), das mit LibreELEC 12.x ausgeliefert wird, funktioniert die oben beschriebene Cache-Konfiguration über die advancedsettings.xml nicht mehr korrekt. Die <cache> Sektion wird zwar noch eingelesen und im Log angezeigt — die tatsächlich aktiven Werte kommen aber aus den GUI-Settings (guisettings.xml). Im Kodi-Log erkennt man das an dieser Zeile:

New Cache GUI Settings (replacement of cache in advancedsettings.xml) are:
    Buffer Mode: 4
    Memory Size: 20 MB
    Read Factor: 4.00 x

Das bedeutet: Trotz konfigurierter 500 MB in der advancedsettings.xml läuft Kodi mit nur 20 MB Puffer — dem Default. Nicht gerade ideal.

Die neue Methode

Die Cache-Werte müssen jetzt direkt in /storage/.kodi/userdata/guisettings.xml gesetzt werden. Dafür Kodi stoppen, Datei bearbeiten, Kodi starten:

systemctl stop kodi
sleep 3

In der guisettings.xml diese drei Zeilen suchen und anpassen. Wichtig: Das default="true" muss entfernt werden, damit Kodi die Werte als benutzerdefiniert erkennt.

Vorher:

<setting id="filecache.buffermode" default="true">4</setting>
<setting id="filecache.memorysize" default="true">20</setting>
<setting id="filecache.readfactor" default="true">400</setting>

Nachher (Beispiel für 8 GB RAM):

<setting id="filecache.buffermode">1</setting>
<setting id="filecache.memorysize">500</setting>
<setting id="filecache.readfactor">600</setting>

Dann Kodi wieder starten:

systemctl start kodi

Was die Werte bedeuten

buffermode = 1

Legt fest, welche Quellen gepuffert werden:

WertBedeutung
0Nur Internet-Streams (HTTP, FTP…)
1Alles (Internet + LAN + lokal) ← empfohlen
2Nur „echte“ Internet-Streams
3Kein Puffer
4Alle Netzwerk-Quellen (Default in Kodi 21)

Wir setzen 1 statt 4, damit NFS-Quellen garantiert gepuffert werden — egal wie Kodi die Quelle intern klassifiziert.

memorysize = 500 (bzw. 250)

Die Größe des Puffers in MB. Das ist der Speicher, den Kodi im RAM reserviert, um Film-Daten vorauszulesen.

Praktisches Beispiel: Ein typischer 4K-Film hat ~80 Mbit/s Bitrate (ca. 10 MB/s).

  • 20 MB (Default): Nur ~2 Sekunden Film im Puffer. Wenn das Netzwerk kurz schwankt, stockt die Wiedergabe sofort.
  • 500 MB: Ca. 50 Sekunden Film im Puffer. Selbst wenn NFS mehrere Sekunden hängt, läuft die Wiedergabe weiter.

Empfohlene Werte nach verfügbarem RAM:

  • 8 GB RAM: memorysize = 500
  • 4 GB RAM: memorysize = 250

readfactor = 600 (= 6×)

Der Wert wird intern durch 100 geteilt, also 600 = 6,0×. Kodi liest Daten mit der 6-fachen Geschwindigkeit der benötigten Bitrate voraus. Bei einem 80 Mbit/s Film liest Kodi also mit ~480 Mbit/s vom NFS, bis der Puffer voll ist. Danach drosselt es auf die tatsächlich benötigte Rate. Das sorgt dafür, dass der Puffer sich schnell füllt und möglichst voll bleibt.

Verifizierung

Nach dem Neustart im Kodi-Log prüfen, ob die neuen Werte aktiv sind:

grep "New Cache GUI Settings" -A4 /storage/.kodi/temp/kodi.log

Hinweis zum Raspberry Pi 5

Die config.txt Anpassungen (gpu_mem=256 und force_turbo=1) gelten weiterhin für den Raspberry Pi 4. Beim Raspberry Pi 5 sind diese nicht nötig — er nutzt eine andere GPU-Architektur (VideoCore VII) und gpu_mem hat dort keine Wirkung.

Raspberry Pi als Angriffsziel: SSH-Brute-Force auf den User pi

In meinen Honeypots war 2019 ein deutlicher Trend sichtbar: SSH-Brute-Force-Angriffe zielten massiv auf den Benutzernamen pi. Im November 2018 waren 13 Prozent der Loginversuche mit dem User pi. Im März 2019 lag der Anteil bei 87 bis 88 Prozent.

Mar 25 06:20:21 pot06 sshd[93829]: Invalid user pi from xx.xx.xx.xx port 55312
Mar 25 06:20:21 pot06 sshd[93829]: Failed unknown for invalid user pi from xx.xx.xx.xx port 55312 ssh2
Mar 25 06:20:21 pot06 sshd[93827]: Invalid user pi from xx.xx.xx.xx port 55310
Mar 25 06:20:21 pot06 sshd[93827]: Failed unknown for invalid user pi from xx.xx.xx.xx port 55310 ssh2

Warum gerade pi?

Bis April 2022 legte Raspberry Pi OS automatisch den Benutzer pi mit dem Standardpasswort raspberry an. Millionen von Geräten liefen mit diesen Default-Credentials, viele davon direkt am Internet. SSH war standardmäßig aktiviert. Die Botnetze haben das erkannt und ihre Wörterbücher entsprechend angepasst.

Auffällig war auch die Herkunft: Die Quellen kamen nicht wie sonst überwiegend aus Asien, sondern vermehrt aus dem DACH-Raum. Das deutet darauf hin, dass die Angriffe erfolgreich waren und bereits kompromittierte Raspberry Pis in Deutschland, Österreich und der Schweiz als Sprungbrett nutzten.

Was sich geändert hat

Seit April 2022 erzwingt Raspberry Pi OS bei der Ersteinrichtung die Vergabe eines eigenen Benutzernamens und Passworts. Der automatische User pi wird nicht mehr angelegt. Das ist ein richtiger Schritt. Das Problem sind die Millionen von Altgeräten die noch mit den Default-Credentials laufen und nie aktualisiert wurden.

Wer einen Raspberry Pi am Internet betreibt: Standardpasswort ändern, SSH mit Key-Authentifizierung absichern, idealerweise mit Zwei-Faktor-Authentifizierung. Und den User pi am besten ganz durch einen eigenen ersetzen.

Fragen? Einfach melden.

Temperatur und Luftfeuchtigkeit mit DHT22 am Raspberry Pi messen

Meine Wetterstation hatte aufgegeben. Wirklich interessiert haben mich aber eh nur Temperatur und Luftfeuchtigkeit draußen. Das sollte ein Raspberry Pi mit einem DHT22 für zwei Euro hinbekommen — und die Daten landen direkt in meinem Cacti.

Update März 2026 — Dieser Beitrag ist von 2014 und einer meiner ältesten hier im Blog. Die Grundidee — DHT22 an den GPIO, Werte per Cron einsammeln, per SNMP an Cacti liefern — funktioniert unverändert. Ich habe den Beitrag komplett überarbeitet und den Software-Teil auf Python aktualisiert. Die ursprünglich verwendete C-Bibliothek wiringPi wurde 2019 vom Autor offline genommen und lol_dht22 wird nicht mehr gepflegt. Der Ansatz selbst ist zeitlos.

Was du brauchst

  • Einen Raspberry Pi — egal welches Modell, solange GPIO-Pins vorhanden sind
  • Einen DHT22 / AM2302 Sensor (2–5 €)
  • Einen 4,7 kΩ Widerstand als Pull-up
  • Drei Kabel

Die Verkabelung ist simpel: VCC an 3,3 V (Pin 1), Data an GPIO 4 (Pin 7), GND an GND (Pin 6). Der 4,7 kΩ Widerstand kommt zwischen VCC und Data. Den handgezeichneten Schaltplan habe ich unten in der Bildergalerie.

Sensor auslesen — Python

Auf einem aktuellen Raspberry Pi OS brauchen wir die Adafruit CircuitPython DHT Bibliothek und libgpiod:

sudo apt install python3-pip libgpiod2
pip3 install adafruit-circuitpython-dht

Dann ein kleines Script /usr/local/bin/read_dht22.py:

#!/usr/bin/env python3
import adafruit_dht
import board
import sys

sensor = adafruit_dht.DHT22(board.D4)
try:
    print(f"{sensor.humidity:.1f}")
    print(f"{sensor.temperature:.1f}")
except RuntimeError:
    sys.exit(1)
finally:
    sensor.exit()

Ausführbar machen und testen:

chmod +x /usr/local/bin/read_dht22.py
/usr/local/bin/read_dht22.py
73.9
9.3

Erste Zeile Luftfeuchtigkeit, zweite Zeile Temperatur. Der DHT22 liefert nicht bei jedem Aufruf saubere Daten — manchmal kommt ein RuntimeError. Das ist normal bei diesem Sensor, deswegen der try/except und der Exit-Code. board.D4 entspricht GPIO 4, also Pin 7 auf dem Board.

Werte per Cron einsammeln

Per Cron-Job jede Minute:

* * * * * /var/scripts/getsensor.sh

Das Script /var/scripts/getsensor.sh:

#!/bin/bash
/usr/local/bin/read_dht22.py > /home/pi/both.txt 2>/dev/null

while [ ! -s "/home/pi/both.txt" ]; do
    sleep 5
    /usr/local/bin/read_dht22.py > /home/pi/both.txt 2>/dev/null
done

sed '2d' /home/pi/both.txt > /home/pi/humid.txt
sed '1d' /home/pi/both.txt > /home/pi/temp.txt

Wenn der Sensor beim ersten Versuch keine Daten liefert, probiert das Script alle fünf Sekunden erneut. Am Ende liegen Luftfeuchtigkeit und Temperatur in separaten Textdateien unter /home/pi/.

Ab in den Cacti — SNMP

Damit Cacti die Werte abfragen kann, brauchen wir SNMP auf dem Pi:

sudo apt install snmpd snmp

In der /etc/snmp/snmpd.conf zwei Pass-through OIDs anlegen. Wird eine dieser OIDs per SNMP abgefragt, führt der snmpd das zugehörige Script aus und liefert dessen Ausgabe als Antwort:

pass .1.3.6.1.2.1.25.1.8.1  /bin/sh  /usr/local/bin/humid
pass .1.3.6.1.2.1.25.1.8.2  /bin/sh  /usr/local/bin/temp

Die beiden Scripts müssen drei Zeilen ausgeben — die OID, den Datentyp und den Wert:

/usr/local/bin/temp:

#!/bin/bash
echo .1.3.6.1.2.1.25.1.8.2
echo gauge
cat /home/pi/temp.txt

/usr/local/bin/humid:

#!/bin/bash
echo .1.3.6.1.2.1.25.1.8.1
echo gauge
cat /home/pi/humid.txt

Test:

snmpget -v2c -c public localhost .1.3.6.1.2.1.25.1.8.1
iso.3.6.1.2.1.25.1.8.1 = Gauge32: 76

snmpget -v2c -c public localhost .1.3.6.1.2.1.25.1.8.2
iso.3.6.1.2.1.25.1.8.2 = Gauge32: 9

Damit lässt sich im Cacti ein Graph anlegen. Etwas von hinten durch die Brust ins Auge — aber es funktioniert seit über elf Jahren zuverlässig. Die Template-Exports für Cacti gibt es hier: cacti-temp.tar.gz


Hinweise

SNMP-Sicherheit — Im Beispiel steht public als Community-String und SNMPv2c. Für ein Heimnetz reicht das. In einem produktiven Umfeld sollte man SNMPv3 mit Authentifizierung verwenden und den Zugriff per Firewall auf den Cacti-Server beschränken.

Alternative zu Cacti — Wer kein Cacti hat: Grafana mit InfluxDB oder Prometheus wäre die modernere Alternative. Der SNMP-Weg funktioniert dort genauso, alternativ kann man die Werte auch direkt per Telegraf oder einen kleinen Python-Exporter einliefern.

Warum kein wiringPi mehr? — Gordon Henderson hat das wiringPi-Repository 2019 offline genommen. Es gibt Forks auf GitHub, die auf neueren Pi-Modellen funktionieren, aber offiziell wird die Bibliothek nicht mehr gepflegt. Für neue Projekte ist Python mit der Adafruit-Bibliothek der bessere Weg — weniger Kompilieraufwand, bessere Fehlerbehandlung und aktive Wartung.


Der Sensor da draußen

Der Sensor muss nach draußen, vor Wasser geschützt sein, aber nicht hermetisch versiegelt — sonst kann er keine Luftfeuchtigkeit messen.

Meine Lösung: Ein PVC-Rohr, den Sensor dort mit etwas Silikon eingeklebt, eine Seite mit Deckel verschlossen. So kann kein Wasser an den Sensor laufen, Luft kommt aber noch ran. Angebracht am Pfosten der Satellitenschüssel — dort oben steht die Luft selten, es kommt niemand ran und es fällt nicht auf.

Das Ding hängt dort seit 2014. Funktioniert.


Siehe auch: Raspberry Pi als Konsolenserver, Stromverbrauch messen mit Raspberry Pi, Eltako DSZ12E und Cacti

Fragen? Einfach melden.

Stromverbrauch messen mit Raspberry Pi, Eltako DSZ12E und Cacti

Im Keller hing ein alter Ferraris-Zähler mit Drehscheibe. Zählt brav für den Energieversorger, liefert aber keine Daten. Ich wollte den Stromverbrauch im Haus grafisch auswerten, am besten mit Cacti. Dafür braucht man einen Zähler mit S0-Schnittstelle.

Der Zähler

Mein Energieversorger wollte für einen digitalen Zähler Fantasiepreise. Also selbst kaufen. Die Wahl fiel auf den Eltako DSZ12E-3x80A, einen Drehstromzähler mit S0-Ausgang. 3 × 80 A reicht für den normalen Hausgebrauch locker. Kostenpunkt damals rund 75 Euro.

Wichtig: Dieser Zähler ersetzt nicht den offiziellen Zähler des Versorgers. Er wird dahinter eingebaut. Das darf nicht jeder machen. Wer nicht weiß ob er es darf, darf es nicht. Ein Elektriker braucht dafür eine halbe bis eine Stunde, mit Anfahrt kommt man auf 100 bis 150 Euro.

Zur Deutlichkeit: Bei 3×80 A reden wir über 400 V Drehstrom. Ein Fehlkontakt ist lebensgefährlich. Selbst einbauen ist keine Option, auch wenn es auf YouTube einfach aussieht. Wer ohne Elektrikerschein bastelt, riskiert nicht nur sich selbst, sondern auch den Versicherungsschutz im Haus. Nebenbei: Für die eigene Auswertung ist der Zähler prima, für Abrechnungszwecke wie WG oder Mieter gelten eichrechtliche Anforderungen, die man vorher klären sollte.

S0-Schnittstelle und Raspberry Pi

Die S0-Schnittstelle ist ein potentialfreier Impulskontakt. Pro verbrauchter Kilowattstunde gibt der Zähler eine bestimmte Anzahl Impulse aus, beim DSZ12E sind es 2000 Impulse pro kWh. Der Raspberry Pi zählt diese Impulse über einen GPIO-Pin.

Die Verkabelung ist simpel: S0-Ausgang des Zählers an einen GPIO-Pin und GND des Raspberry Pi. Ein Pullup-Widerstand sorgt dafür, dass der Pin sauber zwischen High und Low wechselt. Bei jedem Impuls wird ein Zähler hochgezählt und der aktuelle Verbrauch berechnet.

Sauberer: Optokoppler statt direkter GPIO-Anschluss

In der Praxis funktioniert der direkte Anschluss meistens, spezifikationsgerecht ist er aber nicht. Die S0-Schnittstelle ist in DIN 43864 für 27 V DC Nennspannung und 10 bis 27 mA Schleifenstrom definiert. Wer es sauber haben will, baut einen Optokoppler dazwischen, zum Beispiel einen PC817. Die S0-Leitung versorgt man mit 5 oder 12 V über einen Vorwiderstand, der Ausgang des Optokopplers schaltet galvanisch getrennt den GPIO-Pin. Vorteil: kein Potentialproblem, keine Spec-Verletzung, und die Flanken sind sauber genug, dass man auf Software-Entprellung verzichten kann.

Die Auswertung habe ich nach dieser Anleitung aufgebaut: Stromzähler mit S0-Schnittstelle vom Raspberry Pi auswerten (Johannes Weber). Ein Python-Script zählt die Impulse und stellt die Werte per SNMP bereit.

Cacti-Graphen

Cacti fragt den Raspberry Pi per SNMP ab und zeichnet die Graphen. Neben dem aktuellen Verbrauch in Watt lassen sich mit zusätzlichen SNMP-Abfragen auch Tagesverbrauch, Wochenverbrauch und Monatsverbrauch darstellen. Die Berechnung macht das Script auf dem Pi, Cacti muss nur die fertigen Werte abgreifen und zeichnen.

Das Ergebnis: Auf einen Blick sieht man wann die Waschmaschine lief, wann der Herd an war und wie hoch die Grundlast nachts ist. Verbrauchsspitzen fallen sofort auf.

Update 2026: was heute anders wäre

Der Beitrag ist von 2014, und zwölf Jahre sind in der Energiemesstechnik eine halbe Ewigkeit. Inzwischen läuft in Deutschland der Pflichtrollout für intelligente Messsysteme (iMSys) nach dem Messstellenbetriebsgesetz. Wer ein Smart-Meter-Gateway (SMGW) hat, bekommt die Daten ohnehin digital, und über die HAN-Schnittstelle (Controllable Local Systems) lassen sich Verbräuche direkt abholen. Ist der alte Ferraris-Zähler hingegen noch drin, ist ein IR-Lesekopf auf der D0-Schnittstelle (SML-Protokoll) der Weg der Wahl, gut gepflegt im Volkszähler-Projekt oder in Kombination mit Tasmota. Fertige WLAN-Messmodule wie das Shelly 3EM oder Pro 3EM liefern Drehstrommessung direkt per MQTT, ganz ohne GPIO-Basteln. Als Backend wäre heute eher Home Assistant mit dem Energy-Dashboard oder Grafana plus InfluxDB gesetzt, Cacti hat seinen Charme, aber die Zeit der Graphen mit RRDtool ist in der HomeLab-Ecke vorbei.

Siehe auch: Temperatur und Luftfeuchtigkeit mit DHT22 am Raspberry Pi messen

Fragen zum Aufbau? Einfach melden.

Raspberry Pi als FM-Radiosender mit PiFM

Kinder sind etwas Wunderbares, so auch meine beiden. Die Größere hört zum Einschlafen gerne ein Hörspiel, beim Spielen hören und tanzen beide zu Kindermusik. Klar haben sie eine kleine Kompaktanlage im Kinderzimmer. Aber Kinderhörspiele gibt es kaum noch auf Kassette — fast nur noch auf CD oder als MP3. Keine Ahnung wie es bei euren Kindern ist, bei uns leben CDs nicht sonderlich lange. Ich grille in der Woche 3 bis 4 Stück. Noch schlimmer: Die Lieblings-CD trifft nach 38 Minuten auf einen Kratzer und macht nur noch unverständlichen Lärm.

MPD als CD-Ersatz

Ich hatte noch einen Raspberry Pi herumliegen. Den zusammen mit dem Music Player Daemon (MPD) als Musikspieler nutzen — die gekauften MP3-Alben liegen eh auf dem Server und lassen sich per NFS mounten. WLAN ist im ganzen Haus, und wir Eltern steuern alles per Android-App. Das Projekt war in anderthalb Stunden erledigt, getestet und von den Kindern abgenommen.

Seitdem fristet der CD-Spieler ein ungenutztes Leben. Nur das Radio läuft hin und wieder am Abend. Radio… irgendwo hatte ich doch im Zusammenhang mit dem Raspberry Pi etwas zu FM-Radio gelesen.

PiFM — FM-Sender über GPIO

PiFM (mittlerweile weiterentwickelt als rpitx) nutzt den GPIO-Pin 4 des Raspberry Pi, um ein FM-Signal zu erzeugen. Eine ca. 15 cm lange Antenne — ein Stück Draht — reicht. Der Pi generiert per DMA ein Taktsignal auf dem GPIO, das direkt als FM-moduliertes HF-Signal abstrahlt. Kein zusätzlicher Sender-IC nötig.

Eine WAV-Datei auf 90,0 MHz senden:

sudo ./pifm musik.wav 90.0

Einen Web-Stream — zum Beispiel einen Kinderradiosender — per sox umwandeln und direkt an PiFM pipen:

sox -t mp3 http://stream-url -t wav -r 22050 -c 1 - | sudo ./pifm - 90.0

MPD kann auch streamen — so lässt sich die gesamte Musikbibliothek per FM ins Kinderzimmerradio schicken.

Verstärkerschaltung

Das reine GPIO-Signal ist schwach. Um es etwas zu verstärken und sauber zu filtern, habe ich eine kleine Schaltung gebaut — den handgezeichneten Schaltplan mit Bauteileliste findet ihr in den Bildern unten. Mit der Schaltung reicht das Signal für das ganze Haus inklusive Garten.

Oberwellen: der eigentliche Grund für den Filter

Der GPIO liefert kein sauberes Sinussignal, sondern ein Rechteck. Ein Rechteck hat neben der Grundfrequenz eine lange Reihe Oberwellen bei 2f, 3f, 4f und so weiter, und durch die DMA-getaktete Frequenzmodulation entstehen zusätzlich Splatter-Anteile im Nachbarkanal. Bei 90 MHz Grundfrequenz heißt das: 180 MHz, 270 MHz, 360 MHz und höher. Mindestens eine dieser Harmonischen liegt mit Sicherheit in einem Band, das belegt oder sicherheitskritisch ist. Ohne Tiefpass strahlt PiFM also nicht nur auf der gewählten UKW-Frequenz, sondern breitbandig quer durch VHF und UHF. Der Filter in der Verstärkerschaltung ist deshalb nicht Kür, sondern der einzige Grund, warum man keinen Flugfunk, Amateurfunk oder Rundfunk stört. Wer PiFM ohne Filter betreibt, wird im Zweifel nicht nur von der Bundesnetzagentur, sondern auch von jedem Amateurfunker im Umkreis sehr schnell gefunden.

Rechtliches

In Deutschland darf man im FM-Band senden — aber nur mit extrem geringer Leistung. Die Bundesnetzagentur erlaubt ohne Genehmigung Sendeanlagen mit wenigen Nanowatt, was in der Praxis etwa einen Meter Reichweite ergibt. Der Raspberry Pi mit Verstärkerschaltung überschreitet das deutlich. Dieses Projekt bleibt deshalb ein einmaliger Versuchsaufbau.

Schade eigentlich — der WDR-Kinderkanal MausLive (ehemals KiRaKa) ist nur per DAB+ oder Internet-Stream zu empfangen. Per PiFM könnte man den Stream als FM-Signal im Haus verteilen und die Kinder könnten überall mit einem einfachen Radio hören. Aber so ist die Rechtslage.

Update 2026: zeitgemäße Alternativen

Der Beitrag ist von 2014. Heute wäre mein Weg ein anderer: Bluetooth-Audio direkt ans Kinderzimmerradio (falls es Bluetooth kann) oder ein kleiner Multi-Room-Audio-Setup mit Snapcast, squeezelite oder einem fertigen Smart Speaker. DLNA/UPnP und AirPlay decken den Rest ab, alles legal und ohne Frequenz-Diskussion. rpitx gibt es übrigens immer noch, inzwischen mit deutlich mehr Modi (SSB, FSK, LoRa, sogar DVB-T), und ist als Experimentierplattform für die SDR-Ecke weiterhin spannend. Nur eben nichts, was man offen im Wohnzimmer laufen lassen sollte.


Bilder vom Projekt — Platine, Schaltplan mit Bauteileliste und das Ergebnis auf dem Radio:

Fragen? Einfach melden.

ownCloud

Veraltet: ownCloud wird nicht mehr aktiv weiterentwickelt. Der Nachfolger ist Nextcloud.

Zur kurzen Beschreibung von ownCloud greife ich jetzt einfach mal ganz faul auf den ersten Absatz aus dem passenden Wikipediaartikel zurück:

### schnipp ###

ownCloud ist eine Software-Suite, die einen ortsunabhängigen Speicherbereich für Daten zur Verfügung stellt. Das Projekt wurde im Januar 2010 vom KDE-Entwickler Frank Karlitschek ins Leben gerufen, um eine freie Alternative zu kommerziellen Cloud-Anbietern zu schaffen. Im Gegensatz zu kommerziellen Speicherdiensten kann ownCloud auf einem privaten Server ohne Zusatzkosten installiert werden. Somit können gerade bei sensiblen Daten die Bedenken gegenüber einer Datenweitergabe und der damit einhergehenden Abgabe der Kontrolle über die Daten zerstreut werden.

Als Grundlage setzt das Projekt auf PHP und einer angebundenen SQLite-, MySQL- oder PostgreSQL-Datenbank. Die ownCloud kann über eine Weboberfläche bedient werden und ist dadurch nicht an ein bestimmtes Betriebssystem gebunden. Aber auch andere Anwendungen, wie beispielsweise Dateimanager oder Groupwares, können die ownCloud über eine Schnittstelle ansprechen und Dateien und Daten lokal bereitstellen.

### schnapp ###

Im Grunde lässt sich ownCloud also mit recht kleinen Grundvoraussetzungen ownCloud in Betrieb nehmen. Selbst die einfache Installation ist nicht weiter aufwendig. Natürlich hängt es immer etwas davon ab, welche Systeme man noch anbinden möchte und wie groß es am Ende wirklich werden soll.

Inzwischen gibt es für alle möglichen Clients auch Software, welche sie an ownCloud anbindet. Evolution, Thunderbird, Kmail (und Anhang), Sync-Clients für Windows/Linux/… Man kann einfach auf seine Dateien per WebDAV zugreifen usw. usw…

Man hat also seine Daten wirklich unter der eigenen Kontrolle und würfelt sie nicht irgendwo hin. Dabei ist die nötige Basis so gering dass es alles sogar über einen Raspberry Pi läuft.

OK… Es hat natürlich einen Haken. Denn es ist wie immer, wenn man selbst dafür verantwortlich ist, dann ist man auch selbst dafür verantwortlich. Alles ist dann nur so sicher wie man es selbst abgesichert hat, sich um die Patchstände kümmert und die Konfiguration vorgenommen hat.

Denn noch bietet man natürlich selbst in der Regel ein nicht ganz so attraktives Ziel wie ein großer Clouddienstleister (ich mag das Wort cloud nicht…).

Siehe auch: ownCloud und Kalender / Kontakte synchronisieren, ownCloud News-App, ownCloud und Mozilla-Sync, Davdroid ownCloud sync

Fragen? Einfach melden.

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑