Les passerelles VPN à haut débit maintiennent fréquemment des points d'entrée TCP en parallèle de leurs tunnels UDP. Dans les environnements d'infrastructure modernes, TCP sert de canal de secours lorsque les réseaux d'entreprise filtrent les flux UDP, tout en assurant le transport des plans de contrôle et des flux TLS. Dès lors que des passerelles exposent des ports TCP 443 au réseau public, elles s'exposent inévitablement à des attaques par inondation de paquets TCP SYN.
Bien que le matériel réseau moderne traite des millions de paquets par seconde, le sous-système de suivi de connexion Linux montre ses limites sous une saturation brute. Si le pare-feu alloue un enregistrement pour chaque paquet entrant avant d'authentifier le client, la mémoire s'épuise bien avant la capacité de l'interface. Pour éliminer cette vulnérabilité, les ingénieurs réseau déploient Linux nftables SYNPROXY.
Comprendre le fonctionnement de SYNPROXY nécessite d'analyser le traitement des paquets au sein du sous-système Netfilter sous charge intensive.
Vulnérabilité de saturation de la table de suivi :
Flux SYN Flood ──> Carte réseau (NIC) ──> Netfilter PREROUTING ──> Allocation mémoire conntrack (struct nf_conn)
│
SATURATION (nf_conntrack: table full)
│
PERTE DE SERVICE (Trafic rejeté)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────
Filtrage sans état avec nftables SYNPROXY :
Flux SYN Flood ──> PREROUTING (notrack) ──> INPUT (SYNPROXY) ──> Réponse SYN-ACK sans état (Syncookie)
│
(Aucune allocation mémoire conntrack)
│
Client légitime envoie ACK ────────────────────────────────────> Vérification cookie ──> Connexion conntrack ──> Démon VPN
Le goulot d'étranglement de conntrack : Les limites des syncookies de socket
Il est souvent supposé que l'activation des syncookies via net.ipv4.tcp_syncookies = 1 suffit à neutraliser les attaques SYN flood. En pratique, ce mécanisme protège uniquement la file d'attente d'écoute du socket local (listen(backlog)), sans protéger la table de suivi de connexion Netfilter (nf_conntrack).
Dans la chaîne de traitement Linux, Netfilter intercepte les paquets au niveau du point d'ancrage NF_INET_PRE_ROUTING, bien avant la couche transport locale (NF_INET_LOCAL_IN). Lorsqu'un paquet portant le drapeau SYN entre dans le système, nf_conntrack alloue immédiatement une structure struct nf_conn et l'insère dans la table de hachage globale avec l'état SYN_RECV :
Arrivée paquet ──> nf_conntrack_in() ──> init_conntrack() ──> kmem_cache_alloc(nf_conntrack_cachep)
Chaque enregistrement consomme entre 320 et 384 octets de mémoire slab. Avec une limite par défaut nf_conntrack_max fixée à 262 144 entrées, une attaque générant 300 000 paquets SYN par seconde sature la table en moins de 900 millisecondes.
Une table saturée entraîne plusieurs conséquences immédiates :
- Le noyau consigne l'erreur
net_ratelimit: nf_conntrack: table full, dropping packet. - Les tunnels VPN actifs et les nouvelles connexions légitimes sont rejetés.
- La charge processeur s'envole sous l'effet des routines d'interruption logicielle.
Les syncookies traditionnels n'agissant que dans tcp_v4_rcv(), ils restent inefficaces si nf_conntrack échoue en amont. La validation de la poignée de main doit impérativement intervenir avant le suivi d'état.
Architecture interne de Netfilter SYNPROXY
Le module synproxy, implanté dans net/netfilter/nf_synproxy_core.c et piloté via nftables, opère comme un mandataire TCP sans état au niveau du noyau. Il dissocie l'établissement de connexion en deux temps : une poignée de main externe sans enregistrement d'état avec le client, suivie d'une poignée de main interne avec l'application locale.
Client externe nftables SYNPROXY Démon VPN local
│ │ │
│─── 1. TCP SYN [MSS, WScale, SACK] ─────>│ (Sans état, aucune mémoire allouée) │
│ │ │
│<── 2. SYN-ACK sans état [Cookie] ───────│ (Condensat cryptographique 4-tuple) │
│ │ │
│─── 3. TCP ACK [Cookie + 1] ────────────>│ │
│ │─── 4. Émission TCP SYN interne ───────>│
│ │<── 5. Réception SYN-ACK interne ──────│
│ │─── 6. Envoi ACK interne ──────────────>│
│ │ │
│═════════════════════════════════════════╪═══════════════════════════════════════│
│ Phase de données et ajustement du décalage de séquence │
│─── 7. Données applicatives TLS ────────>│─── 8. Réécriture SEQ/ACK (delta) ─────>│
│<── 10. Réécriture SEQ/ACK (delta) ──────│<── 9. Données de réponse ─────────────│
Les étapes d'exécution se déroulent comme suit :
Étape 1 : Exclusion du suivi initial
Les paquets SYN à destination du port VPN sont marqués avec l'instruction notrack dans la chaîne prerouting brute. Netfilter n'alloue ainsi aucune ressource mémoire.
Étape 2 : Synthèse de syncookie sans état
Le paquet atteint la règle SYNPROXY dans la chaîne INPUT. Au lieu de transmettre le paquet au socket, SYNPROXY calcule un numéro de séquence initial (ISN) de 32 bits par hachage cryptographique combinant :
- Les adresses IP source et destination
- Les ports source et destination
- Le numéro de séquence initial du client
- Une clé secrète du noyau renouvelée toutes les 60 secondes
- Les paramètres TCP encodés (index MSS, facteur d'échelle de fenêtre, SACK)
Le noyau émet instantanément un paquet SYN-ACK vers le client sans conserver d'état. Si le paquet provenait d'un robot émettant des adresses falsifiées, la transaction prend fin immédiatement sans impacter la mémoire.
Étape 3 : Validation de l'ACK et instanciation d'état
Un client légitime répond par un paquet ACK avec le numéro de séquence Cookie + 1. SYNPROXY intercepte ce paquet et recalcule la formule cryptographique.
Dès que la légitimité du client est confirmée :
- Une entrée
struct nf_connest créée dansnf_conntrack. - L'état bascule immédiatement vers
ESTABLISHED. - Les options négociées sont restituées fidèlement.
Étape 4 : Poignée de main locale et réécriture du décalage
Le démon local attendant une poignée de main TCP standard, SYNPROXY génère un paquet SYN local vers le port d'écoute applicatif.
Lorsque l'application répond par un SYN-ACK porteur de son propre numéro de séquence (ISN_server), SYNPROXY calcule l'écart :
$$\Delta = ext{ISN}_{ ext{server}} - ext{Cookie}$$
Durant tous les échanges ultérieurs, SYNPROXY applique ce correctif à la volée directement dans le chemin de données du noyau :
- Trafic entrant : incrémente le numéro de séquence de la valeur $\Delta$.
- Trafic sortant : décrémente le numéro d'acquittement de la valeur $\Delta$.
Cette translation s'effectue sans surcoût d'espace utilisateur, garantissant une transparence totale pour l'application.
Mise en œuvre pratique : Configuration de nftables SYNPROXY
L'intégration de SYNPROXY repose sur un jeu de règles nftables articulé autour d'une priorité appropriée.
Exemple de configuration adaptée au port 443 d'une passerelle VPN :
#!/usr/sbin/nft -f
flush ruleset
table inet vpn_filter {
synproxy synproxy_vpn {
mss 1460
wscale 7
timestamp sack-perm
}
chain raw_prerouting {
type filter hook prerouting priority raw; policy accept;
tcp dport 443 tcp flags syn notrack
}
chain filter_input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
ct state invalid drop
tcp dport 443 synproxy config synproxy_vpn
tcp dport 443 ct state new accept
}
chain filter_forward {
type filter hook forward priority filter; policy drop;
}
chain filter_output {
type filter hook output priority filter; policy accept;
}
}
Chargement de la configuration sous Linux :
sudo nft -f /etc/nftables.conf
Vérification des règles actives :
sudo nft list table inet vpn_filter
Ajustement des paramètres noyau et métriques de supervision
Le bon fonctionnement de SYNPROXY requiert des réglages réseau adaptés au sein du fichier /etc/sysctl.d/99-synproxy.conf :
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_buckets = 524288
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
Application des modifications :
sudo sysctl --system
Consultation des statistiques en temps réel
Les métriques d'activité de SYNPROXY sont consultables via les pseudo-fichiers système :
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/net/stat/synproxy
Le fichier affiche les compteurs détaillés :
entries: Sessions actuellement gérées par SYNPROXY.syn_received: Paquets SYN traités de manière sans état.cookie_invalid: Paquets ACK forgés rejetés.cookie_valid: Poignées de main validées intégrées à conntrack.
Intégration dans l'architecture réseau RiceGuard
Une stratégie de défense réseau robuste repose sur la résilience de chaque couche protocolaire. Si le protocole RiceGuard fonctionne principalement sur UDP avec une validation par cookie cryptographique, les infrastructures de passerelle exposent des interfaces TCP pour assurer la compatibilité en entreprise et sécuriser les requêtes DNS chiffrées.
En plaçant nftables SYNPROXY en première ligne de traitement, l'infrastructure RiceGuard sépare la résistance aux saturations brutes du suivi d'état des connexions, préservant les ressources serveur pour le trafic légitime.



