La nouvelle -C
n'est pas satisfaisante, car elle ouvre la voie à une condition de course entre le moment de la vérification et le moment de l'utilisation (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.
Il n'est donc pas plus performant que le grep
solution. Un travail de traitement de texte précis sur la sortie de iptables-save
peut fonctionner de manière aussi fiable que -C
puisque ce résultat est un instantané fiable de l'état des tables.
Ce qu'il faut, c'est un --ensure
qui vérifie atomiquement et ajoute une règle uniquement si elle n'existe pas déjà. De plus, il serait bon 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 1
est utilisé pour créer une règle à la tête d'une chaîne, mais que cette règle existe déjà en septième position, alors la règle existante doit être déplacée dans la section première position.
Sans ces fonctionnalités, je pense qu'une solution de contournement possible consiste à écrire une boucle Shell 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 peut tourner en rond ; il ne garantit pas que deux coureurs ou plus seront éliminés dans un nombre fixe d'itérations. Il est possible d'ajouter des périodes de sommeil exponentielles aléatoires pour y remédier.