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

207 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.