GitHub
Skizzepackages/p2p/src

P2P

@ralphschuler/p2p

Verbindet lokale Peer-Discovery, einen gerahmten Transport und authentifizierte Sessions zu einem Peer-to-Peer-System.

peer-to-peerframingdiscovery

01 · Problem

Wofür braucht man das?

Peers müssen sich finden, eine stabile Identität aushandeln, Nachrichten begrenzen und Vertraulichkeit sowie Authentizität über eine Session sicherstellen.

02 · Denkmodell

Das mentale Modell

Discovery verrät nur eine Adresse. Ein Handshake bestätigt Identität und Fähigkeiten; danach transportieren längengerahmte, sequenzierte Nachrichten über eine etablierte sichere Session.

Im Repository

P2P soll mDNS, TCP und RSA verbinden, kompiliert aber nicht. Signaturen werden nicht übertragen, Framing fehlt, Peer-IDs sind inkonsistent und das selbstgebaute Kryptoprotokoll ist unvollständig.

03 · Kontrollfluss

Was passiert in welcher Reihenfolge?

  1. Per mDNS nur nodeId, Host, Port und öffentlichen Fingerprint ankündigen.
  2. Transport verbinden und Peer über TLS oder ein geprüftes Handshake-Protokoll authentifizieren.
  3. Stabile Node-IDs und Protokollversionen austauschen; Self- und Duplicate-Verbindungen ablehnen.
  4. Nachrichten mit Länge, Typ und Sequenz framen und harte Maximalgrößen erzwingen.
  5. Backpressure, Heartbeat, Reconnect und vollständigen Shutdown implementieren.

04 · Bauteile

Die entscheidenden Verträge

P2P Beabsichtigter Coordinator für Server, mDNS-Discovery und Peer-Lifecycle.
Peer EventEmitter um einen TCP-Socket mit send und Datenverarbeitung.
KeyPairEncryption Soll RSA signieren und verschlüsseln, ist aber unvollständig und nicht importfähig.
PeerInfo Adress- und Identitätsdaten eines entdeckten Peers.

05 · Build it yourself

Selbst implementieren

Baue kein eigenes Kryptoprotokoll. Beginne mit klarem Framing und verwende eine etablierte sichere Transportschicht.

  1. Trenne Discovery, Transport, Session und Peer-Registry in eigene Ports.
  2. Nutze TLS oder Noise und binde den erwarteten Fingerprint an einen Trust Store.
  3. Erzwinge Frame-Limits, Sequenzen, Timeouts und idempotenten Lifecycle.
minimal.ts · unabhängig vom Package
type Frame = { type: number; sequence: number; payload: Uint8Array };

function encodeFrame(frame: Frame) {
  const body = encodeBody(frame);
  if (body.length > 1_048_576) throw new RangeError("Frame too large");
  const output = new Uint8Array(4 + body.length);
  new DataView(output.buffer).setUint32(0, body.length);
  output.set(body, 4);
  return output;
}

function acceptSequence(last: number, next: number) {
  if (next !== last + 1) throw new Error("Invalid sequence");
}

06 · Verifizieren

Was du testen solltest

  • TCP-Chunks mit halbem, genau einem und mehreren Frames werden korrekt reassembliert.
  • Zu große Frames, Replay-Sequenzen und falsche Peer-Fingerprints werden vor Payload-Verarbeitung abgelehnt.
  • Disconnect, Timeout und destroy räumen Server, Sockets, Timer und Discovery vollständig auf.

07 · Grenzen

Kompromisse und Stolperfallen

  • mDNS entdeckt nur Peers im lokalen Netz; Internet-P2P braucht Rendezvous, NAT-Traversal oder Relay.
  • Direct RSA encryption eignet sich nicht für beliebige Payloads; Sessions verwenden symmetrische AEAD-Keys.
  • Discovery-Metadaten sind ohne nachfolgenden Trust-Check nicht vertrauenswürdig.
Wichtig

Kryptografie, Framing und Lifecycle sind Sicherheitsgrenzen. Der aktuelle Source ist eine unvollständige Idee und darf nicht als sicheres Protokoll eingesetzt werden.

08 · Weiterdenken

Quellcode und Nachbarn

Originalcode auf GitHub ansehen