From 60c4570e72e36c2a9720593c8baec74ee2ab52d6 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Mon, 10 Aug 2026 22:12:59 +0200 Subject: feat: Phase 9.1–9.5 — WebRTC DataChannel transport for browser P2P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Browser clients can now connect P2P to nodes behind residential NAT via WebRTC DataChannel with ICE/STUN. Validated on SFR Port-Restricted Cone NAT + 4G CGNAT across three scenarios (WiFi LAN, 4G IPv6, 4G IPv4 STUN). No TURN relay needed. Hub serves only as signaling relay (<1 KB). New files: - webrtc_server.py: aiortc-based WebRTC transport (node side) - signaling.py: SDP/ICE relay endpoint (hub side) - transport.js: browser WebRTC client with msgpack framing - webrtc-test.html: spike test page for browser→NAT→node validation - test_webrtc_transport.py: 4 tests (handshake, file transfer, auth, guard) - meshbay-draft-v4.md: architecture spec updated for web client Modified: - hub_client.py: WebRTC offer handling via hub WebSocket - revocation.py: node_id from WS auth + webrtc_answer routing - pyproject.toml: aiortc>=1.9 dependency 123 tests passing (117 existing + 6 new). Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md index d0c49bd..8cc9db9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -121,33 +121,48 @@ key hierarchy, on-the-fly encryption, transport abstraction. Existing v1 users (64 MB) are transparently rehashed on next successful login. CLI `calibrate` command still TODO for per-hardware tuning. -## NAT traversal — résultats empiriques (demo-v2) - -SFR résidentiel Fedora 44 → meshbay.org OVH VPS : -- **IPv6** : adresse publique présente MAIS entrant bloqué par la box → skippé -- **NAT type** : **Port-Restricted Cone** (pas Address-Restricted comme supposé en Spike 4) -- **Mécanisme validé** : `QuicChunkServer.punch_nat(peer_ip, peer_port)` envoie la probe - depuis le socket QUIC interne (`_transport.sendto()`). Le client DOIT se connecter - depuis le même port (local_port=QUIC_PORT dans QuicChunkClient). -- **UPnP** : désactivé sur box SFR → skippé -- **Handshake QUIC** : 12.7s (demo) → < 500ms attendu en prod (gap probe↔connect réduit + 0-RTT) -- **Scripts** : `QE/demo-v2/` — run_node.py / download.py / nat.py / setup_demo.py +## NAT traversal — empirical results + +### QUIC native clients (demo-v2) + +SFR residential Fedora 44 → meshbay.org OVH VPS: +- **NAT type**: Port-Restricted Cone +- **Mechanism**: `QuicChunkServer.punch_nat()` sends probe from QUIC server socket +- **Scripts**: `QE/demo-v2/` + +### WebRTC browser clients (Phase 9 spike, 2026-08-10) + +Mobile 4G SFR → node behind SFR residential NAT (Port-Restricted Cone + CGNAT 4G): + +| Test | ICE path | Result | +|---|---|---| +| WiFi LAN | IPv6 direct | OK, ~100ms | +| 4G + IPv6 | IPv6 inter-network | OK, ~600ms | +| 4G + IPv4 only (IPv6 disabled) | STUN hole-punch IPv4 | OK, ~650ms | + +- **No TURN relay needed** — ICE/STUN handles both NAT types automatically +- **Hub role**: signaling only (SDP/ICE relay via WebSocket, <1 KB) +- **Data path**: browser ↔ node P2P via WebRTC DataChannel +- **Scripts**: `QE/demo-v3/run_node_webrtc.py`, test page at `/webrtc-test.html` ## Key modules — où trouver quoi -| Besoin | Module | Fichier | +| Need | Module | File | |---|---|---| -| Chiffrement chunks (prod) | `meshbay_common.crypto` | `crypto.py` | -| Dérivation clés depuis password | `meshbay_common.keyderive` | `keyderive.py` | -| Bundle clés (web) | `meshbay_common.keyderive` | `keyderive.py` + `static/keyderive.js` | +| Chunk encryption (prod) | `meshbay_common.crypto` | `crypto.py` | +| Key derivation from password | `meshbay_common.keyderive` | `keyderive.py` | +| Key bundle (web) | `meshbay_common.keyderive` | `keyderive.py` + `static/keyderive.js` | | GEK wrap/unwrap (ECIES) | `meshbay_common.crypto` | `crypto.py` | | Double Ratchet (1:1 DM, future) | `meshbay_common.ratchet` | `ratchet.py` | | Sender Keys (group chat) | `meshbay_common.senderkeys` | `senderkeys.py` (Phase 7.5) | -| AES-GCM (navigateur) | `meshbay_common.webcrypto` | `webcrypto.py` + `static/crypto.js` | -| Keystore node | `meshbay_node.keystore` | `keystore.py` | -| NAT traversal | `QE/demo-v2/nat.py` | non versionné — résultats dans devel-phases.md | -| QUIC NAT punch | `meshbay_node.transport.quic_server` | `QuicChunkServer.punch_nat()` | -| Scripts de démo opérationnels | — | `QE/demo-v1/*.py` (non versionné) | +| AES-GCM (browser) | `meshbay_common.webcrypto` | `webcrypto.py` + `static/crypto.js` | +| Node keystore | `meshbay_node.keystore` | `keystore.py` | +| QUIC NAT punch (native) | `meshbay_node.transport.quic_server` | `QuicChunkServer.punch_nat()` | +| WebRTC transport (browser) | `meshbay_node.transport.webrtc_server` | Phase 9.3 — `aiortc` DataChannel | +| WebRTC signaling (hub) | `meshbay_hub.api.signaling` | Phase 9.2 — SDP/ICE relay | +| Browser transport client | `static/transport.js` | Phase 9.4 — WebRTC DataChannel | +| Web SPA | `static/app.js` | Phase 9.6 — Preact + preact-router | +| Demo scripts | — | `QE/demo-v1/*.py`, `QE/demo-v2/*.py` (not versioned) | ## meshbay.org server (état cible) -- cgit v1.2.3