Iptables et ipset
Préférez nftables sur une installation neuve. Je laisse ça ici pour retrouver les infos sur les vieux coucous.
Installer
apt install ipset iptable netfilter-persistent ipset-persistent iptables-persistent whois python3-systemd
*-persistent permet de charger des règles au démarrage, en principe situées dans /etc/iptables/
.
Règles de base
Actuellement mon routeur me coince en ipv4 (/etc/iptables/rules.v4
) donc mes règles ne concernent que ça, il faudra adapter pour ipv6.
Son contenu actuel :
# source https://antoinelounis.com/informatique/securite/configuration-fail2ban-iptables-debian-raspberry/
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Allow internal traffic on the loopback device
-A INPUT -i lo -j ACCEPT
# Continue connections that are already established or related to an established connection
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Drop non-conforming packets, such as malformed headers, etc.
-A INPUT -m conntrack --ctstate INVALID -j DROP
# SSH
-A INPUT -p tcp --dport 226 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# HTTP + HTTPS
-A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Email (postfix + dovecot)
# 25 = smtp, 587 = submission and 993 = IMAPS, 143 imap, 110 pop
-A INPUT -p tcp -m multiport --dports 25,587,993,110,143 -j ACCEPT
# NTP
-A INPUT -p udp --dport 123 -j ACCEPT
# Chain for preventing ping flooding - up to 6 pings per second from a single
# source, again with log limiting. Also prevents us from ICMP REPLY flooding
# some victim when replying to ICMP ECHO from a spoofed source.
-N ICMPFLOOD
-A ICMPFLOOD -m recent --name ICMP --set --rsource
#-A ICMPFLOOD -m recent --name ICMP --update --seconds 1 --hitcount 6 --rsource --rttl -m limit --limit 1/sec --limit-burst 1 -j LOG --log-prefix "iptables[ICMP-flood]>
-A ICMPFLOOD -m recent --name ICMP --update --seconds 1 --hitcount 6 --rsource --rttl -j DROP
-A ICMPFLOOD -j ACCEPT
# Permit useful IMCP packet types.
# Note: RFC 792 states that all hosts MUST respond to ICMP ECHO requests.
# Blocking these can make diagnosing of even simple faults much more tricky.
# Real security lies in locking down and hardening all services, not by hiding.
-A INPUT -p icmp --icmp-type 0 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p icmp --icmp-type 3 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ICMPFLOOD
-A INPUT -p icmp --icmp-type 11 -m conntrack --ctstate NEW -j ACCEPT
# Drop all incoming malformed NULL packets
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# Drop syn-flood attack packets
-A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
# Drop incoming malformed XMAS packets
-A INPUT -p tcp --tcp-flags ALL ALL -j DROP
COMMIT
# Usage des tables déclarées avec ipset
#-A INPUT -m set --match-set blocklist_ip src -j DROP
# Ça, ça ne veut pas...
#rejeter tout le reste
-A INPUT -j REJECT --reject-with icmp-port-unreachable
Commandes Iptables utiles
Lister “tout” en vrac :
iptables -S
Lister tout en format tableau verbeux, avec numéros de ligne
iptables -L -n -v --line-numbers
Juste dans un des tableaux (ici INPUT)
iptables -L INPUT --line-numbers
Sauf que ce n'est pas “tout”, genre pour lister les règles nat :
iptables -t nat -S
Enlever une règle d'après son numéro de ligne
iptables -D INPUT 14
Restaurer des règles
iptables-restore /etc/iptables/rules.v4
Quelques explications
Différence entre -I et -A
-I
signifie “insérer la règle à la ligne n° X” ; sans préciser de numéro, la règle se retrouve au début et a donc la priorité sur tout autre.-A
indique d'ajouter donc ce sera à la suite du reste des règles.
Bref, quand on a un fichier qui charge les règles, elles sont forcément les unes après les autres, -A
est indiqué. Si on teste une règle, alors -I
peut être plus pertinent.
DROP ou REJECT --reject-with icmp-port-unreachable
DROP
ignore complètement le paquet (comme si le serveur n'existait pas). Il ne renvoie pas de message, ce qui évite les attaques où on force le serveur à envoyer des messages icmp à un autre serveur par exemple.REJECT –reject-with icmp-port-unreachable
renvoie un message icmp disant que le port est fermé (comme si le service qui écoute sur ce port n'était pas lancé et que le port était inutilisé).
Ordre des règles
Les règles sont appliquées dans l'ordre.
Donc il faut que les commandes d'ipset et fail2ban soient avant celles qui acceptent une connexion :
- On regarde si l'un de ces logiciels dit qu'il faut bloquer l'ip
- Si oui, elle dégage
- Si non, on passe à la règle suivante
- La règle suivante étant “on accepte”.
Sinon, ça serait :
- On accepte la connexion
- On regarde si fail2ban… ah ben non, forcément, ça ne marche pas, puisque la connexion est acceptée.
Ipset
Créer une entrée pour toutes les ip qui vont être renvoyées dans les limbes (adapter le nom blocklist_ip
):
ipset create blocklist_ip hash:ip
Faire en sorte qu'iptables utilise cette liste d'ipset (appelée chaine) :
iptables -A INPUT -m set --match-set blocklist_ip src -j DROP
Et à présent pour alimenter la liste des ip définitivement bannies, ça sera ce genre de commande (remplacer $ip
par l'ip) :
ipset add blocklist_ip $ip
Commandes ipset
Pour lister les ip et “chaînes” :
ipset list
Pour juste lister les chaînes :
ipset list -n
Pour enlever une des ip sur notre chaîne “bloclist_ip” :
ipset del blocklist_ip X.X.X.X
Rendre ça persistant au démarrage
C'est netfilter qui gère ça.
S'assurer que les règles iptable et ipset sont bonnes, et que netfilter-persistent est démarré et en mode “enable”
iptables -L -n -v ipset list systemctl status netfilter-persistent
Pour garder les ip bannies dans ipset, il faut aussi faire cette commande (à renouveler quand on ajoute des ip) :
ipset save
Sauver le tout :
netfilter-persistent save