Как я могу проверить, существует ли правило iptables?

41

Мне нужно добавить правило в iptables, чтобы заблокировать подключения к TCP-порту из Интернета.

Поскольку мой сценарий может вызываться несколько раз, а сценарий для удаления правила отсутствует, я хочу проверить, существует ли правило iptables, прежде чем его вставить, иначе в цепочке INPUT будет много правил dup.

Как я могу проверить, существует ли правило iptables?

sevenever
источник
В качестве альтернативы, используйте эту оболочку, которая обеспечивает идемпотентное взаимодействие iptables: xyne.archlinux.ca/projects/idemptables
sampablokuper

Ответы:

44

В -C --checkпоследних версиях 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

Для более старых версий iptables я бы использовал предложение Гарретта:

# iptables-save | grep -- "-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT"
Марк Морис
источник
12

Новая -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

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

Kaz
источник
1
Могу ли я добавить, что эта команда довольно неудовлетворительна по той простой причине, что вы должны точно указать, как было добавлено ваше правило. Я сделал тест с моей настройкой, и он не смог найти правило, потому что я не указал точные ключевые слова и значения ...
Фабьен Хаддади,
Если вы временно удалите правило, тогда вы можете что-то нарушить ...
Mehrdad
5

Это может показаться немного отсталым, но это работает для меня - попробуйте сначала удалить правило.

iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP;

Вы должны получить сообщение, похожее на:

iptables: неверное правило (существует ли соответствующее правило в этой цепочке?)

Затем просто добавьте ваше правило как обычно:

iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP;

рекурсию
источник
1
Открытие нежелательной дыры в брандмауэре, просто для симуляции идемпотентной команды, вероятно, не очень хорошая идея. Конечно, дыра должна быть временной, но она все же увеличивает шансы атакующего. И если что-то прерывает добавление правила замены, то дыра может сохраняться бесконечно долго.
Сампаблокупер
Хороший вопрос @sampablokuper: эта стратегия, вероятно, подходит только для правил ПРИНЯТЬ, а не для DROP, из соображений безопасности
lucaferrario
Я закончил тем же!
warhansen
4

Просто список и поиск?

iptables --list | grep $ip

... или, тем не менее, вы указали правило. Если вы используете grep -qего, ничего не выведите, и вы можете просто проверить возвращаемое значение с помощью$?

Джонатон Рейнхарт
источник
3
Я бы предложил iptables-save|grep $ipвместо этого, так как это более легко анализируемый формат, особенно в сценарии. Вы также можете проверить точный синтаксис команды, если хотите.
Гарретт
1
Ни один из них на самом деле не отвечает на вопрос, потому что iptables-save|grep $ipвполне может соответствовать нескольким правилам. Возможно, iptables-saveможно использовать для проверки полной спецификации правила, но это все же немного хак: формат, возвращаемый, iptables-saveможет не полностью соответствовать правилу в сценарии. iptables-saveможет генерировать параметры в другом порядке, добавлять вещи (например -m tcp) и так далее.
Жаворонки
Имейте в виду, что iptables --listпопытаются разрешить известные порты. Так что убедитесь в этом, прежде чем grep для порта.
Фабьен Хаддади,
0

Чтобы избежать дублирования правил в вашем скрипте, добавьте строку ниже.

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

При первом запуске вышеуказанной команды мы увидим следующее сообщение

iptables: неверное правило (существует ли соответствующее правило в этой цепочке?).

Это только для информации. Но вторая половина команды обеспечит добавление правила.

Laxman Vallandas
источник