6030 links
  • GuiGui's Show

  • Home
  • Login
  • RSS Feed
  • Tag cloud
  • Picture wall
  • Daily
Links per page: 20 50 100
page 1 / 1
  • Synproxy - nftables wiki

    A netfilter synproxy intercepts new TCP connections and handles the initial 3-way handshake using syncookies instead of conntrack to establish the connection. Running synproxy on a listening server port thus prevents a SYN flood attack on that port from consuming limited conntrack resources.

    Ça évite également d'envoyer des messages TCP SYN ACK à répétition à un interlocuteur possiblement usurpé.

    Les cookies TCP laissent passer une partie du trafic pourri (mais je n'ai pas affiné les paramètres noyau), Netfilter ne laisse rien passer.



    Sur un système Debian GNU/Linux, les cookies et timestamps TCP sont activés par défaut.

    Il ne reste plus qu'à activer le mode strict du suivi des connexions TCP au démarrage. (Par défaut, ce suivi est souple : les connexions existantes sont automatiquement ajoutées à la table des états. Donc un émetteur qui ne terminerait pas la poignée de main TCP pourrait quand même créer un état, pile ce qu'on veut éviter.) Il s'agit du paramètre noyau /proc/sys/net/netfilter/nf_conntrack_tcp_loose (0 = strict ; 1 = loose = souple).

    Au démarrage, ce paramètre n'existe pas. Il est créé par un module noyau. Vu son nom, on devine que c'est le module nf_conntrack. On vérifie avec lsmod : quand on crée une règle avec une action synproxy en l'absence de toute autre règle, le module nft_synproxy est chargé et entraîne celui du module nf_conntrack (lsmod : « nf_conntrack 204800 3 nft_ct,nft_synproxy,nf_synproxy_core »).

    Lors d'un démarrage, il nous faut donc charger un module noyau puis changer l'un des paramètres du noyau (pas du module, donc modprobe nf_conntrack nf_conntrack_tcp_loose=0 ne fonctionnera pas). Possible race condition, donc (si le paramétrage se déclenche avant le chargement du noyau, ça ne le fera pas). Heureusement, par défaut, systemd-sysctl est configuré pour démarrer après systemd-modules-load (pour vérifier : systemctl list-dependencies --after systemd-sysctl | grep modules-load).

    Du coup, au travail :

    echo 'nft_synproxy' > /etc/modules-load.d/nft_synproxy.conf
    echo 'net.netfilter.nf_conntrack_tcp_loose = 0' > /etc/sysctl.d/98-synproxy.conf

    Pour le reste, on suit le tutoriel du wiki officiel nftables pointé par ce shaarli.



    Contrairement à ce qu'on peut lire sur le web, et comme l'expose le wiki nftables, il ne faut pas mettre le synproxy devant l'ensemble des ports TCP, mais uniquement devant les ports en écoute. Sinon, il sera impossible d'établir des connexions sortantes.

    Comme l'expose succinctement le wiki nftables, l'action synproxy vaut acceptation de la connexion entrante si la poignée de main TCP est achevée. Il n'y a donc pas besoin d'une règle d'acceptation en sus. Si je reprends l'exemple du wiki nftables qui travaille sur les connexions au port 8888, il n'y a pas besoin, dans « input », d'une règle additionnelle de la forme « tcp dport 8888 accept ».



    Si l'on veut être pointilleux, la règle prerouting « tcp dport 8888 tcp flags syn notrack » proposée par le wiki nftables est trop permissive : elle sera déclenchée par tous les messages TCP dont au moins le drapeau SYN est activé. Dit autrement : un message SYN FIN, par exemple, sera aussi accepté, alors qu'il est invalide, au sens de la norme TCP, pour initier une connexion TCP.

    Pour ne déclencher que sur les paquets qui ont uniquement le drapeau SYN : « tcp dport 8888 tcp flags & (urg|ack|psh|rst|syn|fin) == (syn) notrack ».

    Explications :

    • Les drapeaux TCP existants sont publiés par l'IANA. On peut voir les constantes associées avec nft describe tcp flags. Notons que les constantes « ALL » et « NONE » d'iptables n'existent plus et que les autres s'écrivent désormais en minuscule ;

    • La syntaxe est environ celle d'iptables : « DRAPEAUX_DANS_MSG ET LOGIQUE (MASQUE_BINAIRE) == (DRAPEAUX_RECHERCHÉS) ». Le masque est les drapeaux que l'on regarde (pour y chercher ce que l'on veut). Dans le masque et dans la liste des drapeaux recherchés, les drapeaux sont séparés par un OU LOGIQUE (au lieu d'une virgule à l'époque d'iptables). « flags » est comme une variable (que j'ai nommé « DRAPEAUX_DANS_MSG »), elle fait partie du calcul. Pour réviser le masquage binaire, c'est ici. Pour lire une autre explication et d'autres exemples, c'est là ;

    • Ici, on cherche SYN dans un ensemble de drapeaux. L'ensemble de drapeaux (= masque) vaut 00111111. (Les drapeaux sont des bits ordonnés, cf. le registre IANA supra, et je mets à 1 les 6 bits que je veux étudier. URG = 00100000, ACK = 00010000, etc., donc SYN | ACK | etc. = 00100000 | 00010000 | etc. = 00111111.) Le seul drapeau que l'on veut, c'est SYN, soit 00000010. Si un message SYN arrive, ses « flags » valent 00000010. Le résultat du ET LOGIQUE entre le message et le masque vaut 00000010, ce qui correspond à ce que l'on cherche (SYN = 00000010), donc la règle sera déclenchée. Si un message SYN FIN arrive, flags vaudra 00000011. Le résultat du ET LOGIQUE sera 00000011, ce qui n'est pas égal à SYN (00000010), donc la règle ne sera pas déclenchée ;

    • Si je reprends la règle proposée par le wiki nftables, « tcp dport 8888 tcp flags syn notrack », cette fois-ci le masque vaut 00000010, car on regarde uniquement SYN. Si un message SYN FIN se présente, le résultat du ET LOGIQUE sera 00000010, ce qui correspond à SYN, donc la règle sera déclenchée, d'où sa permissivité. La règle détecte le SYN mais ne voit pas le FIN, puisque, à travers le masque choisi, elle ne l'étudie pas ;

    • Les plus attentifs auront remarqué que, dans la règle que je propose, je travaille sur 6 drapeaux, donc 6 bits, alors que, dans mes exemples de masques, je travaille sur 8 bits donc 8 drapeaux. Actuellement, 8 drapeaux sont normalisés (un 9e est en projet), dont 2 servent à la gestion de la congestion d'un réseau. La norme en cette matière dit qu'ils sont cumulables avec le drapeau SYN. Donc je ne les regarde pas, afin de les autoriser, d'où les 2 premiers bits à 0 et leur absence de la règle nft.



    Si l'on filtre aussi les connexions sortantes (dans « output »), la règle usuelle, « ct state established,related counter accept », ne laissera pas passer le message SYN ACK de la poignée de main, donc les connexions entrantes ne seront pas établies.

    Il faut ajouter une règle supplémentaire. Pour l'exemple du wiki nftables, qui ouvre le port TCP 8888, cette règle est : tcp sport 8888 ct state invalid,untracked tcp flags & (fin|syn|rst|psh|ack|urg) == (syn|ack) accept. Le ct state invalid,untracked est superfétatoire puisque les connexions suivies et relatives auront été capturées en amont par la règle usuelle, donc, forcément, il ne reste que les connexions invalides ou non-suivies.

    19/02/2026 13:06:09 - permalink -
    - https://wiki.nftables.org/wiki-nftables/index.php/Synproxy
Links per page: 20 50 100
page 1 / 1
Mentions légales identiques à celles de mon blog | CC BY-SA 3.0

Shaarli - The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community