Files
DataControl/docs/PLAN-wireguard.md
T
tuxgyverandClaude Opus 5.5 33ea4ff947 feat: tunnel WireGuard vers le serveur familyd et mode propriétaire de l'appareil
- Firebase et le pare-feu local (trou noir, liste blanche par application, coupure cyclique locale) sont retirés
- Client WireGuard officiel (GoBackend) : tout le trafic passe par le serveur familyd, qui filtre
- Appairage par code ou lien familyd:// ; clé privée WireGuard et jeton chiffrés par l'Android Keystore
- Remontées par le tunnel : état, temps d'écran, applications installées, évènements (file persistante)
- Mode propriétaire (Device Owner) : VPN toujours actif avec blocage hors VPN, réglages verrouillés,
  garde-fou si le serveur ne répond plus pendant 15 min
- Plan de la refonte : docs/PLAN-wireguard.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9CBCVP5oDu2sfoYPisNCQ
2026-10-25 14:44:18 +01:00

426 lines
25 KiB
Markdown
Raw 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.
# Plan : contrôle parental par WireGuard et serveur auto-hébergé
> Statut : **proposition**, rien n'est réalisé. Rédigé le 2026-10-25.
> Concerne DataControl (téléphone de l'enfant), FamilyControl (téléphone du parent) et un nouveau
> service serveur, `familyd`, hébergé sur le CT 233 de pve-home (192.168.77.233).
## 1. Objectif
Remplacer le fonctionnement actuel (pare-feu VPN local « trou noir » + Firebase) par :
- **un tunnel WireGuard permanent** entre le téléphone de l'enfant et le serveur : tout le trafic
du téléphone (Wi-Fi comme 4G/5G) passe par le serveur ;
- **un filtrage côté serveur** : coupures, plages horaires, quota, sites et services interdits ;
- **un canal de contrôle** par ce même tunnel : consignes du parent, état de l'appareil, alertes ;
- **plus aucune dépendance à Firebase / Google**.
Ce qui reste sur le téléphone : ce que seul le téléphone peut savoir (application au premier plan,
temps d'écran, batterie, position, type de réseau) et le blocage du lancement des applications.
## 2. Principe et contrainte fondatrice
WireGuard transporte des **paquets IP** : le serveur voit des adresses, des ports et (via le DNS)
des noms de domaine, **jamais l'application qui a émis le paquet**. D'où la répartition :
| Besoin | Où | Comment |
|---|---|---|
| Couper Internet (horaire, punition, coupure cyclique) | Serveur | Règle nftables de l'appareil → « coupé » |
| Bloquer un service (TikTok, YouTube…) ou une catégorie | Serveur | DNS filtrant par appareil |
| « Seul Pronote passe » (liste blanche) | Serveur | DNS limité aux domaines autorisés + jeu d'IP rempli par les réponses DNS |
| Quota de données | Serveur | Compteur d'octets du pair WireGuard (fiable, non falsifiable) |
| Interdire / limiter le temps d'une application | Téléphone | Service d'accessibilité existant (blocage au lancement) |
| Temps d'écran, batterie, position, type de réseau | Téléphone | Remontés à l'API par le tunnel |
| Empêcher de couper le VPN, de changer l'heure, de désinstaller | Téléphone | Mode Device Owner (§8) |
Le filtrage réseau **par application** n'est pas repris en phase 1 : une application interdite est
bloquée à son lancement, ce qui couvre l'usage réel. Il reste possible en phase 5 (§11).
## 3. Architecture
```
Téléphone enfant (DataControl) CT 233 srv-home-zoompilot (192.168.77.233)
┌──────────────────────────────┐ ┌──────────────────────────────────────────────┐
│ VPN = client WireGuard │ UDP 51721 │ wg1 10.78.0.1/24 (wg0 ZoomPilot inchangé) │
│ AllowedIPs 0.0.0.0/0, ::/0 ├────────────────►│ ├ nftables table inet familyd │
│ DNS 10.78.0.1, MTU 1280 │ Freebox │ │ modes par appareil, NAT sortant, │
│ Service d'accessibilité │ 82.67.111.224 │ │ DNS forcé, DoT/DoH bloqués │
│ Client API (+ WebSocket) │ │ ├ DNS filtrant (AdGuard Home) 10.78.0.1:53 │
└──────────────────────────────┘ │ ├ familyd (FastAPI + SQLite) │
│ │ 10.78.0.1:8100 (appareils, via wg1) │
FamilyControl (parent) │ │ 192.168.77.233:8100 (Traefik, parents) │
┌──────────────────────────────┐ HTTPS │ ├ compteurs `wg show wg1 transfer` │
│ API REST + WebSocket ├──► Traefik CT 201 ─►└ ntfy :8090 (existant) pour les alertes │
│ Alertes : appli ntfy │ family.tuxtech.fr │
└──────────────────────────────┘ └──────────────────────────────────────────────┘
```
### Cohabitation avec ZoomPilot sur le CT 233
Tout est séparé pour qu'un changement d'un côté ne touche pas l'autre :
| | ZoomPilot (existant) | Contrôle parental (nouveau) |
|---|---|---|
| Interface WireGuard | `wg0` 10.77.0.1/24, UDP 51720 | `wg1` 10.78.0.1/24, UDP **51721** |
| Pare-feu | `table inet filter`, `table ip zp_nat` | `table inet familyd` (dédiée) |
| Service | `zoompilot` :8000 | `familyd` :8100, `adguardhome` :53 + :3000 (admin, local) |
| Utilisateur système | `zoompilot` | `familyd` |
| Données | /var/lib/zoompilot | /var/lib/familyd |
Plages et ports vérifiés libres le 2026-10-25 : 10.6.0.0/24, 10.8.0.0/23 et 10.77.0.0/24 sont pris ;
UDP 51720, 51820, 51900 pris.
**Risque assumé** : le CT devient critique pour l'accès Internet de l'enfant (voir §9). Un CT dédié
(ex. 234) isolerait mieux ; le plan reste valable tel quel en changeant l'IP.
## 4. Serveur
### 4.1 Ressources du CT 233
Actuel : 1 cœur, 512 Mo, disque 3,9 Go (2,4 Go libres). À porter à **2 cœurs, 1,5 Go de RAM,
disque +8 Go** (journaux DNS, historique SQLite). Sur pve-home, lire `/etc/pve` plutôt que
`pct list` (stockage lent) ; le CT est sur `local-lvm`.
```bash
# sur pve-home
pct set 233 --cores 2 --memory 1536
pct resize 233 rootfs +8G
```
### 4.2 Réseau
- **Freebox** : rediriger **UDP 51721** → 192.168.77.233.
- **Nom** : `fam-vpn.tuxtech.fr` → 82.67.111.224 (point de terminaison WireGuard ; un nom plutôt
qu'une IP, pour survivre à un changement d'adresse).
- **Traefik (CT 201)** : `family.tuxtech.fr` → 192.168.77.233:8100, certificat Let's Encrypt,
**uniquement** les routes parent et appairage (`/api/parent/*`, `/api/pair`). Les routes
appareil ne sont servies que sur 10.78.0.1.
- **Retour en boucle (hairpin)** : quand le téléphone est sur le Wi-Fi de la maison, il joint
82.67.111.224 depuis le réseau local. À vérifier sur la Freebox en phase 0 ; sinon, résolution
DNS locale de `fam-vpn.tuxtech.fr` vers 192.168.77.233.
- **IPv6** : le tunnel annonce `::/0` pour qu'aucun trafic IPv6 ne contourne le serveur ; le
serveur ne route pas l'IPv6 (les applications retombent sur IPv4). NAT66 éventuel plus tard.
### 4.3 WireGuard `wg1`
```ini
# /etc/wireguard/wg1.conf
[Interface]
Address = 10.78.0.1/24
ListenPort = 51721
PrivateKey = <clé serveur, chmod 600>
# Les pairs sont ajoutés par familyd (wg set + wg-quick save) — pas d'édition à la main.
```
Pair type (écrit par familyd à l'appairage) :
```ini
[Peer]
# device=<uuid> family=<id>
PublicKey = <clé publique générée sur le téléphone>
AllowedIPs = 10.78.0.10/32
```
Côté téléphone : `PersistentKeepalive = 25` (indispensable derrière le NAT des opérateurs), MTU 1280.
### 4.4 Pare-feu nftables (`table inet familyd`)
Chaque appareil a un **mode** appliqué par familyd, via une map plutôt qu'une réécriture des
règles :
| Mode | Effet |
|---|---|
| `open` | Tout passe (filtrage DNS seul) |
| `allowlist` | Seules les IP du jeu `allow4` (remplies par les réponses DNS des domaines autorisés) passent |
| `cut` | Rien ne sort, sauf le serveur lui-même (API + DNS sur 10.78.0.1) |
```nft
table inet familyd {
map mode4 { type ipv4_addr : verdict; } # 10.78.0.10 : jump m_open …
set allow4 { type ipv4_addr; flags timeout; timeout 1h; } # rempli par dnsmasq (nftset)
set doh4 { type ipv4_addr; flags interval; } # résolveurs DoH connus
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "wg1" udp dport 53 dnat ip to 10.78.0.1 # DNS forcé
iifname "wg1" tcp dport 53 dnat ip to 10.78.0.1
}
chain postrouting {
type nat hook postrouting priority srcnat;
iifname "wg1" oifname "eth0" masquerade
}
chain forward {
type filter hook forward priority 0; policy accept;
iifname != "wg1" return
tcp dport 853 drop # DNS sur TLS
udp dport 853 drop
ip daddr @doh4 tcp dport 443 drop # DNS sur HTTPS vers IP connues
ip saddr vmap @mode4
drop # appareil inconnu
}
chain m_open { accept }
chain m_allowlist { ip daddr @allow4 accept; drop; }
chain m_cut { drop }
chain input {
type filter hook input priority 0; policy accept;
iifname "wg1" ip daddr 10.78.0.1 tcp dport { 53, 8100 } accept
iifname "wg1" ip daddr 10.78.0.1 udp dport 53 accept
iifname "wg1" drop # rien d'autre du CT (ZoomPilot, SSH…)
}
}
```
Points à respecter :
- règles **idempotentes**, rechargées au démarrage de familyd depuis la base (source de vérité :
SQLite, pas nftables) ;
- **isolation entre pairs** : un appareil ne joint ni les autres pairs de `wg1`, ni `wg0`, ni le
réseau 192.168.77.0/24 (règles `ip daddr { 10.77.0.0/24, 10.78.0.0/24, 192.168.77.0/24 } drop`
dans `forward`, sauf 10.78.0.1) ;
- après un changement de mode, purger les connexions en cours de l'appareil
(`conntrack -D -s 10.78.0.x`), sinon une connexion ouverte survit à la coupure.
### 4.5 DNS filtrant
**Choix : AdGuard Home** (binaire unique, API REST, réglages par client) :
- un **client par appareil** (identifié par son IP 10.78.0.x) avec ses **services bloqués**
(liste intégrée : TikTok, YouTube, Snapchat…), contrôle parental, recherche sécurisée ;
- règles par appareil avec le modificateur `$client` (mode liste blanche :
`/.*/$client='10.78.0.10'` + `@@||index-education.net^$client='10.78.0.10'`) ;
- blocage des domaines DoH connus (`dns.google`, `cloudflare-dns.com`…) et du domaine canari
`use-application-dns.net` (désactive le DoH de Firefox) ;
- journal des requêtes conservé **7 jours** (consultable par le parent, à mentionner à l'enfant) ;
- interface d'administration sur 127.0.0.1:3003 uniquement, pilotée par familyd ; les règles de
blocage DoH portent `$important` (sinon les exceptions du filtre AdGuard par défaut l'emportent).
**Liste blanche (validé en phase 0)** : la fonction `ipset` d'AdGuard Home ne remplit que les
anciens jeux « ipset », illisibles par nftables. On utilise donc une petite instance **dnsmasq**
(`familyd-dnsmasq`, 127.0.0.1:5353, option `nftset=`) à laquelle AdGuard Home transmet les seuls
domaines de la liste blanche ; chaque adresse obtenue entre dans le jeu `allow4` (expiration 1 h,
renouvelée à chaque requête ; AdGuard Home plafonne son cache à 300 s pour que le renouvellement
ait lieu). Conséquence : `allow4` est **commun à tous les appareils** (union des listes blanches) ;
la liste propre à chaque appareil s'applique au niveau DNS (règles `$client`).
### 4.6 Service `familyd` (FastAPI + SQLite)
Même pile que ZoomPilot (déjà maîtrisée et déployée sur ce CT) : `/opt/familyd`, venv,
`/etc/familyd/familyd.env` (600), données `/var/lib/familyd`, unité systemd, utilisateur
`familyd`. Les opérations privilégiées (`wg set`, `nft`, `conntrack`) passent par un petit
assistant root appelé via `sudo` avec une liste de commandes fermée (pas de shell libre).
**Tâches de fond**
- toutes les 60 s : relevé `wg show wg1 transfer` + `latest-handshakes` → octets par appareil
(deltas stockés), « appareil en ligne » (dernière poignée de main < 3 min) ;
- moteur de règles : à chaque minute et à chaque changement, calcule le mode de chaque appareil
(consigne du parent, plage horaire, coupure cyclique sur données mobiles, quota) et l'applique
(nft + AdGuard) ;
- alertes vers **ntfy** (déjà sur le CT) : appareil hors ligne > 15 min, VPN coupé, protection
retirée, heure modifiée, quota atteint.
**Schéma SQLite (esquisse)**
| Table | Contenu |
|---|---|
| `parents` | id, e-mail, hachage argon2, créé le |
| `families` / `family_parents` | famille, parents associés |
| `devices` | id (uuid), famille, nom, IP tunnel, clé publique WG, hachage du jeton, créé le, dissocié le |
| `pairing_codes` | code (8 car.), famille, appareil prévu, expire le, utilisé le |
| `policies` | appareil, mode manuel, plages horaires, quota, coupure cyclique, services bloqués, liste blanche, règles d'applications (JSON), version |
| `device_state` | appareil, batterie, position, réseau (mobile/Wi-Fi), version de l'appli, Device Owner actif, vu le |
| `traffic` | appareil, jour, octets mobile, octets Wi-Fi (attribués selon le réseau déclaré) |
| `usage` | appareil, jour, temps d'écran total et par application |
| `events` | appareil, type, détail, horodatage |
**API (esquisse)**
| Route | Qui | Rôle |
|---|---|---|
| `POST /api/parent/login` | parent | jeton de session |
| `GET/PUT /api/parent/devices/{id}/policy` | parent | lire / modifier les consignes (versionnées) |
| `POST /api/parent/devices/{id}/pairing-code` | parent | créer un code d'appairage (10 min, usage unique) |
| `POST /api/parent/devices/{id}/bonus` | parent | temps supplémentaire du jour |
| `GET /api/parent/devices/{id}/{state,traffic,usage,events,dns-log}` | parent | suivi |
| `WS /api/parent/ws` | parent | changements en direct |
| `POST /api/pair` | appareil (public, limité en débit) | code + clé publique → IP tunnel, clé serveur, point de terminaison, jeton |
| `GET /api/device/policy` | appareil (tunnel) | consignes en vigueur |
| `POST /api/device/{state,usage,events}` | appareil (tunnel) | remontées |
| `WS /api/device/ws` | appareil (tunnel) | consignes poussées en direct |
| `GET /api/device/time` | appareil (tunnel) | heure de référence (horloge de confiance) |
**Authentification**
- parent : mot de passe (argon2) + jeton de session ;
- appareil : jeton remis à l'appairage (stocké haché) **et** adresse source 10.78.0.x qui doit
correspondre à l'appareil du jeton. Un jeton volé est inutilisable hors du tunnel de cet appareil ;
- `/api/pair` : 5 essais par minute et par IP, code invalidé après usage.
## 5. Appairage
```
Parent (FamilyControl) familyd Enfant (DataControl)
│ créer l'appareil ───────────►│ réserve 10.78.0.x
│◄── code ABCD2345 (10 min) ───│
│ affiche code + QR ··································►│ saisit le code (ou scanne)
│ │ │ génère sa paire de clés WG
│ │◄── POST /api/pair ─────│ (clé privée jamais transmise)
│ │ {code, clé publique} │
│ │ wg set wg1 peer … │
│ │ code consommé │
│ │──► {IP, clé serveur, fam-vpn.tuxtech.fr:51721, DNS, jeton}
│ │ │ monte le tunnel
│◄── WS : « appareil en ligne » │◄── 1re poignée de main ─│
```
- Le QR code contient l'URL `https://family.tuxtech.fr` et le code : rien à taper sur le téléphone
de l'enfant.
- La clé privée WireGuard est générée et stockée sur le téléphone (chiffrée par l'Android
Keystore) ; perdue = ré-appairage.
- Dissociation (par le parent) : pair retiré de `wg1`, jeton révoqué, mode `cut` jusqu'au retrait.
## 6. DataControl (téléphone de l'enfant) — v0.2
**Retiré**
- `FirewallVpnService` (trou noir) et la logique de liste blanche locale par application ;
- Firebase (`FirebaseGateway`, `RemoteSync`, dépendances `firebase-*`, écran de configuration
Firebase) — l'APK s'allège d'autant ;
- la coupure cyclique locale (devient une règle serveur).
**Ajouté**
- client WireGuard : bibliothèque officielle `com.wireguard.android:tunnel` (`GoBackend`, qui
fournit son propre `VpnService`) ; un seul VPN sur l'appareil, donc aucun conflit. Compter
quelques Mo par architecture pour la bibliothèque native ; ne livrer que `arm64-v8a` (et
`armeabi-v7a` si un vieil appareil l'exige) ;
- écran d'appairage (code ou QR) ;
- client API (HTTP + WebSocket sur 10.78.0.1:8100) avec file d'attente hors ligne pour les
remontées ;
- surveillance du tunnel : poignée de main trop ancienne → nouvelle tentative, alerte locale,
événement envoyé dès le retour.
**Conservé**
- service d'accessibilité et `GuardEngine` (blocage au lancement, temps d'écran) ; les règles
arrivent par l'API au lieu de Firestore ; l'horloge de confiance se recale sur
`/api/device/time` ;
- mot de passe local (verrouillage des réglages), journal, mises à jour Gitea ;
- suivi de consommation local (`TrafficStats`) à titre de contrôle croisé du compteur serveur.
**Type de réseau** : le téléphone déclare à chaque changement s'il est en données mobiles ou en
Wi-Fi ; le serveur s'en sert pour attribuer les octets (forfait) et pour les règles propres aux
données mobiles (coupure cyclique).
## 7. FamilyControl (parent) — v0.2
- `src/firebase/*` remplacé par un client de l'API familyd (`src/api/`) : même découpage
fonctionnel, pour garder les écrans ;
- écran de configuration : URL du serveur + compte parent au lieu de la configuration Firebase ;
- nouveaux écrans : mode en cours (libre / liste blanche / coupé) avec bascule immédiate, services
bloqués, journal DNS, consommation réelle mesurée par le serveur ;
- alertes : appli **ntfy** abonnée au sujet de la famille (ntfy exposé par Traefik en HTTPS, accès
refusé par défaut, un jeton par parent). Intégration directe dans FamilyControl plus tard ;
- **clé de signature** : FamilyControl est signé aujourd'hui avec la clé de débogage publique du
modèle React Native. La v0.2 est l'occasion de passer à une clé privée (une réinstallation
unique du téléphone parent).
## 8. Verrouillage du téléphone : mode Device Owner
Sans ce mode, l'enfant peut toujours couper le VPN dans les réglages Android (le serveur le voit
hors ligne et alerte le parent, sans pouvoir l'empêcher). Avec ce mode, DataControl impose :
| Politique | API Android |
|---|---|
| VPN toujours actif + blocage des connexions hors VPN | `setAlwaysOnVpnPackage(admin, pkg, lockdown = true, exemptions)` (API 29+ pour les exemptions) |
| Impossible de modifier les VPN | `addUserRestriction(DISALLOW_CONFIG_VPN)` |
| Impossible de changer date et heure | `DISALLOW_CONFIG_DATE_TIME` |
| Pas de réinitialisation ni de mode sans échec | `DISALLOW_FACTORY_RESET`, `DISALLOW_SAFE_BOOT` |
| DataControl indésinstallable | `setUninstallBlocked(admin, pkg, true)` |
| Pas d'autre utilisateur | `DISALLOW_ADD_USER` |
| Mises à jour silencieuses de DataControl | `PackageInstaller` (autorisé au Device Owner) |
**Mise en place** (une fois, câble USB) :
1. retirer temporairement le compte Google du téléphone (Android refuse sinon) ;
2. `adb shell dpm set-device-owner com.jttools.datacontrol/.admin.AppDeviceAdminReceiver` ;
3. remettre le compte Google.
**Précautions**
- **essayer d'abord sur un téléphone de test** ;
- prévoir dans DataControl « Retirer le mode propriétaire » (mot de passe + confirmation du
parent) : sans lui, seule une réinitialisation complète l'enlève ;
- `DISALLOW_DEBUGGING_FEATURES` n'est **pas** activé par défaut (garder adb pour la maintenance) ;
activable à distance par le parent ;
- **politique en cas de serveur injoignable** (choix du parent) :
- *fermé* : plus d'Internet tant que le serveur ne répond pas (sûr, mais une panne du CT prive
l'enfant d'Internet) ;
- *ouvert après délai* (recommandé) : au bout de 15 min sans poignée de main, DataControl lève
le blocage hors VPN (`lockdown = false`), garde le blocage des applications au lancement, et
signale l'incident dès le retour du serveur.
- applications exemptées du VPN (liste du parent) : téléphone et messagerie de l'opérateur,
appels d'urgence.
## 9. Exploitation
- **Disponibilité** : redémarrage automatique du CT (`onboot`), `Restart=on-failure` pour familyd
et AdGuard Home, sonde de santé (`/api/health`) surveillée, alerte ntfy si familyd ou `wg1`
tombe.
- **Sauvegarde** : `sqlite3 familyd.db ".backup …"` quotidien (jamais `cp`), clé privée du
serveur et `wg1.conf`, configuration AdGuard Home ; intégration aux sauvegardes existantes de
pve-home.
- **Débit** : tout le trafic du téléphone (vidéos comprises) passe par la Freebox deux fois
(entrée + sortie). Mesurer en phase 0 ; la fibre Free est en général largement suffisante.
- **Batterie** : WireGuard est le VPN le plus sobre ; `PersistentKeepalive = 25` coûte un peu,
à mesurer sur une journée en phase 0.
- **Vie privée** : le journal DNS et la position sont des données sur un mineur ; durée de
conservation courte (7 jours DNS, 30 jours position), accès réservé aux parents de la famille.
## 10. Migration depuis Firebase
Une seule famille et un ou deux appareils : **bascule franche** plutôt que fonctionnement mixte.
1. Serveur en place et testé (phases 0–1).
2. Publier FamilyControl v0.2 et DataControl v0.2 (sans Firebase).
3. Mettre à jour les deux téléphones, ré-appairer l'enfant (QR code).
4. Vérifier une journée complète (coupures, horaires, quota, alertes).
5. Supprimer le projet Firebase. L'historique Firestore n'est pas repris (option : script d'export
ponctuel si tu veux garder l'historique de trafic).
Tant que la v0.2 n'est pas installée, la v0.1.x continue de fonctionner avec Firebase.
## 11. Phases
| Phase | Contenu | Critère de fin |
|---|---|---|
| **0. Essai** (≈ 1 j) | `wg1` à la main + appli WireGuard officielle sur un téléphone de test ; AdGuard Home ; essais nft `open` / `cut` / `allowlist` | Débit et batterie mesurés ; hairpin Freebox vérifié ; mode liste blanche validé (AdGuard `ipset` ou repli dnsmasq) |
| **1. Serveur** | familyd (API, moteur de règles, compteurs, alertes), assistant root, déploiement documenté, tests pytest | Appairage, changement de mode et quota testés de bout en bout avec un pair manuel |
| **2. DataControl v0.2** | Client WireGuard, appairage, client API, suppression trou noir + Firebase | Téléphone de test piloté uniquement par familyd pendant 48 h |
| **3. FamilyControl v0.2** | Client API, nouveaux écrans, clé de signature privée | Toutes les fonctions actuelles disponibles sans Firebase |
| **4. Device Owner** | Politiques §8, provisionnement, sortie du mode | VPN impossible à couper sur le téléphone de test ; reprise après panne serveur conforme à la politique choisie |
| **5. Option** | Filtrage réseau par application sur le téléphone : couche Go entre l'interface du VPN et wireguard-go, identification de l'application par `getConnectionOwnerUid` (API 29+) | Une application précise coupée sans couper le reste |
## 12. Phase 0 — état au 2026-10-25
**Réalisé sur le CT 233** (sauvegarde des règles et configurations d'origine :
`/root/backup-familyd-phase0/`) :
- CT agrandi : 2 cœurs, 1,5 Go, disque 20 Go ;
- `wg1` 10.78.0.1/24, UDP 51721 (`wg-quick@wg1`), pair de test 10.78.0.10 ;
- `/etc/nftables.conf` : ouvertures minimales pour `wg1` dans `table inet filter` + `include
"/etc/nftables.d/*.nft"` ; `table inet familyd` dans `/etc/nftables.d/familyd.nft` ;
- AdGuard Home v0.107.79 (`/opt/AdGuardHome`, DNS 10.78.0.1:53, admin 127.0.0.1:3003, mot de
passe `/root/adguard-admin.password`), client « test-phase0 » avec TikTok bloqué ;
- `familyd-dnsmasq` (liste blanche → `allow4`) ;
- `fam-mode IP open|allowlist|cut` et `fam-mode list` en attendant familyd ;
- fichiers de travail : `/root/familyd-phase0/` (config et QR du téléphone de test,
`famsim-test.sh` : faux téléphone en espace réseau isolé pour rejouer les tests).
**Tests passés avec le faux téléphone** : les trois modes se comportent comme prévu ; DNS forcé
(une requête « vers 8.8.8.8 » est servie par le DNS filtrant) ; DoH par IP et DoT bloqués ; LAN,
ZoomPilot et ntfy injoignables depuis le tunnel ; ZoomPilot, ntfy et `wg0` inchangés.
**Reste à mesurer avec un vrai téléphone** : redirection Freebox UDP 51721 (en 4G), retour en
boucle sur le Wi-Fi de la maison, débit, batterie sur une journée, blocage TikTok, applications
qui contournent le DNS.
## 13. Questions ouvertes
1. **Politique en cas de serveur injoignable** : *fermé* ou *ouvert après 15 min* (recommandé) ?
2. **Device Owner** : d'accord pour retirer temporairement le compte Google du téléphone de
l'enfant (ou le réinitialiser) ? Existe-t-il un téléphone de test ?
3. **CT dédié** plutôt que le CT 233 partagé avec ZoomPilot ?
4. **Coupure cyclique** (toutes les X minutes sur données mobiles) : la garder dans le nouveau
modèle, ou la remplacer par le quota et les plages horaires ?
5. **Exemptions** du VPN : quelles applications doivent toujours passer (opérateur, banque…) ?