A nova opção -C
não é satisfatória, pois está aberta a uma condição de corrida de tempo de verificação de tempo de uso (TOCTTOU). Se dois processos tentarem adicionar a mesma regra aproximadamente ao mesmo tempo, -C
não os protegerá de adicioná-la duas vezes.
Portanto, realmente não é melhor que a solução grep
. Um trabalho de processamento de texto preciso sobre a saída de iptables-save
pode funcionar de forma confiável como -C
, pois essa saída é um instantâneo confiável do estado das tabelas.
O que é necessário é uma opção --ensure
, que verifica e adiciona atomicamente uma regra somente se ela ainda não existir. Além disso, seria bom se a regra fosse movida para a posição correta onde uma nova regra seria inserida se já não existisse ( --ensure-move
). Por exemplo, se iptables -I 1
for usado para criar uma regra na cabeça de uma cadeia, mas essa regra já existir na sétima posição, a regra existente deverá ser movida para a
primeira posição.
Sem esses recursos, acho que uma solução viável é escrever um loop de script de shell com base nesse pseudo código:
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
Esse código pode girar ao redor; não garante que dois ou mais pilotos estarão fora dentro de um número fixo de iterações. Alguns backoffs aleatórios exponenciais poderiam ser adicionados para ajudar com isso.