Du point de vue conception, cette partie est consacrée au filtrage réseau sans état. Les trois sections proposent des règles qui demandent un traitement le plus rapide possible et le moins coûteux possible en ressources.
Le but de cette partie est de mettre en place les fonctions de
filtrage de base communes à tous les routeurs de la topologie. Ceci
implique que le paquet nftables
soit installé et que le service systemd
soit activé sur tous routeurs
Spoke
sudo apt -y install nftables
sudo systemctl enable --now nftables
Voici une description des fonctions à mettre en œuvre dans cette section.
- Protection contre l'usurpation des adresses sources
-
Pour bloquer tous les paquets provenant d'un réseau extérieur avec des adresses IP sources appartenant à un réseau intérieur, on implante une chaîne
rpfilter
dans la tableraw
qui assure un filtrage sans état. Voir Network Ingress Filtering: Defeating Denial of Service Attacks which employ IP Source Address Spoofing.Les tests de validation de ces mécanismes sont faciles à réaliser sur les routeurs Spoke. Tout paquet qui arrive via l'interface PPP et dont l'adresse source IPv4 ou IPv6 appartient au réseau d'hébergement (VLAN vert) doit être jeté. On protège ainsi les routeurs contre les dénis de services.
- Protection contre les dénis de services ICMP
-
Les routeurs doivent s'assurer que le volume de trafic qui est présenté en entrée est compatible avec un fonctionnement nominal des services.
- Protection contre les robots de connexion au service SSH
-
Les routeurs ont besoin d'un accès d'administration à distance via SSH. Pour autant, cet accès doit être protégé contre les tentatives d'intrusion par dictionnaire de couples d'authentifiants.
L'outil fail2ban fourni avec le paquet du même nom introduit une chaîne de filtrage dédiée à ces tentatives d'intrusion.
Voici le jeu de règles à implanter dans le fichier /etc/nftables.conf
sur les deux routeurs
Spoke pour activer la protection contre
l'usurpation d'adresses réseau source.
#!/usr/sbin/nft -f flush ruleset table inet raw { chain rpfilter { type filter hook prerouting priority raw; policy accept; iifname "ppp0" fib saddr . iif oif 0 counter packets 0 bytes 0 drop } }
Important | |
---|---|
Dans le but de faciliter les tests de validation, le trafic “malveillant” est émis depuis le routeur Hub. Sur ce routeur, nous avons la possibilité d'installer tous les outils et de faire toutes les manipulations possibles pour falsifier les adresses sources. De plus, on contrôle le plan d'adressage. Si ce n'était pas le cas, il faudrait utiliser une autre machine virtuelle et les erreurs auraient des conséquences plus beaucoup plus graves. |
Q13. |
Comment définir le rôle de la table
Rechercher la présentation de cette table dans la documentation
|
|||
La table |
||||
Q14. |
Comment expliquer l'utilisation de la
correspondance Rechercher le mot clé |
|||
La règle |
||||
Q15. |
Comment afficher la liste des règles de
filtrage de la table Rechercher dans les pages de manuels de la commande nft les options relatives aux listes. |
|||
C'est l'option Voici un exemple dans le contexte de la maquette sur un routeur
Spoke. Un jeu de règles a déjà été
inséré dans la table sudo nft list table inet raw table inet raw { chain rpfilter { type filter hook prerouting priority raw; policy accept; iifname "ppp0" fib saddr . iif oif 0 counter packets 10 bytes 280 drop } }
|
||||
Q16. |
Comment valider la fonction de blocage des tentatives d'usurpation d'adresses entre le routeur Hub et les routeurs Spoke ? Pour falsifier les adresses réseau source, nous devons distinguer les deux protocoles.
|
|||
On débute les tests avec le protocole IPv4 et la commande hping3. Voici un exemple de test effectué sur le routeur Hub dans lequel l'option sudo hping3 -1 -a 10.0.10.12 --fast -c 10 10.0.10.10 HPING 10.0.10.10 (ppp0 10.0.10.10): icmp mode set, 28 headers + 0 data bytes
--- 10.0.10.10 hping statistic ---
10 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
Côté routeur Hub, on constate qu'aucune réponse n'a été reçue. Côté routeur Spoke, on affiche le jeu des règles de filtrage actif et on relève les valeurs des compteurs de paquets jetés. sudo nft list table inet raw table inet raw {
chain rpfilter {
type filter hook prerouting priority raw; policy accept;
iifname "ppp0" fib saddr . iif oif 0 counter packets 20 bytes 560 drop
}
}
Dans l'exemple ci-dessus, 20 paquets ont été jetés. Pour le protocole IPv6, il n'existe pas de solution équivalente à l'utilisation de la commande hping3. De plus, le fait d'utiliser une session PPP pour acheminer le trafic ne facilite pas les tests. C'est la raison pour laquelle on utilise un autre
artifice : une interface de type Voici comment créer une interface et lui ajouter une adresse. On
commence par charger le module sudo modprobe -v dummy numdummies=1 sudo ip link set dev dummy0 up On peut maintenant ajouter une adresse IPv6 appartenant au réseau d'hébergement situé au-delà du routeur Spoke à cette interface. sudo ip -6 addr add fda0:7a62:a::e/64 dev dummy0 On modifie la table de routage pour s'assurer que les paquets partiront en direction de la session PPP. sudo ip -6 route del fda0:7a62:a::/64 dev dummy0 sudo ip -6 route add fda0:7a62:a::/64 dev dummy0 metric 2048 On vérifie la solution d'acheminement du trafic à destination du réseau d'hébergement des conteneurs. ip -6 route get fda0:7a62:a::a
fda0:7a62:a::a from :: dev ppp0 src fda0:7a62:a::e metric 1024 pref medium
Il ne reste plus qu'à lancer des requêtes ICMP6 avec cette adresse source. sudo ping6 -c 10 fda0:7a62:a::a PING fda0:7a62:a::a (fda0:7a62:a::a) from fda0:7a62:a::e dummy0: 56 data bytes
--- fda0:7a62:a::a ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 9210ms
Là encore, aucune réponse n'est revenue et c'est heureux ! Si on relève le compte des paquets jetés côté routeur Spoke, on voit que toutes les requêtes sont
tombées dans la règle de la table sudo nft list table inet raw table inet raw {
chain rpfilter {
type filter hook prerouting priority raw; policy accept;
iifname "ppp0" fib saddr . iif oif 0 counter packets 40 bytes 4160 drop
}
}
|
||||
Q17. |
Comment utiliser la fonction Rechercher la clé |
|||
Il existe un réglage du sous-système réseau du noyau avec la clé
rp_filter - INTEGER 0 - No source validation. 1 - Strict mode as defined in RFC3704 Strict Reverse Path Each incoming packet is tested against the FIB and if the interface is not the best reverse path the packet check will fail. By default failed packets are discarded. 2 - Loose mode as defined in RFC3704 Loose Reverse Path Each incoming packet's source address is also tested against the FIB and if the source address is not reachable via any interface the packet check will fail. Current recommended practice in RFC3704 is to enable strict mode to prevent IP spoofing from DDos attacks. If using asymmetric routing or other complicated routing, then loose mode is recommended. The max value from conf/{all,interface}/rp_filter is used when doing source validation on the {interface}. Default value is 0. Note that some distributions enable it in startup scripts. On peut fixer la clé à 1 et lancer un test avec une série d'adresses IPv4 source aléatoires. sudo sysctl -w net.ipv4.conf.all.rp_filter=1 Voici un exemple de commande qui provoquera un nombre de blocages aléatoire en fonction des correspondances. sudo hping3 -1 --rand-source --fast -c 100 10.0.10.10 Dans ce cas, c'est la fonction de protection du noyau qui a détecté des paquets “martiens” pour lesquels il n'existe aucune solution de routage. journalctl -n 500 -f --grep martian spoke1 kernel: IPv4: martian source 10.0.10.10 from 239.9.60.83, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 225.61.235.216, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 234.137.124.42, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 225.151.17.117, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 227.163.239.170, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 227.27.22.34, on dev ppp0 spoke1 kernel: IPv4: martian source 10.0.10.10 from 233.200.216.31, on dev ppp0 |
Dans cette section, on reprend le jeu de règles précédentes et on le complète avec la limitation du nombre de requêtes ICMP entrantes.
Le trafic “malveillant“ est toujours généré sur le routeur Hub à destination des conteneurs des réseaux d'hébergement des sites distants.
Voici une nouvelle copie du fichier /etc/nftables.conf
qui contient le jeu de règles
à ajouter sur les deux routeurs Spoke
pour assurer la protection contre les dénis de service par
saturation de requêtes ICMP.
#!/usr/sbin/nft -f flush ruleset table inet raw { # BCP38 Rules chain rpfilter { type filter hook prerouting priority raw; policy accept; iifname "ppp0" fib saddr . iif oif 0 counter packets 0 bytes 0 drop } # ICMP Rate Limiting Rules chain icmpfilter { type filter hook prerouting priority raw; policy accept; icmp type echo-request limit rate 10/second burst 5 packets counter accept icmp type echo-request counter drop } }
Q18. |
À quelle chaîne prédéfinie de la table
Consulter la représentation graphique
Packet Flow in Netfilter et repérer
les chaînes prédéfinies de la table |
Il s'agit de la chaîne |
|
Q19. |
Comment qualifier le fonctionnement des règles de limitation du nombre de nouvelles requêtes ICMP avec IPv4 ? Rechercher les options de la commande hping3 qui permettent de générer un envoi de requêtes ICMP en grand nombre. |
Voici un exemple d'envoi de requêtes ICMP en nombre à destination du deuxième conteneur hébergé sur le premier routeur Spoke. sudo hping3 -1 --flood -c 10 10.0.10.11 Si le temps d'exécution de ces émission paraît trop long, il ne faut pas hésiter à interrompre l'émission avec Ctrl+C. HPING 10.0.10.11 (ppp0 10.0.10.11): icmp mode set, 28 headers + 0 data bytes hping in flood mode, no replies will be shown --- 10.0.10.11 hping statistic --- 61492309 packets transmitted, 0 packets received, 100% packet loss round-trip min/avg/max = 0.0/0.0/0.0 ms Les résultats de cette commande montrent que le mécanisme de protection a bien fonctionné. On doit aussi vérifier qu'une émission “raisonnable“ de requêtes ICMP donne des résultats corrects. ping -qc 10 10.0.10.11 PING 10.0.10.11 (10.0.10.11) 56(84) bytes of data.
--- 10.0.10.11 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9013ms
rtt min/avg/max/mdev = 1.056/1.279/2.034/0.268 ms
Côté routeur Spoke “cible”, on peut relever les compteurs des règles de traitement ICMP et constater qu'un grand nombre de paquets ont été jetés. sudo nft list table inet raw table inet raw { chain rpfilter { type filter hook prerouting priority raw; policy accept; iifname "ppp0" fib saddr . iif oif 0 counter packets 0 bytes 0 drop } chain icmpfilter { type filter hook prerouting priority raw; policy accept; icmp type echo-request limit rate 10/second burst 5 packets counter packets 5378 bytes 150584 accept icmp type echo-request counter packets 90460174 bytes 2532884872 drop } } |
|
Q20. |
Comment qualifier le fonctionnement des règles de limitation du nombre de nouvelles requêtes ICMP avec IPv6 ? Rechercher les options de la commande ping qui permettent de générer un flux de saturation ICMPv6. On s'intéresse plus particulièrement aux options |
Voici un exemple de tentative de saturation à destination du deuxième conteneur du réseau d'hébergement du premier routeur Spoke. sudo ping -6 -c100 -i 0.0005 -f fda0:7a62:a::b En réponse à cette commande, on voit que le taux de perte de paquets est important. PING fda0:7a62:a::b (fda0:7a62:a::b) 56 data bytes
..................................................................................
--- fda0:7a62:a::b ping statistics ---
100 packets transmitted, 18 received, 82% packet loss, time 1315ms
rtt min/avg/max/mdev = 0.316/0.845/2.057/0.334 ms, ipg/ewma 13.281/0.931 ms
Côte routeur “cible”, on relève à nouveau un grand nombre de paquets jetés. sudo nft list table inet raw table inet raw { chain rpfilter { type filter hook prerouting priority raw; policy accept; iifname "ppp0" fib saddr . iif oif 0 counter packets 0 bytes 0 drop } chain icmpfilter { type filter hook prerouting priority raw; policy accept; icmpv6 type echo-request limit rate 10/second burst 5 packets counter packets 93 bytes 9672 accept icmpv6 type echo-request counter packets 485 bytes 50440 drop } } Comme on l'a fait pour le protocole IPv4, on vérifie qu'on obtient un retour correct suite à des requêtes émises “à un rythme normal”. ping -qc10 fda0:7a62:a::b PING fda0:7a62:a::b (fda0:7a62:a::b) 56 data bytes
--- fda0:7a62:a::b ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9018ms
rtt min/avg/max/mdev = 0.839/1.055/1.191/0.097 ms |
Comme dans les deux sections précédentes, l'évaluation du mécanisme de protection se joue entre le routeur Hub et un routeur Spoke. On verra que le cas d'une protection contre les robots SSH, celle-ci doit s'appliquer sur tous les systèmes qui autorisent une connexion par mot de passe.
Le sujet de ce document étant l'étude du filtrage réseau, on s'intéresse ici à la génération automatique de règles suite à la violation des critères définis dans l'application de gestion des tentatives de connexion : fail2ban.
En appliquant cette configuration du service fail2ban sur les trois routeurs, on dispose d'une base de protection contre les attaques de type brute force sur l'authentification au service SSH.