J'ai besoin d'ajouter une règle à iptables pour bloquer les connexions à un port TCP depuis Internet.
Étant donné que mon script peut être appelé plusieurs fois et qu'il n'y a pas de script pour supprimer la règle, je souhaite vérifier si une règle iptables existe déjà avant de l'insérer - sinon, il y aura beaucoup de règles dup dans la chaîne INPUT.
Comment puis-je vérifier si une règle iptables existe déjà?
Il y a une nouvelle option -C --check
dans les versions récentes d'iptables.
# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
iptables: Bad rule (does a matching rule exist in that chain?).
# echo $?
1
# iptables -A INPUT -p tcp --dport 8080 --jump ACCEPT
# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
# echo $?
0
Pour les anciennes versions d'iptables, j'utiliserais la suggestion de Garrett:
# iptables-save | grep -- "-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT"
La nouvelle option -C
n'est pas satisfaisante car elle est ouverte à une condition de concurrence selon l'heure de la vérification (TOCTTOU). Si deux processus tentent d'ajouter la même règle à peu près au même moment, -C
ne les empêchera pas de l'ajouter deux fois.
Donc, ce n’est vraiment pas mieux que la solution grep
. Un travail de traitement de texte précis sur la sortie de iptables-save
peut fonctionner de manière aussi fiable que -C
, car cette sortie est un instantané fiable de l'état des tables.
Ce qu'il faut, c'est une option --ensure
qui vérifie et ajoute une règle de manière atomique uniquement si elle n'existe pas déjà. De plus, ce serait bien si la règle est déplacée à la position correcte où une nouvelle règle serait insérée si elle n'existait pas déjà (--ensure-move
). Par exemple, si iptables -I 1
est utilisé pour créer une règle en tête d'une chaîne, mais que cette règle existe déjà à la septième position, la règle existante doit passer à la première position.
Sans ces fonctionnalités, je pense qu'une solution de contournement possible consiste à écrire une boucle de script Shell basée sur ce pseudo-code:
while true ; do
# delete all copies of the rule first
while copies_of_rule_exist ; do
iptables -D $RULE
done
# now try to add the rule
iptables -A $RULE # or -I
# At this point there may be duplicates due to races.
# Bail out of loop if there is exactly one, otherwise
# start again.
if exactly_one_copy_of_rule_exists ; then
break;
fi
done
Ce code pourrait tourner autour; cela ne garantit pas que deux coureurs ou plus seront absents dans un nombre déterminé d'itérations. Des périodes de repos exponentielles aléatoires pourraient être ajoutées pour y remédier.
Cela peut sembler un peu en arrière, mais cela fonctionne pour moi - Essayez d’abord de supprimer la règle.
iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP;
Vous devriez recevoir un message similaire à:
iptables: Bad rule (une règle de correspondance existe-t-elle dans cette chaîne?)
Ensuite, ajoutez simplement votre règle comme d'habitude:
iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP;
Juste la liste et la recherche?
iptables --list | grep $ip
... ou peu importe la règle spécifiée. Si vous utilisez grep -q
, rien ne sera généré et vous pourrez simplement vérifier la valeur de retour avec $?
.