==== Routes parasites Docker : ConnMan — services injoignables depuis l'extérieur ==== === Symptômes === * Gitea SSH (port 8329) injoignable depuis le WAN, web OK. Précédemment : NFS via WireGuard en timeout. * ''tcpdump'' côté serveur : SYN reçus, **aucun SYN-ACK renvoyé** — le retour part dans le vide. * Symptôme générique : tout trafic retour vers une destination **hors LAN** (IP publiques, réseau VPN) est détourné. <code> ip route get <IP_client_externe> → ... dev veth3b7619a src 169.254.x.x # retour envoyé dans un veth Docker ! ip route show | grep -E "veth|^0.0.0.0" 0.0.0.0 dev vethXXXX scope link default dev vethXXXX scope link # métriques énormes (429496xxxx) 169.254.0.0/16 dev vethXXXX proto kernel scope link src 169.254.x.x </code> === Cause racine === **Quatre gestionnaires réseau cohabitaient** : ifupdown (le légitime, dhclient sur ''enp3s0''), NetworkManager (inactif sur les veth), systemd-networkd (réveillé par socket), et **ConnMan** — le vrai coupable. ConnMan « adopte » chaque veth Docker à sa création, tente un DHCP dessus, échoue, retombe en IPv4LL (''169.254.x'') et pose des routes ''default''/''0.0.0.0'' parasites qui captent le trafic retour. Identification via le journal : <code> journalctl -b | grep -i vethXXXX → connmand[...]: Adding interface vethXXXX [ ethernet ] </code> Fausse piste initiale : systemd-networkd (fichier ''10-docker-veth-unmanaged.network'' créé, sans effet — les veth étaient déjà ''unmanaged'' côté networkd). === Solution === Vérifier **avant** que ifupdown tient bien l'interface (crucial en remote) : <code> systemctl is-active networking # active ps aux | grep dhclient # dhclient ... enp3s0 </code> Puis neutraliser ConnMan **avec filet de sécurité** (relance auto si perte de main) : <code> # Filet : relance ConnMan dans 300 s quoi qu'il arrive systemd-run --on-active=300 systemctl start connman # Bascule : stop ConnMan + reprise de l'interface par ifupdown systemctl stop connman; sleep 2; ifdown enp3s0; ifup enp3s0 # Si la main est conservée : annuler le filet (nom affiché par systemd-run) systemctl stop run-XXXX.timer # Rendre permanent systemctl disable --now connman && systemctl mask connman </code> De même pour systemd-networkd (redondant, socket-activated) : <code> systemctl disable --now systemd-networkd.socket systemd-networkd.service systemctl mask systemd-networkd.socket systemd-networkd.service </code> === Validation (après reboot) === <code> ip route show | grep -E "veth|^0.0.0.0" # vide ip route show | head -1 # default via 192.168.1.90 dev enp3s0 git fetch # depuis l'extérieur, via Gitea SSH </code> === Pièges rencontrés === * ''systemctl stop connman'' **à chaud sans ifup derrière** : ConnMan flushe l'IP de ''enp3s0'' en mourant → serveur injoignable (reset électrique nécessaire). * Les routes parasites déjà posées ne partent pas seules : ''ip route flush dev vethXXXX''. * **Attention au flush** : il peut aussi emporter la route par défaut si elle avait été posée par le gestionnaire fautif → vérifier ''ip route show'' juste après.