Новая -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
Этот код может вращаться; это не гарантирует, что два или более гонщика будут в пределах фиксированного числа итераций. Некоторые рандомизированные экспоненциальные отсрочки могут быть добавлены, чтобы помочь с этим.