Новая опция -C
не является удовлетворительной, потому что она открыта для состояния гонки «время проверки на время использования» (TOCTTOU). Если два процесса пытаются добавить одно и то же правило в одно и то же время, -C
не защитит их от добавления его дважды.
Так что это действительно не лучше, чем решение grep
. Точное задание обработки текста над выводом iptables-save
может работать так же надежно, как и -C
, поскольку этот вывод является надежным снимком состояния таблиц.
Необходим параметр --ensure
который атомарно проверяет и добавляет правило, только если оно еще не существует. Более того, было бы хорошо, если бы правило было перемещено в правильную позицию, в которую было бы вставлено новое правило, если оно еще не существовало (--ensure-move
). Например, если iptables -I 1
используется для создания правила в начале цепочки, но это правило уже существует в седьмой позиции, то существующее правило должно переместиться в первую позицию.
Без этих функций, я думаю, что возможный обходной путь - написать цикл сценария оболочки на основе этого псевдокода:
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
Этот код может вращаться; это не гарантирует, что два или более гонщика будут в пределах фиксированного числа итераций. Некоторые рандомизированные экспоненциальные отсрочки могут быть добавлены, чтобы помочь с этим.