Files
iroh-forward/recherche-vpn-vs-p2p-netzwerk.md
skoandClaude Opus 4.8 ec7c96b092 Initial commit: iroh-forward TCP-over-Iroh forwarder
TCP-Forwarding über das Iroh-Netz (QUIC), adressiert per Public Key statt IP
(Umsetzung von Option B aus recherche-vpn-vs-p2p-netzwerk.md).

- server: nimmt Iroh-Verbindungen an, leitet QUIC-Streams an lokalen Port weiter
- client: lauscht lokal auf TCP, öffnet pro Verbindung einen QUIC-Stream zum Peer
- keygen: erzeugt Key-Datei und gibt EndpointId aus (Vorab-Verteilung)
- Allowlist (--allow) erlaubter Client-EndpointIds
- QUIC-Multiplexing, Reconnect mit Backoff, n0-Default-Relays + DNS-Discovery

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 14:25:15 +00:00

10 KiB
Raw Permalink Blame History

Recherche: VPN vs. P2P-Netzwerk


Teil 1 Vergleichende Übersicht

Klassifikation nach Betriebsmodell

Begriff Bedeutung
Netzwerk-Tunnel / Daemon Läuft als System-Dienst, erzeugt ein virtuelles Netzwerkinterface (tun/tap). Routing erfolgt OS-seitig.
Overlay-Netzwerk / Mesh Spannt ein virtuelles Netz über bestehende Infrastruktur auf. Jeder Knoten kennt (ggf. über Koordination) alle anderen.
App-Konnektivität / P2P-SDK Keine Netzwerkschnittstelle im OS. Konnektivität wird direkt in die Applikation eingebettet. Verbindung über kryptographische Schlüssel, nicht IPs.

Protokoll-Vergleich

Protokoll OSI-Schicht Betriebsmodell Koordination Verschlüsselung Besonderheiten
IPSec L3L4 (Netzwerk/Transport) Netzwerk-Tunnel / Kernel Manuell (IKEv2/IKEv1) oder PKI AES-GCM, ChaCha20 (via Suite B) Standard in Enterprise-Firewalls; komplex in Konfiguration; NAT-Probleme (NAT-T nötig); zwei Modi: Transport (L4-Header bleibt) und Tunnel (ganzes IP-Paket)
OpenVPN L4-Tunnel → präsentiert L2/L3 Netzwerk-Tunnel / Daemon CA-basiert (TLS-Zertifikate) TLS (OpenSSL/mbedTLS) TUN=L3, TAP=L2; läuft über UDP oder TCP; sehr verbreitet, aber langsam (Userspace); gut durch Firewalls tunnelbar (TCP:443)
WireGuard L3 (Netzwerk) Overlay-Netzwerk / Kernel-Modul Manuell (Pre-shared Keys + Public Keys) ChaCha20-Poly1305, Curve25519 Minimaler Kernel-Code (~4000 Zeilen); kein Handshake-Overhead im Betrieb; keine eingebaute Key-Discovery; bildet Basis für Tailscale/Netbird
Yggdrasil L3-Overlay (IPv6) Overlay-Netzwerk / Mesh-Daemon Selbstorganisierend (distributed routing) X25519 + Ed25519 Adresse = Hash des Public Key; kein zentraler Koordinator; schlechte Performance bei sehr großem Mesh; experimentell
Tailscale L3-Overlay Overlay-Netzwerk / Managed Mesh Zentraler Koordinations-Server (control plane) WireGuard darunter „Zero-config VPN"; DERP-Relay-Netz von Tailscale für NAT-Traversal; SaaS-Modell (oder Headscale self-hosted); gut für Team-Zugriff auf interne Dienste
Iroh L4L7 (QUIC/Application) App-Konnektivität / P2P-SDK Relay-Server (optional, betreibbar) TLS 1.3 über QUIC Kein Netzwerkinterface; Bibliothek (Rust, Python, Node.js, Swift, Kotlin); Adressierung über Public Keys; 95 % direkte Verbindungen; QUIC Multipath; kein Flottenmanagement eingebaut

L4 vs. L7 was bedeutet das hier konkret?

L4 (Transport):

  • IPSec Tunnel-Modus, OpenVPN, WireGuard und Tailscale operieren auf dieser Ebene oder darunter
  • Das OS erhält ein virtuelles Interface (wg0, tun0) und routet IP-Traffic darüber
  • Alle Anwendungen profitieren automatisch keine Code-Änderung nötig

L7 (Applikation):

  • Iroh arbeitet ausschließlich auf Applikationsebene
  • Die Anwendung selbst öffnet eine Iroh-Verbindung (QUIC-Session) zu einem Remote-Node via dessen Public Key
  • Kein System-Routing, kein Interface die App muss Iroh aktiv nutzen
  • Vergleichbar mit WebRTC: im Browser transparent, aber nur für eingebettete Anwendungen sinnvoll

Wann welches Modell?

Szenario Empfehlung
Site-to-Site zwischen Firewalls IPSec (native OPNsense-Support)
Remote-Access für Mitarbeiter Tailscale oder WireGuard
Self-hosted Mesh ohne SaaS WireGuard + Netbird/Headscale
P2P in eigener Anwendung gebaut Iroh
Gerät soll von überall erreichbar sein, ohne feste IP Iroh oder Tailscale
Experimentelles dezentrales Netz Yggdrasil

Teil 2 Iroh-Integration in bestehendes Setup

Ausgangslage

Internet
   │
[OPNsense] ──── Firewall / Router
   │
[Nginx] ──── Reverse Proxy (terminiert TLS, routet vhosts)
   │
[Serving Host] ──── Anwendungsserver (bisher feste IP / internes Netz)

Das Problem: Der Serving Host muss derzeit über ein geroutetes Netz (VPN oder direkt) erreichbar sein. Ziel ist es, ihn standortunabhängig zu betreiben ohne VPN-Konfiguration auf Netzwerkebene.


Iroh-Konzept: Dial by Key, not by IP

Jeder Iroh-Node hat ein Ed25519-Schlüsselpaar. Der Public Key ist die Adresse. Solange ein Node seinen Relay kennt (oder direkten QUIC-Hole-Punch schafft), ist er erreichbar unabhängig von Netzwerkposition, NAT oder dynamischer IP.


Verfügbare Iroh-Tools (ohne eigenen Code)

Tool Funktion Einsatzbarkeit
dumbpipe Bidirektionale Byte-Pipe zwischen zwei Iroh-Nodes (wie nc über Iroh) Ja als TCP-Tunnel mit socat kombinierbar
sendme Einmalige Dateiübertragung Nein kein dauerhafter Dienst
iroh-relay Eigener Relay-Server (DERP-ähnlich) Ja für selbst-gehostetes Setup

dumbpipe ist die einzige Komponente, die einen dauerhaften Kanal aufbauen kann aber sie überträgt einen Byte-Stream, kein TCP-Multiplexing. Für einen HTTP-Upstream im Nginx braucht man ein TCP-Forward-Setup.


Architektur-Optionen

Option A: dumbpipe + socat als TCP-Proxy-Kette

[Client]
   ↓ HTTPS
[Nginx] → upstream: localhost:8080
   ↓
socat LISTEN:8080 → dumbpipe connect <serving-host-key>
   ↓ [Iroh-Netz]
dumbpipe listen → socat → localhost:3000 (App)
[Serving Host]

Vorgehen:

# Serving Host
dumbpipe listen | socat - TCP:localhost:3000
# → gibt Node-Key aus, z.B. "ki2..."

# Nginx-Host
socat TCP-LISTEN:8080,fork EXEC:"dumbpipe connect ki2..."
# Nginx: proxy_pass http://127.0.0.1:8080;

Problem: dumbpipe ist eine Single-Connection-Pipe, kein TCP-Listener. Für parallele HTTP-Verbindungen müsste man pro Request eine neue Pipe öffnen oder ein Connection-Multiplexer vorschalten. Für produktiven Einsatz ungeeignet ohne eigenen Code.


Option B: Eigenes Iroh-TCP-Forward-Tool (empfohlen)

Ein kleines Tool in Rust oder Python (ca. 100200 Zeilen), das:

  • Serving Host: Iroh-Endpunkt öffnet, akzeptiert Verbindungen, leitet an lokalen Port weiter
  • Nginx-Host: Lauscht auf lokalem TCP-Port, öffnet pro Verbindung eine neue Iroh-QUIC-Stream

Iroh unterstützt nativ multiple Streams pro Connection (QUIC), daher skaliert das ohne Tricks.

[Nginx]
  proxy_pass http://127.0.0.1:9080
       ↓
[iroh-forward-client] lauscht :9080, öffnet QUIC-Stream zu Serving Host
       ↓ QUIC / Iroh
[iroh-forward-server] auf Serving Host, leitet weiter an :3000
       ↓
[App]

Aufwand: ~12 Tage Entwicklung in Rust mit der iroh-Crate. Python-Bindings sind verfügbar, aber QUIC-Performance ist in Rust besser.


Option C: OPNsense bleibt unberührt, Iroh nur Nginx ↔ Serving Host

Dies ist das sauberste Setup: OPNsense braucht nichts von Iroh zu wissen. Der Iroh-Tunnel existiert nur auf Applikationsebene zwischen Nginx-Host und Serving Host.

Internet → OPNsense → Nginx (Port 443) → iroh-forward-client → [Iroh] → Serving Host

OPNsense sieht nur: Nginx-Host macht ausgehende QUIC-Verbindungen (UDP) zu Iroh-Relays. Kein eingehender Traffic auf dem Serving Host nötig.


Credential-Verteilung

Komponente Credential Wo gespeichert Übergabe
Iroh Node Key (Serving Host) Ed25519-Keypair /etc/iroh/node.key (Serving Host) Public Key wird einmalig aus dem Log extrahiert
Iroh Node Key (Nginx-Host) Ed25519-Keypair /etc/iroh/client.key (Nginx-Host) Automatisch generiert beim ersten Start
Serving Host Public Key Public Key (String) Nginx-Host Config / .env Out-of-band: z.B. über Ansible/Vault, Gitea-Secret, o.ä.
Relay-URL URL beide Hosts Im iroh-config oder Env-Variable
App-Credentials DB-Passwörter etc. Serving Host lokal Unverändert Iroh ändert nichts daran

Wichtig: Der Public Key des Serving Host muss sicher und authentisch übertragen werden er ist der einzige Vertrauensanker. Wird er kompromittiert (Man-in-the-Middle beim Austausch), kann ein Angreifer eine eigene Verbindung vortäuschen.


Vor- und Nachteile

Vorteile

  • Standortunabhängigkeit: Serving Host kann in Hetzner, Zuhause, AWS oder hinter CGNAT laufen kein eingehender Port nötig
  • Kein VPN-Daemon: Keine WireGuard-Konfiguration, keine IKEv2-PKI Aufwand sinkt deutlich
  • OPNsense bleibt unberührt: Firewall-Regeln, Routing-Tabellen alles unverändert
  • Ende-zu-Ende-verschlüsselt: TLS 1.3 über QUIC; Relay sieht nur verschlüsselte Bytes
  • Selbst-hostbarer Relay: Kein SaaS-Abhängigkeit wie bei Tailscale; iroh-relay ist Open Source
  • Direkte Verbindungen wo möglich: 95 % der Verbindungen gehen ohne Relay-Hop durch (Iroh-Angabe)

Nachteile

  • L7-only: Nginx muss explizit konfiguriert werden; kein transparentes OS-Routing
  • Kein Flottenmanagement: Key-Rotation, Revocation, Inventar alles selbst gebaut
  • dumbpipe reicht nicht für HTTP-Upstream: Eigene Entwicklung nötig (Option B)
  • QUIC-Firewall-Probleme: Manche Netze blockieren UDP; WebSocket-Fallback existiert, aber nicht alle Clients unterstützen ihn
  • Relay-Abhängigkeit bei symmetrischem NAT: Eigener Relay nötig für vollständige Unabhängigkeit
  • Fehlerdiagnose schwieriger: Kein tcpdump auf dem Iroh-Interface; Debugging läuft über Iroh-eigene Logs
  • Nginx kennt keine echte Client-IP: Bei Relay-Routing kommt Traffic von der Relay-IP; X-Forwarded-For muss manuell gesetzt werden

Empfehlung

Für ein produktives Setup ist Option B (eigenes Iroh-Forward-Tool) der richtige Weg. Der Aufwand ist überschaubar und man bekommt ein sauberes TCP-Forwarding mit QUIC-Multiplexing, ohne auf dumbpipe-Hacks angewiesen zu sein.

Für einen ersten Proof of Concept reicht Option A mit dumbpipe + socat aus, um die Prinzipien zu validieren, bevor eigener Code entsteht.

OPNsense und Nginx müssen in keinem der Szenarien strukturell verändert werden Iroh ist eine reine Ergänzung auf Applikationsebene.