Black hole PMTU : Gitea SSH inaccessible depuis l'extérieur (gros paquets perdus)

Date : juillet 2026

Symptômes

Diagnostic

1. tcpdump sur le serveur (.9) :

sudo tcpdump -ni any port 8329

Signature caractéristique : les petits paquets passent, mais un trou de séquence apparaît — le serveur acquitte ack 43 et signale en SACK avoir reçu 1447:1611. Le segment 43:1447 (~1404 octets de données, 1456 octets sur le fil) n'arrive jamais, même réémis.

... Flags [.], ack 43, ... sack 1 {1447:1611} ...

2. tcpdump sur le routeur (apk add tcpdump — OpenWrt récent utilise apk, plus opkg) : le gros segment n'apparaît jamais sur wan In → perdu en amont du routeur, sur le chemin opérateur. L'infra locale est hors de cause.

3. Test MTU depuis le client (réflexe à retenir) :

ping -M do -s 1428 -c 2 git.beafrancois.fr   # 1456 octets sur le fil

Résultat mesuré : 1428 (fil) passe, 1456 silence — alors que la gateway 4G annonçait MTU 1456. Équipement opérateur défaillant.

Cause

Un équipement du chemin opérateur mobile a une MTU réelle < 1456 et droppe les paquets trop gros sans envoyer l'ICMP « fragmentation needed ». Le TCP du client ne peut donc pas détecter le problème (PMTU discovery cassée) et réémet indéfiniment le même segment trop gros.

Le mtu_fix d'OpenWrt (MSS clamping de la zone wan) était actif mais inopérant : il clampe selon la MTU du WAN du routeur (1500), alors que le goulot est ailleurs.

Solution : MSS clamp forcé sur le routeur

Forcer un MSS bas dans tous les SYN forwardés : le client négocie des segments plus petits qui passent partout. Protège tous les clients externes quel que soit leur réseau.

Sur le routeur (aiguilleur, .90) :

cat > /etc/nftables.d/10-mss-clamp.nft << 'EOF'
chain mssfix {
    type filter hook forward priority mangle; policy accept;
    tcp flags syn tcp option maxseg size > 1388 tcp option maxseg size set 1388
}
EOF
/etc/init.d/firewall restart

MSS 1388 = paquets de 1428 octets max (la valeur validée par le test). Impact débit : ~4 % de payload en moins par segment, négligeable.

Pérennité après sysupgrade :

echo '/etc/nftables.d/10-mss-clamp.nft' >> /etc/sysupgrade.conf

Notes