# ADR 0006 — Relais TURN pour la visio, sur le port 443 - **Date** : 2026-10-12 - **Statut** : proposé (attend le DNS et l'accord d'Adam — pas encore appliqué) ## Contexte Dette depuis l'étape 15 (ADR 0005) : sur un réseau scolaire qui bloque tout sauf le port 443 (CLAUDE.md, section 6 : « Tout passe par le port 443 »), la visio Jitsi n'a ni son ni image, car JVB n'écoute qu'en UDP sur le port 10000. Un relais TURN sur 443 est la solution standard de Jitsi pour ce cas. Recherche faite dans la documentation officielle (pas de mémoire) : - [Jitsi Handbook — Setting up TURN](https://jitsi.github.io/handbook/docs/devops-guide/turn/) - fichier source `prosody/rootfs/defaults/prosody.cfg.lua` de l'image `ghcr.io/jitsi/prosody:stable-11248` (celle déployée, lue directement, pas résumée) - `README.turnserver` du dépôt officiel `coturn/coturn` ## Décisions 1. **coturn, paquet Debian (`apt`), service systemd — pas en conteneur Docker.** Comme `correcteur` et `proxy-console` : évite tout le lot de soucis déjà rencontrés avec Docker (pont absent, `iptables: false`, `br_netfilter`). Un seul process système à durcir et superviser. 2. **coturn n'écoute qu'en TLS (`tls-listening-port`), sur `127.0.0.1` ** — jamais directement sur l'IP publique. `no-udp` et `no-tcp` (pas de client en clair : TURNS seulement). Le relais vers JVB (`udp-relay`, RFC 5766, en local) reste actif — c'est le sens inverse (coturn → JVB), indispensable et jamais exposé à Internet. 3. **Partage du port 443 par SNI**, sans toucher au TLS existant : un bloc `stream {}` Nginx (module `libnginx-mod-stream`, à installer — absent aujourd'hui) avec `ssl_preread` lit le nom de domaine demandé dans la poignée de main TLS **sans la déchiffrer**, puis route : - `turn.syllabuslab.fr` → `127.0.0.1:5349` (coturn, qui termine son propre TLS avec son propre certificat) ; - tout le reste (`syllabuslab.fr`, `www`, `status`, `meet`) → `127.0.0.1:8443` (le Nginx HTTP actuel, qui passe du port public 443 à ce port interne — **inchangé sinon**). `/etc/nginx/nginx.conf` passe de `include /etc/nginx/sites-enabled/*` à une structure à deux niveaux (`http {}` sur le port interne, nouveau `stream {}` sur le port public) : seul changement structurel du projet. 4. **Authentification par secret partagé (TURN REST API / XEP-0215)**, mécanisme natif des deux côtés, aucun module ni plugin personnalisé : - côté coturn : `use-auth-secret`, `static-auth-secret=`, `realm=syllabuslab.fr` ; - côté Prosody (variables d'environnement déjà lues par `prosody.cfg.lua`, confirmé dans le fichier source) : `TURNS_HOST=turn.syllabuslab.fr`, `TURNS_PORT=443`, `TURN_CREDENTIALS=`. Prosody calcule alors lui-même, pour chaque participant, un couple nom d'utilisateur/mot de passe TURN valable 24 h (`TURN_TTL`, défaut `86400`), sans jamais exposer le secret au navigateur. - Le secret est généré une fois sur le serveur (comme les autres secrets de la visio), jamais dans Git. 5. **Aucun nouveau port à ouvrir dans nftables.** Le relais UDP de coturn vers JVB reste en boucle locale (les deux tournent sur le même serveur) : l'intérêt du TURN-sur-TCP est justement que tout le trafic de l'élève — contrôle *et* médias — passe par la seule connexion TCP/443 déjà établie ; coturn se charge seul de parler en UDP à JVB, sans jamais demander au navigateur de contacter une autre adresse. 6. **Certificat** : `turn.syllabuslab.fr` ajouté au certificat Let's Encrypt existant (comme `meet`/`status`), obtenu une fois le DNS créé. ## Prérequis avant d'appliquer quoi que ce soit - **DNS** : `turn.syllabuslab.fr → 163.172.4.195`, pas d'AAAA (comme `meet` et `status`). **À faire par Adam.** - Accord explicite d'Adam sur le diff exact de Nginx (changement structurel le plus visible de ce chantier) et sur l'ouverture d'aucun nouveau port — seule une restructuration interne du 443 existant. ## Alternatives écartées - **coturn en conteneur Docker** : repasserait par les soucis de réseau Docker déjà vus avec Kuma et Jitsi (étapes 9, 15) pour un gain nul (un seul process, pas besoin d'isolation supplémentaire). - **`mod_turncredentials.lua` personnalisé** (ancienne méthode documentée dans des guides tiers) : l'image `prosody:stable-11248` le fait déjà nativement par variables d'environnement — ne pas réinventer ce qui existe. - **Ouvrir une plage de ports UDP pour le relais coturn → JVB** : inutile, cette liaison reste locale au serveur. ## Conséquences - Nouveau paquet système (`coturn`) et nouveau module Nginx (`libnginx-mod-stream`) à faire vivre (mises à jour de sécurité comme le reste : `unattended-upgrades` les couvre déjà). - Restructuration de `/etc/nginx/nginx.conf` : à vérifier avec la même prudence qu'un changement de pare-feu (filet anti-coupure, accord explicite), même si techniquement aucune règle nftables ne change. - Dette retirée une fois vérifié par un vrai test (client forcé en TCP, comme documenté dans le Handbook Jitsi, ou réseau dont l'UDP est bloqué).