Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| retry-schleife [30.07.2026 08:20] – angelegt maria | retry-schleife [29.09.2026 23:57] (aktuell) – polly | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| ====== Der Grossteil des Request-Traffics ist eine Retry-Schleife, | ====== Der Grossteil des Request-Traffics ist eine Retry-Schleife, | ||
| - | *English version: [[2026-07-29-request-response-traffic-analysis.en.md]]* | + | Aktuelle Statistik: [[https:// |
| **Datum:** 2026-07-29 | **Datum:** 2026-07-29 | ||
| - | == Kurzfassung == | + | ===== Kurzfassung |
| - | Request/ | + | Request/ |
| haben untersucht, woher sie kommen — in der Erwartung, Missbrauch zu finden. Es | haben untersucht, woher sie kommen — in der Erwartung, Missbrauch zu finden. Es | ||
| - | ist kein Missbrauch. Es ist ein ''' | + | ist kein Missbrauch. Es ist ein **Fehlermuster, |
| - | teilt''' | + | teilt**: |
| - | ''' | + | **Eine Abfrage, die nie beantwortet wird, flutet das gesamte Netz — für immer, |
| - | und der Sender kann es nicht bemerken.''' | + | und der Sender kann es nicht bemerken.** |
| - | Zwischen | + | Zwischen |
| entfallen auf FLOOD-Requests, | entfallen auf FLOOD-Requests, | ||
| wiederholen sich seit über einer Woche alle 39 Sekunden, Tag und Nacht. | wiederholen sich seit über einer Woche alle 39 Sekunden, Tag und Nacht. | ||
| - | Wer ein Script betreibt, das Repeater abfragt: | + | Wer ein Script betreibt, das Repeater abfragt: |
| - | wahrscheinlich von deinem Script''' | + | wahrscheinlich von deinem Script**, und der Fix sind drei Zeilen ([[retry-schleife# |
| - | == Datenbasis == | + | ===== Datenbasis |
| - | | | | | + | ^ Kennzahl ^ Wert ^ |
| | Zeitraum | 2026-07-22 – 2026-07-28 (6 Tage) | | | Zeitraum | 2026-07-22 – 2026-07-28 (6 Tage) | | ||
| | Aktive Observer | 367 | | | Aktive Observer | 367 | | ||
| Zeile 33: | Zeile 33: | ||
| | davon Request/ | | davon Request/ | ||
| - | ''' | + | **Messgrösse |
| - | gehört haben. Das misst die ''' | + | gehört haben. Das misst die **Verbreitung** eines Pakets im Netz, nicht die |
| Sendezeit. Im Fenster wurden 30 MB einmal gesendet und dabei als 688 MB über | Sendezeit. Im Fenster wurden 30 MB einmal gesendet und dabei als 688 MB über | ||
| alle Empfänger gehört — Faktor 23. Echte Airtime lässt sich daraus nicht | alle Empfänger gehört — Faktor 23. Echte Airtime lässt sich daraus nicht | ||
| Zeile 40: | Zeile 40: | ||
| Observer hören. | Observer hören. | ||
| - | == 1. Warum unbeantwortete Abfragen dauerhaft teuer sind == | + | ===== 1. Warum unbeantwortete Abfragen dauerhaft teuer sind ===== |
| ^ Route ^ Pakete ^ Sichtungen ^ Ø Empfänger pro Paket ^ | ^ Route ^ Pakete ^ Sichtungen ^ Ø Empfänger pro Paket ^ | ||
| - | | FLOOD | 48 173 | 2 302 805 | ''' | + | | FLOOD | 48 173 | 2 302 805 | **47,8** | |
| | TRANSPORT_FLOOD | 14 663 | 973 176 | 66,4 | | | TRANSPORT_FLOOD | 14 663 | 973 176 | 66,4 | | ||
| - | | DIRECT | 40 400 | 69 067 | ''' | + | | DIRECT | 40 400 | 69 067 | **1,71** | |
| Ein FLOOD-Request erreicht ~28× so viele Funkgeräte wie ein DIRECT-Request. | Ein FLOOD-Request erreicht ~28× so viele Funkgeräte wie ein DIRECT-Request. | ||
| MeshCore löst das bereits, und der Mechanismus funktioniert: | MeshCore löst das bereits, und der Mechanismus funktioniert: | ||
| - | geht als FLOOD raus. ''' | + | geht als FLOOD raus. **Die Antwort bringt den Rückweg mit.** Ab dann pollt der |
| Client DIRECT, und die Kosten brechen ein. Gemessen an einem realen Paar | Client DIRECT, und die Kosten brechen ein. Gemessen an einem realen Paar | ||
| - | (``e4``→``24``): | + | ('' |
| ^ Tag ^ Requests ^ davon FLOOD ^ | ^ Tag ^ Requests ^ davon FLOOD ^ | ||
| | 07-23 | 96 | 55 % | | | 07-23 | 96 | 55 % | | ||
| - | | 07-24 | 473 | ''' | + | | 07-24 | 473 | **4 %** | |
| - | | 07-26 | 224 | ''' | + | | 07-26 | 224 | **5 %** | |
| - | Und hier der Fehlerfall: | + | Und hier der Fehlerfall: |
| Antwort, kein Pfad. Kein Pfad, und der nächste Request geht wieder als FLOOD | Antwort, kein Pfad. Kein Pfad, und der nächste Request geht wieder als FLOOD | ||
| raus. Für immer. | raus. Für immer. | ||
| Zeile 68: | Zeile 68: | ||
| gesendet. | gesendet. | ||
| - | == 2. Die Aufteilung der Request-Last == | + | ===== 2. Die Aufteilung der Request-Last |
| Kriterium A — pro (Sender→Ziel)-Paar, | Kriterium A — pro (Sender→Ziel)-Paar, | ||
| ^ Kategorie ^ Paare ^ Requests ^ Sichtungen ^ Anteil ^ Empfangs-Bytes ^ | ^ Kategorie ^ Paare ^ Requests ^ Sichtungen ^ Anteil ^ Empfangs-Bytes ^ | ||
| - | | ''' | + | | **FLOOD, unbeantwortet — Verschwendung** | 4 088 | 57 184 | 2 902 094 | **88,1 %** | **92 MB** | |
| | FLOOD, wird beantwortet | 579 | 7 528 | 313 377 | 9,5 % | 10,0 MB | | | FLOOD, wird beantwortet | 579 | 7 528 | 313 377 | 9,5 % | 10,0 MB | | ||
| | DIRECT (Pfad gelernt) — günstig | 927 | 37 895 | 78 816 | 2,4 % | 1,9 MB | | | DIRECT (Pfad gelernt) — günstig | 927 | 37 895 | 78 816 | 2,4 % | 1,9 MB | | ||
| Zeile 80: | Zeile 80: | ||
| ^ Kategorie ^ Pakete ^ Sichtungen ^ Anteil ^ | ^ Kategorie ^ Pakete ^ Sichtungen ^ Anteil ^ | ||
| - | | FLOOD, keine Antwort | 60 695 | 3 104 090 | ''' | + | | FLOOD, keine Antwort | 60 695 | 3 104 090 | **94,2 %** | |
| | FLOOD, Antwort binnen 10 min | 1 488 | 121 096 | 3,7 % | | | FLOOD, Antwort binnen 10 min | 1 488 | 121 096 | 3,7 % | | ||
| | DIRECT | 40 424 | 69 101 | 2,1 % | | | DIRECT | 40 424 | 69 101 | 2,1 % | | ||
| Zeile 86: | Zeile 86: | ||
| Beide Partitionen summieren exakt auf 3 294 287 Sichtungen — die Kontrollsumme | Beide Partitionen summieren exakt auf 3 294 287 Sichtungen — die Kontrollsumme | ||
| aller ausgewerteten Request-Sichtungen. Kriterium A ist das konservativere, | aller ausgewerteten Request-Sichtungen. Kriterium A ist das konservativere, | ||
| - | dort ein Paar oberhalb der Schwelle | + | dort ein Paar oberhalb der Schwelle |
| - | gutgeschrieben bekommt. Belastbare Aussage: | + | gutgeschrieben bekommt. Belastbare Aussage: |
| - | ''' | + | **Die DIRECT-Zeile ist die gute Nachricht:** sauber konfiguriertes Polling ist |
| praktisch gratis — 37 895 Requests kosten zusammen 2,4 % der Last. Es geht | praktisch gratis — 37 895 Requests kosten zusammen 2,4 % der Last. Es geht | ||
| nicht darum, weniger zu pollen. | nicht darum, weniger zu pollen. | ||
| - | == 3. Top-Verursacher (FLOOD, ohne Antwort) == | + | ===== 3. Top-Verursacher (FLOOD, ohne Antwort) |
| ^ Sender ^ Ziel ^ Requests ^ Antworten ^ Sichtungen ^ Req/Tag ^ | ^ Sender ^ Ziel ^ Requests ^ Antworten ^ Sichtungen ^ Req/Tag ^ | ||
| - | | ``27`` | ``f1`` | 5 040 | ''' | + | | '' |
| - | | ``f4`` | ``19`` | 1 596 | 44 | 186 252 | 266 | | + | | '' |
| - | | ``bb`` | ``30`` | 2 007 | ''' | + | | '' |
| - | | ``5d`` | ``98`` | 1 361 | ''' | + | | '' |
| - | | ``7f`` | ``74`` | 699 | ''' | + | | '' |
| - | | ``7f`` | ``b5`` | 678 | ''' | + | | '' |
| - | | ``13`` | ``89`` | 825 | 25 | 39 419 | 138 | | + | | '' |
| - | | ``10`` | ``3e`` | 1 037 | ''' | + | | '' |
| - | | ``69`` | ``1f`` | 1 053 | ''' | + | | '' |
| - | ``27``→``f1`` allein ist ''' | + | '' |
| allen 7 Tagen, am 27.07. 2 238 Requests (alle 39 s), auf dieser Strecke keine | allen 7 Tagen, am 27.07. 2 238 Requests (alle 39 s), auf dieser Strecke keine | ||
| einzige Antwort. | einzige Antwort. | ||
| - | ''' | + | **Der Defekt ist streckenspezifisch, |
| - | - ``f1`` sendet 114 Responses an 19 andere Peers, nur nie an ``27``. | + | - '' |
| - | - ``27`` empfängt Antworten: 186 von ``ae``, dazu einzelne von 19 weiteren Peers. | + | - '' |
| Naheliegende Erklärung: ein veralteter Schlüssel oder ein Kontakt, der auf einer | Naheliegende Erklärung: ein veralteter Schlüssel oder ein Kontakt, der auf einer | ||
| Seite entfernt wurde — die MAC-Prüfung schlägt fehl, es kommt keine Antwort. | Seite entfernt wurde — die MAC-Prüfung schlägt fehl, es kommt keine Antwort. | ||
| - | '' | + | //Das ist eine Vermutung — verifiziert ist nur, dass beide Seiten leben und nur |
| - | diese eine Strecke tot ist.'' | + | diese eine Strecke tot ist.// Genau so etwas fällt niemandem auf, weil es |
| nirgends gemeldet wird. | nirgends gemeldet wird. | ||
| - | == 4. Das sind Scripts, keine Menschen == | + | ===== 4. Das sind Scripts, keine Menschen |
| - | ''' | + | **Alle 23 Top-Sender sind über alle 24 Stunden aktiv**, mit einem Nacht/ |
| - | Verhältnis von 0,82–1,64 — mehrere senden nachts | + | Verhältnis von 0,82–1,64 — mehrere senden nachts |
| Die Intervalle sind Cron-Takte (Median-Abstand pro Paar, Anteil innerhalb ±10 %): | Die Intervalle sind Cron-Takte (Median-Abstand pro Paar, Anteil innerhalb ±10 %): | ||
| ^ Sender→Ziel ^ Takt ^ Pakete ^ im Takt ^ | ^ Sender→Ziel ^ Takt ^ Pakete ^ im Takt ^ | ||
| - | | ``6e`` → 4 Ziele | ''' | + | | '' |
| - | | ``c1``→``3c`` | 3600,1 s | 102 | 94 % | | + | | '' |
| - | | ``2a`` → ''' | + | | '' |
| - | | ``52``→``96`` | 318 s (5 min) | 1 205 | 94 % | | + | | '' |
| - | | ``f6``→``c1`` | 1825 s (30 min) | 212 | 92 % | | + | | '' |
| - | | ``dd``→``79`` | 1827 s | 198 | 77 % | | + | | '' |
| - | | ``af``→``3e`` | 621 s (10 min) | 645 | 75 % | | + | | '' |
| - | | ``e4``→``cc`` | 631 s | 214 | 69 % | | + | | '' |
| - | ``2a`` arbeitet ''' | + | '' |
| sendet durchgehend DIRECT und kostet das Netz fast nichts — der Beweis, dass | sendet durchgehend DIRECT und kostet das Netz fast nichts — der Beweis, dass | ||
| Scannen an sich nicht das Problem ist. | Scannen an sich nicht das Problem ist. | ||
| - | == 5. Wo die Verursacher stehen == | + | ===== 5. Wo die Verursacher stehen |
| - | Der ``src_hash`` im Request ist nur ''' | + | Der '' |
| - | ``PATH_HASH_SIZE 1``; ``Mesh.cpp: | + | '' |
| - | in ``createDatagram``). Bei 8 940 bekannten Nodes teilen sich im Schnitt | + | in '' |
| - | Nodes''' | + | Nodes** einen Hash — **eine eindeutige Identifikation des Senders ist daraus |
| - | nicht möglich.''' | + | nicht möglich.** |
| - | Was '' | + | Was //möglich// ist: der erste Path-Hash eines Flood-Pakets ist der erste |
| weiterleitende Repeater, also ein Funknachbar des Senders. Wo dieser Pfad mit | weiterleitende Repeater, also ein Funknachbar des Senders. Wo dieser Pfad mit | ||
| - | 2–3 Byte Hashes läuft, ist er ''' | + | 2–3 Byte Hashes läuft, ist er **eindeutig auflösbar**: |
| ^ Sender ^ Heimat-Repeater ^ Standort ^ | ^ Sender ^ Heimat-Repeater ^ Standort ^ | ||
| - | | ``bb`` | ''' | + | | '' |
| - | | ``f4`` | ''' | + | | '' |
| - | | ``91`` | + | | '' |
| - | | ``db`` | ''' | + | | '' |
| - | | ``13`` | ''' | + | | '' |
| - | ''' | + | **Diese Repeater sind nicht die Ursache.** Ein Heimat-Repeater ist die erste |
| - | Station, die das Paket weitergeleitet hat — der pollende Client steht '' | + | Station, die das Paket weitergeleitet hat — der pollende Client steht //in seiner// |
| Funkreichweite. Das ist eine Nachbarschaftsbeziehung, | Funkreichweite. Das ist eine Nachbarschaftsbeziehung, | ||
| Die Betreiber sind nützliche Ansprechpartner, | Die Betreiber sind nützliche Ansprechpartner, | ||
| erkennen können, mehr nicht. | erkennen können, mehr nicht. | ||
| - | Für ``27`` (den grössten Verursacher) gibt es nur 1-Byte-Hops: | + | Für '' |
| - | beginnt mit ``ae`` (99,6 % konsistent — also ''' | + | beginnt mit '' |
| - | über zwei unabhängige Datenpfade belegt: erster Hop im Hinweg | + | über zwei unabhängige Datenpfade belegt: erster Hop im Hinweg |
| - | der ``27`` mit Abstand am häufigsten antwortet (186 Responses, mehr als alle | + | der '' |
| anderen zusammen). | anderen zusammen). | ||
| - | == 6. Kandidaten für die Ziel-Repeater == | + | ===== 6. Kandidaten für die Ziel-Repeater |
| - | Der ``dest_hash`` ist ebenfalls nur 1 Byte, aber die Ziele sind besser greifbar: | + | Der '' |
| - | Repeater senden Adverts, und ein Advert enthält den ''' | + | Repeater senden Adverts, und ein Advert enthält den **vollen** Pubkey. Damit |
| lassen sich Kandidaten filtern — plausibel ist nur, wer (a) Repeater oder | lassen sich Kandidaten filtern — plausibel ist nur, wer (a) Repeater oder | ||
| Roomserver ist und (b) dessen Advert in einer Zone gehört wird, in der auch die | Roomserver ist und (b) dessen Advert in einer Zone gehört wird, in der auch die | ||
| Requests des Senders ankommen (≥10 % der Sender-Sichtungen). | Requests des Senders ankommen (≥10 % der Sender-Sichtungen). | ||
| - | Das reduziert 21–38 Namensvetter auf ''' | + | Das reduziert 21–38 Namensvetter auf **0–6 echte Kandidaten**: |
| ^ Paar ^ Kandidaten ^ Namen ^ | ^ Paar ^ Kandidaten ^ Namen ^ | ||
| - | | ``bb``→``30`` | + | | '' |
| - | | ``7f``→``b5`` | 2 | Taacha🛩️Flugplatz, | + | | '' |
| - | | ``5d``→``98`` | 3 | D-NW-E-TripleZ, | + | | '' |
| - | | ``13``→``89`` | 3 | DLW_REP01_LS, | + | | '' |
| - | | ``7f``→``74`` | 3 | HAS Suedwest JO50EB, Heltec Repeater Algermi, nhf-li9urian | | + | | '' |
| - | | ``69``→``1f`` | 4 | DE-NW-ME-VBT10, | + | | '' |
| - | | ``f4``→``19`` | 5 | NL-ZH-LID-LaMo-RPT☀, | + | | '' |
| - | | ``27``→``f1`` | 6 | NL-OV-FIETS, | + | | '' |
| - | | ``10``→``3e`` | 16 | zu breit gestreut, nicht aussagekräftig | | + | | '' |
| Zwei Lesehilfen: | Zwei Lesehilfen: | ||
| - | - '' | + | * **'' |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | - Bei ``27``→``f1`` sind ''' | + | |
| - | | + | |
| - | | + | |
| - | ''' | + | **Das sind Kandidatenlisten, |
| Beweisführung zu; die Liste sagt „einer von diesen", | Beweisführung zu; die Liste sagt „einer von diesen", | ||
| - | == 7. Was im Script zu ändern ist == | + | ===== 7. Was im Script zu ändern ist ===== |
| - | Das Problem ist nicht das Pollen. Es ist das ''' | + | Das Problem ist nicht das Pollen. Es ist das **unbegrenzte Wiederholen im |
| - | vollen Takt gegen ein Ziel, das nie antwortet.''' | + | vollen Takt gegen ein Ziel, das nie antwortet.** |
| - | 1. ''' | + | - **Fehlschläge pro Ziel zählen.** Antwortet ein Ziel in den letzten N Versuchen nicht (N = 3 reicht), hör auf, es im Normaltakt abzufragen. |
| - | Versuchen nicht (N = 3 reicht), hör auf, es im Normaltakt abzufragen. | + | - **Exponentiell zurückfahren, |
| - | 2. ''' | + | - **Die tote Strecke protokollieren.** Hätte das Script gemeldet, dass es seit 5 000 Versuchen keine Antwort bekommt, wäre es in der ersten Woche aufgefallen. |
| - | täglich. Ein Ziel, das zurückkommt, | + | |
| - | ein totes kostet dann fast nichts. | + | |
| - | 3. ''' | + | |
| - | 5 000 Versuchen keine Antwort bekommt, wäre es in der ersten Woche | + | |
| - | aufgefallen. | + | |
| Wenn dein Client tagelang FLOOD an dasselbe Ziel schickt, ist genau das das | Wenn dein Client tagelang FLOOD an dasselbe Ziel schickt, ist genau das das | ||
| Zeile 226: | Zeile 215: | ||
| installiert. | installiert. | ||
| - | == 8. Was diese Daten nicht hergeben == | + | ===== 8. Was diese Daten nicht hergeben |
| - | * ''' | + | * **Wir können nicht feststellen, |
| - | Das Absenderfeld ist ein 1-Byte-Hash; | + | * **Inhalte bleiben verschlüsselt.** Request- und Response-Nutzlasten sind zwischen den beiden Endpunkten verschlüsselt (curve25519). Ein passiver Beobachter hat keinen der beiden Schlüssel. Diese Auswertung nutzt ausschliesslich Paket-Header und Zeitstempel — nie Nutzlast. |
| - | im Schnitt 35 davon denselben Wert. | + | * **Es geht um kein Fehlverhalten von Repeater-Betreibern.** Wir können oft sagen, welcher Repeater ein Paket zuerst weitergeleitet hat. Das verortet einen Client irgendwo in dessen Funkreichweite — mehr nicht. |
| - | * ''' | + | |
| - | zwischen den beiden Endpunkten verschlüsselt (curve25519). Ein passiver | + | |
| - | Beobachter hat keinen der beiden Schlüssel. Diese Auswertung nutzt | + | |
| - | ausschliesslich Paket-Header und Zeitstempel — nie Nutzlast. | + | |
| - | * ''' | + | |
| - | sagen, welcher Repeater ein Paket zuerst weitergeleitet hat. Das verortet | + | |
| - | einen Client irgendwo in dessen Funkreichweite — mehr nicht. | + | |
| - | == 9. Methodik und Grenzen == | + | ===== 9. Methodik und Grenzen |
| - | ''' | + | **Standortbestimmung** stützt sich ausschliesslich auf den ersten Path-Hash |
| über die 83,7 % der Sichtungen mit befülltem Pfad. Zwei Wege scheiden aus: | über die 83,7 % der Sichtungen mit befülltem Pfad. Zwei Wege scheiden aus: | ||
| - | * '' | + | * //0-Hop-Sichtungen// — '' |
| - | geliefert), echte 0-Hop-Sichtungen machen nur 0,1 % aus. Die Datenmenge trägt | + | * //Signalstärke// — die Observer mit dem stärksten Empfang von '' |
| - | keine Aussage, und NULL darf nicht als 0 gelesen werden. | + | |
| - | * '' | + | |
| - | (RSSI −19,3) sehen das Paket bei ``min_hops`` 4–5. Gemessen wird der letzte | + | |
| - | Repeater, nicht der Sender. | + | |
| - | ''' | + | **Antwortraten sind eine Untergrenze.** Responses laufen meist DIRECT |
| (Ø 1,36 Empfänger) und werden von den Observern schlecht gehört. Bei den | (Ø 1,36 Empfänger) und werden von den Observern schlecht gehört. Bei den | ||
| 0-Antworten-Paaren stützt sich der Befund deshalb nicht auf die Zählung allein, | 0-Antworten-Paaren stützt sich der Befund deshalb nicht auf die Zählung allein, | ||
| - | sondern auf den ''' | + | sondern auf den **100-%-FLOOD-Anteil über alle 7 Tage** — hätte der Sender je |
| eine Antwort erhalten, wäre er auf DIRECT umgestiegen. | eine Antwort erhalten, wäre er auf DIRECT umgestiegen. | ||
| - | ''' | + | **IATA-Codes** in diesem Dokument (RTM, AMS, BER, BWE, LEJ …) bezeichnen die |
| - | Zonen der '' | + | Zonen der //empfangenden Observer// — also wo ein Paket gehört wurde. Sie sind |
| nicht die Flood-Scope-Region des Pakets. | nicht die Flood-Scope-Region des Pakets. | ||
| Wer dieselbe Auswertung für seine eigene Region fahren möchte: die Methodik | Wer dieselbe Auswertung für seine eigene Region fahren möchte: die Methodik | ||
| teilen wir gern. | teilen wir gern. | ||