UDP-Tracker

Proposal 160
Geschlossen
Author zzz
Created 2022-01-03
Last Updated 2025-06-25
Target Version 0.9.67

Status

Genehmigt bei der Überprüfung am 2025-06-24. Die Spezifikation befindet sich unter UDP specification. Implementiert in zzzot 0.20.0-beta2. Implementiert in i2psnark ab API 0.9.67. Prüfen Sie die Dokumentation anderer Implementierungen für den Status.

Überblick

Dieser Vorschlag ist für die Implementierung von UDP-Trackern in I2P.

Change History

Ein vorläufiger Vorschlag für UDP-Tracker in I2P wurde im Mai 2014 auf unserer bittorrent spec page veröffentlicht; dies war vor unserem formalen Vorschlagsverfahren und wurde nie implementiert. Dieser Vorschlag wurde Anfang 2022 erstellt und vereinfacht die Version von 2014.

Da dieser Vorschlag auf antwortfähige Datagramme angewiesen ist, wurde er zurückgestellt, als wir Anfang 2023 mit der Arbeit am Datagram2-Vorschlag begannen. Dieser Vorschlag wurde im April 2025 genehmigt.

Die 2023-Version dieses Vorschlags spezifizierte zwei Modi, “Kompatibilität” und “schnell”. Weitere Analysen zeigten, dass der schnelle Modus unsicher wäre und auch ineffizient für Clients mit einer großen Anzahl von Torrents. Darüber hinaus gab BiglyBT eine Präferenz für den Kompatibilitätsmodus an. Dieser Modus wird einfacher zu implementieren sein für jeden tracker oder Client, der den Standard BEP 15 unterstützt.

Obwohl der Kompatibilitätsmodus auf Client-Seite komplexer von Grund auf zu implementieren ist, haben wir vorläufigen Code dafür, der 2023 begonnen wurde.

Daher ist die aktuelle Version hier weiter vereinfacht, um den Fast Mode zu entfernen und den Begriff “Kompatibilität” zu streichen. Die aktuelle Version wechselt zum neuen Datagram2-Format und fügt Verweise auf das UDP-Announce-Erweiterungsprotokoll BEP 41 hinzu.

Außerdem wird ein Verbindungs-ID-Lebensdauer-Feld zur Connect-Response hinzugefügt, um die Effizienzgewinne dieses Protokolls zu erweitern.

Motivation

Da die Benutzerbasis im Allgemeinen und die Anzahl der BitTorrent-Nutzer im Besonderen weiter wächst, müssen wir Tracker und Announces effizienter gestalten, damit Tracker nicht überlastet werden.

Bittorrent schlug UDP-Tracker in BEP 15 BEP 15 im Jahr 2008 vor, und die große Mehrheit der Tracker im Clearnet sind jetzt nur noch UDP-basiert.

Es ist schwierig, die Bandbreiteneinsparungen von Datagrammen gegenüber Streaming-Protokoll zu berechnen. Eine beantwortbare Anfrage hat etwa die gleiche Größe wie ein Streaming-SYN, aber die Nutzlast ist etwa 500 Bytes kleiner, da der HTTP-GET eine riesige 600-Byte-URL-Parameter-Zeichenkette hat. Die rohe Antwort ist viel kleiner als ein Streaming-SYN-ACK, was eine erhebliche Reduzierung für den ausgehenden Traffic eines Trackers bietet.

Zusätzlich sollte es implementierungsspezifische Speicherreduzierungen geben, da Datagramme deutlich weniger Arbeitsspeicher-Zustand erfordern als eine Streaming-Verbindung.

Post-Quantum-Verschlüsselung und -Signaturen, wie in /en/proposals/169-pq-crypto/ vorgesehen, werden den Overhead von verschlüsselten und signierten Strukturen erheblich erhöhen, einschließlich destinations, leasesets, streaming SYN und SYN ACK. Es ist wichtig, diesen Overhead wo möglich zu minimieren, bevor PQ-Kryptografie in I2P eingeführt wird.

Motivation

Dieser Vorschlag verwendet repliable datagram2, repliable datagram3 und raw datagrams, wie in /en/docs/spec/datagrams/ definiert. Datagram2 und Datagram3 sind neue Varianten von repliable datagrams, die in Vorschlag 163 /en/proposals/163-datagram2/ definiert sind. Datagram2 fügt Replay-Resistenz und Offline-Signatur-Unterstützung hinzu. Datagram3 ist kleiner als das alte Datagram-Format, aber ohne Authentifizierung.

BEP 15

Zur Referenz ist der in BEP 15 definierte Nachrichtenfluss wie folgt:

Client                        Tracker
    Connect Req. ------------->
      <-------------- Connect Resp.
    Announce Req. ------------->
      <-------------- Announce Resp.
    Announce Req. ------------->
      <-------------- Announce Resp.

Die Connect-Phase ist erforderlich, um IP-Adressen-Spoofing zu verhindern. Der Tracker gibt eine Verbindungs-ID zurück, die der Client in nachfolgenden Ankündigungen verwendet. Diese Verbindungs-ID läuft standardmäßig nach einer Minute beim Client und nach zwei Minuten beim Tracker ab.

I2P wird den gleichen Nachrichtenfluss wie BEP 15 verwenden, um die Übernahme in bestehende UDP-fähige Client-Codebasen zu erleichtern: aus Effizienzgründen und aus den unten diskutierten Sicherheitsgründen:

Client                        Tracker
    Connect Req. ------------->       (Repliable Datagram2)
      <-------------- Connect Resp.   (Raw)
    Announce Req. ------------->      (Repliable Datagram3)
      <-------------- Announce Resp.  (Raw)
    Announce Req. ------------->      (Repliable Datagram3)
      <-------------- Announce Resp.  (Raw)
             ...

Dies bietet potenziell erhebliche Bandbreiteneinsparungen gegenüber Streaming (TCP) Ankündigungen. Während das Datagram2 etwa die gleiche Größe wie ein Streaming SYN hat, ist die Raw-Antwort viel kleiner als das Streaming SYN ACK. Nachfolgende Anfragen verwenden Datagram3, und die nachfolgenden Antworten sind raw.

Die Announce-Anfragen sind Datagram3, sodass der Tracker keine große Zuordnungstabelle von Verbindungs-IDs zu Announce-Zielen oder Hashes verwalten muss. Stattdessen kann der Tracker Verbindungs-IDs kryptografisch aus dem Sender-Hash, dem aktuellen Zeitstempel (basierend auf einem bestimmten Intervall) und einem geheimen Wert generieren. Wenn eine Announce-Anfrage empfangen wird, validiert der Tracker die Verbindungs-ID und verwendet dann den Datagram3-Sender-Hash als Sendeziel.

Änderungshistorie

Für eine integrierte Anwendung (Router und Client in einem Prozess, zum Beispiel i2psnark und das ZzzOT Java-Plugin) oder für eine I2CP-basierte Anwendung (zum Beispiel BiglyBT) sollte es unkompliziert sein, den Streaming- und Datagramm-Verkehr separat zu implementieren und zu routen. ZzzOT und i2psnark werden voraussichtlich der erste Tracker und Client sein, die diesen Vorschlag umsetzen.

Nicht-integrierte Tracker und Clients werden im Folgenden besprochen.

Trackers

Es gibt vier bekannte I2P-Tracker-Implementierungen:

  • zzzot, ein integriertes Java router Plugin, läuft auf opentracker.dg2.i2p und mehreren anderen
  • tracker2.postman.i2p, läuft vermutlich hinter einem Java router und HTTP Server tunnel
  • Der alte C opentracker, portiert von zzz, mit auskommentierter UDP-Unterstützung
  • Der neue C opentracker, portiert von r4sas, läuft auf opentracker.r4sas.i2p und möglicherweise anderen, läuft vermutlich hinter einem i2pd router und HTTP Server tunnel

Für eine externe Tracker-Anwendung, die derzeit einen HTTP-Server-Tunnel verwendet, um Announce-Anfragen zu empfangen, könnte die Implementierung recht schwierig sein. Ein spezialisierter Tunnel könnte entwickelt werden, um Datagramme in lokale HTTP-Anfragen/Antworten zu übersetzen. Oder es könnte ein spezialisierter Tunnel entworfen werden, der sowohl HTTP-Anfragen als auch Datagramme verarbeitet und die Datagramme an den externen Prozess weiterleitet. Diese Designentscheidungen werden stark von den spezifischen Router- und Tracker-Implementierungen abhängen und liegen außerhalb des Umfangs dieses Vorschlags.

Clients

Externe SAM-basierte Torrent-Clients wie qbittorrent und andere libtorrent-basierte Clients würden SAM v3.3 benötigen, was von i2pd nicht unterstützt wird. Dies ist auch für DHT-Unterstützung erforderlich und komplex genug, dass kein bekannter SAM-Torrent-Client es implementiert hat. Keine SAM-basierten Implementierungen dieses Vorschlags werden in naher Zukunft erwartet.

Connection Lifetime

BEP 15 legt fest, dass die Verbindungs-ID beim Client nach einer Minute und beim Tracker nach zwei Minuten abläuft. Dies ist nicht konfigurierbar. Das begrenzt die potenziellen Effizienzgewinne, es sei denn, Clients würden Announces stapelweise verarbeiten, um alle innerhalb eines einminütigen Zeitfensters durchzuführen. i2psnark stapelt derzeit keine Announces; es verteilt sie, um Verkehrsspitzen zu vermeiden. Power-User betreiben Berichten zufolge tausende von Torrents gleichzeitig, und so viele Announces in eine Minute zu bündeln ist nicht realistisch.

Hier schlagen wir vor, die Connect-Antwort zu erweitern, um ein optionales Feld für die Verbindungslebensdauer hinzuzufügen. Der Standardwert, falls nicht vorhanden, beträgt eine Minute. Andernfalls soll die in Sekunden angegebene Lebensdauer vom Client verwendet werden, und der Tracker wird die Verbindungs-ID für eine weitere Minute aufrechterhalten.

Compatibility with BEP 15

Dieses Design behält die Kompatibilität mit BEP 15 so weit wie möglich bei, um die erforderlichen Änderungen in bestehenden Clients und Trackern zu begrenzen.

Die einzige erforderliche Änderung ist das Format der Peer-Informationen in der Announce-Antwort. Die Hinzufügung des Lifetime-Feldes in der Connect-Antwort ist nicht erforderlich, wird aber aus Effizienzgründen dringend empfohlen, wie oben erklärt.

BEP 15

Ein wichtiges Ziel eines UDP-Announce-Protokolls ist es, Address-Spoofing zu verhindern. Der Client muss tatsächlich existieren und ein echtes leaseset bündeln. Er muss über eingehende Tunnel verfügen, um die Connect Response zu empfangen. Diese Tunnel könnten Zero-Hop-Tunnel sein und sofort erstellt werden, aber das würde den Ersteller preisgeben. Dieses Protokoll erreicht dieses Ziel.

Tracker/Client-Unterstützung

  • Dieser Vorschlag unterstützt keine blinded destinations, kann aber entsprechend erweitert werden. Siehe unten.

Design

Protocols and Ports

Repliable Datagram2 verwendet I2CP-Protokoll 19; repliable Datagram3 verwendet I2CP-Protokoll 20; rohe Datagramme verwenden I2CP-Protokoll 18. Anfragen können Datagram2 oder Datagram3 sein. Antworten sind immer roh. Das ältere repliable datagram (“Datagram1”) Format mit I2CP-Protokoll 17 darf NICHT für Anfragen oder Antworten verwendet werden; diese müssen verworfen werden, falls sie auf den Anfrage-/Antwort-Ports empfangen werden. Beachten Sie, dass Datagram1-Protokoll 17 weiterhin für das DHT-Protokoll verwendet wird.

Anfragen verwenden den I2CP “to port” aus der Announce-URL; siehe unten. Der “from port” der Anfrage wird vom Client gewählt, sollte aber ungleich null sein und sich von den Ports unterscheiden, die von DHT verwendet werden, damit Antworten leicht klassifiziert werden können. Tracker sollten Anfragen ablehnen, die auf dem falschen Port empfangen werden.

Antworten verwenden den I2CP “to port” aus der Anfrage. Der “from port” der Anfrage ist der “to port” aus der Anfrage.

Announce URL

Das Format der Announce-URL ist in BEP 15 nicht spezifiziert, aber wie im Clearnet haben UDP-Announce-URLs die Form “udp://host:port/path”. Der Pfad wird ignoriert und kann leer sein, ist aber typischerweise “/announce” im Clearnet. Der :port-Teil sollte immer vorhanden sein, falls jedoch der “:port”-Teil weggelassen wird, verwende einen Standard-I2CP-Port von 6969, da dies der übliche Port im Clearnet ist. Es können auch CGI-Parameter &a=b&c=d angehängt werden, diese können verarbeitet und in der Announce-Anfrage bereitgestellt werden, siehe BEP 41. Falls keine Parameter oder Pfad vorhanden sind, kann der abschließende / ebenfalls weggelassen werden, wie in BEP 41 impliziert.

Verbindungslebensdauer

Alle Werte werden in Network-Byte-Reihenfolge (Big Endian) gesendet. Erwarten Sie nicht, dass Pakete genau eine bestimmte Größe haben. Zukünftige Erweiterungen könnten die Größe der Pakete erhöhen.

Connect Request

Client zum Tracker. 16 Bytes. Muss ein beantwortbares Datagram2 sein. Gleich wie in BEP 15. Keine Änderungen.

Offset  Size            Name            Value
  0       64-bit integer  protocol_id     0x41727101980 // magic constant
  8       32-bit integer  action          0 // connect
  12      32-bit integer  transaction_id

Connect Response

Tracker zu Client. 16 oder 18 Bytes. Muss raw sein. Gleich wie in BEP 15 außer wie unten angemerkt.

Offset  Size            Name            Value
  0       32-bit integer  action          0 // connect
  4       32-bit integer  transaction_id
  8       64-bit integer  connection_id
  16      16-bit integer  lifetime        optional  // Change from BEP 15

Die Antwort MUSS an den I2CP “to port” gesendet werden, der als “from port” der Anfrage empfangen wurde.

Das lifetime-Feld ist optional und gibt die connection_id Client-Lebensdauer in Sekunden an. Der Standardwert ist 60, und das Minimum, wenn angegeben, ist 60. Das Maximum ist 65535 oder etwa 18 Stunden. Der Tracker sollte die connection_id 60 Sekunden länger als die Client-Lebensdauer aufrechterhalten.

Announce Request

Client zu Tracker. Mindestens 98 Bytes. Muss ein beantwortbares Datagram3 sein. Gleich wie in BEP 15 außer wie unten vermerkt.

Die connection_id ist wie in der connect-Antwort empfangen.

Offset  Size            Name            Value
  0       64-bit integer  connection_id
  8       32-bit integer  action          1     // announce
  12      32-bit integer  transaction_id
  16      20-byte string  info_hash
  36      20-byte string  peer_id
  56      64-bit integer  downloaded
  64      64-bit integer  left
  72      64-bit integer  uploaded
  80      32-bit integer  event           0     // 0: none; 1: completed; 2: started; 3: stopped
  84      32-bit integer  IP address      0     // default
  88      32-bit integer  key
  92      32-bit integer  num_want        -1    // default
  96      16-bit integer  port
  98      varies          options     optional  // As specified in BEP 41

Änderungen von BEP 15:

  • key wird ignoriert
  • port wird wahrscheinlich ignoriert
  • Der options-Abschnitt, falls vorhanden, ist wie in BEP 41 definiert

Die Antwort MUSS an den I2CP “to port” gesendet werden, der als “from port” der Anfrage empfangen wurde. Verwenden Sie nicht den Port aus der Announce-Anfrage.

Announce Response

Tracker zu Client. Mindestens 20 Bytes. Muss raw sein. Gleich wie in BEP 15, außer wie unten angegeben.

Offset  Size            Name            Value
  0           32-bit integer  action          1 // announce
  4           32-bit integer  transaction_id
  8           32-bit integer  interval
  12          32-bit integer  leechers
  16          32-bit integer  seeders
  20   32 * n 32-byte hash    binary hashes     // Change from BEP 15
  ...                                           // Change from BEP 15

Änderungen von BEP 15:

  • Anstatt 6-Byte IPv4+Port oder 18-Byte IPv6+Port geben wir ein Vielfaches von 32-Byte “compact responses” mit den SHA-256 binären Peer-Hashes zurück. Wie bei TCP compact responses schließen wir keinen Port ein.

Die Antwort MUSS an den I2CP “to port” gesendet werden, der als “from port” der Anfrage empfangen wurde. Verwenden Sie nicht den Port aus der Announce-Anfrage.

I2P-Datagramme haben eine sehr große maximale Größe von etwa 64 KB; für eine zuverlässige Übertragung sollten jedoch Datagramme größer als 4 KB vermieden werden. Für Bandbreiteneffizienz sollten Tracker die maximalen Peers wahrscheinlich auf etwa 50 begrenzen, was etwa einem 1600-Byte-Paket vor Overhead auf verschiedenen Schichten entspricht und innerhalb eines Zwei-Tunnel-Nachrichten-Payload-Limits nach Fragmentierung liegen sollte.

Wie in BEP 15 ist keine Anzahl der folgenden Peer-Adressen (IP/Port für BEP 15, Hashes hier) enthalten. Obwohl in BEP 15 nicht vorgesehen, könnte eine End-of-Peers-Markierung aus lauter Nullen definiert werden, um anzuzeigen, dass die Peer-Informationen vollständig sind und einige Erweiterungsdaten folgen.

Damit eine Erweiterung in der Zukunft möglich ist, sollten Clients einen 32-Byte-Hash aus lauter Nullen und alle darauf folgenden Daten ignorieren. Tracker sollten Ankündigungen von einem Hash aus lauter Nullen ablehnen, obwohl dieser Hash bereits von Java-routern gesperrt wird.

Scrape

Scrape-Anfrage/Antwort aus BEP 15 ist nicht von diesem Vorschlag gefordert, kann aber bei Bedarf implementiert werden, keine Änderungen erforderlich. Der Client muss zuerst eine Verbindungs-ID erwerben. Die Scrape-Anfrage ist immer beantwortbares Datagram3. Die Scrape-Antwort ist immer raw.

Tracker

Tracker zu Client. 8 Bytes mindestens (wenn die Nachricht leer ist). Muss raw sein. Gleich wie in BEP 15. Keine Änderungen.

Offset  Size            Name            Value
  0       32-bit integer  action          3 // error
  4       32-bit integer  transaction_id
  8       string          message

Extensions

Extension-Bits oder ein Versionsfeld sind nicht enthalten. Clients und Tracker sollten nicht davon ausgehen, dass Pakete eine bestimmte Größe haben. Auf diese Weise können zusätzliche Felder hinzugefügt werden, ohne die Kompatibilität zu beeinträchtigen. Das in BEP 41 definierte Extensions-Format wird empfohlen, falls erforderlich.

Die Connect-Antwort wird modifiziert, um eine optionale Lebensdauer der Verbindungs-ID hinzuzufügen.

Wenn Unterstützung für blinded destinations erforderlich ist, können wir entweder die blinded 35-Byte-Adresse am Ende der Announce-Anfrage hinzufügen oder blinded Hashes in den Antworten anfordern, unter Verwendung des BEP 41 Formats (Parameter noch zu bestimmen). Der Satz von blinded 35-Byte-Peer-Adressen könnte am Ende der Announce-Antwort hinzugefügt werden, nach einem aus Nullen bestehenden 32-Byte-Hash.

Implementation guidelines

Siehe den Design-Abschnitt oben für eine Diskussion der Herausforderungen für nicht-integrierte, nicht-I2CP Clients und Tracker.

Kompatibilität mit BEP 15

Für einen gegebenen Tracker-Hostnamen sollte ein Client UDP gegenüber HTTP-URLs bevorzugen und sollte nicht an beide ankündigen.

Clients mit vorhandener BEP 15-Unterstützung sollten nur kleine Modifikationen benötigen.

Wenn ein Client DHT oder andere Datagramm-Protokolle unterstützt, sollte er wahrscheinlich einen anderen Port als “From-Port” für die Anfrage wählen, damit die Antworten an diesen Port zurückgesendet werden und nicht mit DHT-Nachrichten vermischt werden. Der Client empfängt nur rohe Datagramme als Antworten. Tracker senden niemals ein beantwortbares datagram2 an den Client.

Clients mit einer Standard-Liste von Opentrackers sollten die Liste aktualisieren, um UDP-URLs hinzuzufügen, nachdem bekannt ist, dass die bekannten Opentracker UDP unterstützen.

Clients können Retransmissionen von Anfragen implementieren oder auch nicht. Retransmissionen sollten, falls implementiert, ein anfängliches Timeout von mindestens 15 Sekunden verwenden und das Timeout für jede Retransmission verdoppeln (exponential backoff).

Clients müssen nach Erhalt einer Fehlerantwort zurückweichen.

Sicherheitsanalyse

Tracker mit vorhandener BEP 15 Unterstützung sollten nur kleine Änderungen benötigen. Dieser Vorschlag unterscheidet sich von dem Vorschlag aus 2014 dahingehend, dass der Tracker den Empfang von repliable datagram2 und datagram3 auf demselben Port unterstützen muss.

Um die Ressourcenanforderungen des Trackers zu minimieren, ist dieses Protokoll darauf ausgelegt, jegliche Anforderung zu eliminieren, dass der Tracker Zuordnungen von Client-Hashes zu Verbindungs-IDs für spätere Validierung speichert. Dies ist möglich, weil das Announce-Request-Paket ein antwortbares Datagram3-Paket ist, daher enthält es den Hash des Senders.

Eine empfohlene Implementierung ist:

  • Definiere die aktuelle Epoche als die aktuelle Zeit mit einer Auflösung der Verbindungslebensdauer, epoch = now / lifetime.
  • Definiere eine kryptographische Hash-Funktion H(secret, clienthash, epoch), die eine 8-Byte-Ausgabe erzeugt.
  • Generiere die zufällige Konstante secret, die für alle Verbindungen verwendet wird.
  • Für Connect-Antworten, generiere connection_id = H(secret, clienthash, epoch)
  • Für Announce-Anfragen, validiere die empfangene Verbindungs-ID in der aktuellen Epoche durch Überprüfung von connection_id == H(secret, clienthash, epoch) || connection_id == H(secret, clienthash, epoch - 1)

Migration

Vorhandene Clients unterstützen keine UDP-Announce-URLs und ignorieren sie.

Bestehende Tracker unterstützen nicht den Empfang von beantwortbaren oder rohen Datagrammen, diese werden verworfen.

Dieser Vorschlag ist vollständig optional. Weder Clients noch Tracker sind verpflichtet, ihn zu irgendeinem Zeitpunkt zu implementieren.

Rollout

Die ersten Implementierungen werden voraussichtlich in ZzzOT und i2psnark erfolgen. Sie werden zum Testen und Verifizieren dieses Vorschlags verwendet.

Andere Implementierungen werden nach Wunsch folgen, sobald die Tests und Überprüfungen abgeschlossen sind.