37

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

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

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

4 ответа4

42

В последних версиях iptables появилась новая опция -C --check .

# 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"
10

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

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

5

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

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

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

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

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

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

3

Просто перечислите и ищите это?

iptables --list | grep $ip

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .