Comment puis-je vérifier si une règle iptables existe déjà?

41

J'ai besoin d'ajouter une règle à iptables pour bloquer les connexions à un port TCP depuis Internet.

Puisque 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à?

sept ans
la source
Vous pouvez également utiliser ce wrapper, qui fournit une interaction idempotente avec iptables: xyne.archlinux.ca/projects/idemptables
sampablokuper le

Réponses:

44

Il y a une nouvelle -C --checkoption 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"
Marc Maurice
la source
12

La nouvelle -Coption n'est pas satisfaisante car elle est ouverte à une condition de concurrence TOCTTOU (time to check of time). Si deux processus tentent d'ajouter la même règle à peu près au même moment, -Cils ne seront pas protégés contre son ajout deux fois.

Donc, ce n'est vraiment pas mieux que la grepsolution. Un travail de traitement de texte précis sur la sortie de iptables-savepeut fonctionner de manière aussi fiable que possible -C, car cette sortie est un instantané fiable de l’état des tables.

Ce qu'il faut, c'est une --ensureoption qui vérifie et ajoute une règle de manière atomique uniquement si elle n'existe pas déjà. De plus, il serait bien que la règle soit 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 1est 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.

Kaz
la source
1
Puis-je ajouter que cette commande n'est pas satisfaisante pour la simple raison que vous devez identifier exactement la manière dont votre règle a été ajoutée. J'ai fait le test avec ma configuration, et il n'a pas pu trouver de règle car je n'ai pas précisé les mots clés exacts ni les valeurs ...
Fabien Haddadi
Si vous supprimez temporairement une règle, vous risquez de casser quelque chose ...
Mehrdad
5

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;

récidive
la source
1
Ouvrir un trou indésirable dans votre pare-feu, juste pour simuler une commande idempotente, n’est probablement pas une bonne idée. Bien sûr, le trou est censé être temporaire, mais il améliore encore les chances de l'attaquant. Et si quelque chose interrompt l'ajout de la règle de remplacement, le trou pourrait alors persister indéfiniment.
sampablokuper
Bon point @sampablokuper: pour des raisons de sécurité, cette stratégie ne convient probablement que pour les règles ACCEPT et non pour celles de DROP
lucaferrario le
J'ai fini par faire la même chose!
warhansen
4

Juste la liste et la recherche?

iptables --list | grep $ip

... ou peu importe la règle spécifiée. Si vous l'utilisez grep -q, rien ne sera généré et vous pouvez simplement vérifier la valeur de retour avec$?

Jonathon Reinhart
la source
3
Je suggérerais iptables-save|grep $ipplutôt car c'est un format plus facilement analysable, en particulier dans un script. Vous pouvez également vérifier la syntaxe exacte de la commande si vous le souhaitez.
Garrett
1
Aucune de ces réponses ne répond réellement à la question, car elle iptables-save|grep $ippourrait très bien correspondre à plusieurs règles. Peut iptables-save-être pourrait-il être utilisé pour vérifier la spécification complète de la règle, mais cela reste un peu un bidouillage: le format renvoyé par iptables-savepeut ne pas correspondre exactement à la règle du script. iptables-savepeut générer les options dans un ordre différent, ajouter des éléments (du type -m tcp), etc.
larsks
Gardez à l'esprit que vous iptables --listallez essayer de résoudre des ports connus. Donc, assurez-vous de cela avant de grep pour un port.
Fabien Haddadi
0

Pour éviter les règles en double de votre script, ajoutez la ligne ci-dessous.

iptables -C -INPUT -p tcp --dport 8080 --jump ACCEPT || iptables -A -INPUT -p tcp --dport 8080 --jump ACCEPT

Première fois que la commande ci-dessus est exécutée, nous observons le message ci-dessous

iptables: Bad rule (une règle de correspondance existe-t-elle dans cette chaîne?).

Ceci est juste pour information. Mais la seconde moitié de la commande ferait en sorte d’ajouter la règle.

laxman vallandas
la source