Как программно управлять правилами iptables на лету? - PullRequest
37 голосов
/ 21 сентября 2008

Мне нужно запросить существующие правила, а также возможность легко добавлять и удалять правила. Я не нашел API для этого. Я что-то упускаю?

Самое близкое решение, которое я нашел, - это использование iptables-save | iptables-xml для запроса и ручного вызова самой команды iptables для добавления / удаления правил. Другое решение, которое я рассмотрел, - это просто восстановить весь набор правил из базы данных моего приложения и очистить всю цепочку, а затем применить его снова. Но я хочу избежать этого, так как я не хочу отбрасывать какие-либо пакеты - если только не существует способа сделать это атомарно. Мне интересно, есть ли лучший способ.

API в C был бы великолепен; однако, поскольку я планирую встроить это в отдельную программу suid, библиотеки, которые делают это на ЛЮБОМ языке, тоже подойдут.

Ответы [ 8 ]

18 голосов
/ 21 сентября 2008

Из netfilter FAQ :

К сожалению, ответ: Нет.

Теперь вы можете подумать: а как насчет libiptc? Как неоднократно указывалось в списках рассылки, libiptc был НИКОГДА , предназначенный для использования в качестве публичного интерфейса. Мы не гарантируем стабильный интерфейс, и его планируется удалить в следующем воплощении фильтрации пакетов Linux. libiptc слишком низкоуровневый, чтобы его можно было использовать в любом случае.

Мы прекрасно понимаем, что такого API в принципе не хватает, и работаем над улучшением этой ситуации. До тех пор рекомендуется использовать system () или открыть канал в stdin iptables-restore. Последнее даст вам лучшую производительность.

12 голосов
/ 21 сентября 2008

Использование iptables-save и iptables-restore для запроса и регенерации правил - наиболее эффективный способ сделать это. Когда-то они были сценариями оболочки, но теперь это программы на C, которые работают очень эффективно.

Однако я должен отметить, что есть инструмент, который вы можете использовать, который значительно упростит поддержку iptables. Большинство динамических наборов правил действительно повторяются много раз, например:

iptables -A INPUT -s 1.1.1.1 -p tcp -m --dport 22 -j ACCEPT
iptables -A INPUT -s 2.2.2.0/24 -p tcp -m --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j REJECT

Вместо того, чтобы заменять эти правила каждый раз, когда вы хотите изменить какие порты могут обращаться к порту 22 (полезно, например, стук портов), вы можете использовать ipsets. Viz:

ipset -N ssh_allowed nethash
iptables -A ssh_allowed -m set --set ssh_allowed src -p tcp -m --dport 22 -j ACCEPT
ipset -A ssh_allowed 1.1.1.1
ipset -A ssh_allowed 2.2.2.0/24

Наборы могут содержать IP-адреса, сети, порты, MAC-адреса и иметь таймауты в своих записях. (Вы когда-нибудь хотели добавить что-то всего за час?).

Существует даже атомарный способ замены одного набора на другой, поэтому обновление означает создание нового временного набора, а затем его замену в качестве имени существующего набора.

7 голосов
/ 26 марта 2014

Вы можете использовать rfw , который является REST API для iptables. Он сериализует команды iptables из различных потенциально параллельных источников и удаленно выполняет iptables на лету.

rfw предназначен для распределенных систем, которые пытаются обновить правила брандмауэра на нескольких компьютерах, но его также можно запустить на одной машине с интерфейсом localhost. Затем это позволяет избежать затрат на SSL и аутентификацию, так как в этом случае он может работать на обычном HTTP.

Пример команды:

PUT /drop/input/eth0/11.22.33.44

, что соответствует:

iptables -I INPUT -i eth0 -s 11.22.33.44 -j DROP

Вы можете вставлять и удалять правила, а также запрашивать текущий статус, чтобы получить существующие правила в формате JSON:

GET /list/input

Отказ от ответственности: я начал этот проект. Это открытый исходный код под лицензией MIT.

4 голосов
/ 21 сентября 2008

Насколько я понимаю (хотя ни одна ссылка не упоминает об этом), iptables-restore является атомным. В конце, когда читается строка COMMIT, iptables вызывает iptc_commit в libiptc (что во внутреннем интерфейсе не должно использоваться), что затем вызывает setsockopt(SO_SET_REPLACE) с новыми наборами правил.

Звучит так атомно, как только можно: с помощью одного вызова ядра. Однако более осведомленным сторонам предлагается оспаривать это. : -)

Edit: Я могу подтвердить, что ваше описание верно. iptables-restore выполняется как атомарная операция в ядре.

Чтобы быть еще более специфичным , операция "только" является атомарной для каждого процессора. Поскольку мы храним весь BLOB-набор правил на процессор (из-за оптимизации кэша).

3 голосов
/ 21 сентября 2008

Умышленно нет API для управления этими правилами. Ты не должен этого хотеть. Или что-то.

Если вам нужны достаточно динамичные правила, вы заботитесь о производительности выполнения / sbin / iptables, есть другие способы сделать это:

  • Используя что-то вроде «недавнего» совпадения или соответствия IP-набора, вы можете добавлять / удалять IP-адреса из черных / белых списков без изменения набора правил.
  • Вы можете передавать пакеты в пользовательское пространство для фильтрации, используя NFQUEUE
2 голосов
/ 19 апреля 2013

Этим утром я проснулся и обнаружил, что получал атаку на отказ в обслуживании (DOS) из России. Они били меня из десятков блоков IP. У них должно быть либо большой пул IP-адресов, либо какой-то список / служба прокси. Каждый раз, когда я блокировал IP, появлялся другой. Наконец, я искал сценарий и обнаружил, что мне нужно написать собственное решение. Следующее немного агрессивно, но они выполняли мой УРОВЕНЬ НАГРУЗКИ более 200.

Вот быстрый скрипт, который я написал для блокировки DOS в реальном времени.

cat  **"output of the logs"** | php ipchains.php **"something unique in the logs"**

==> PHP Script:

<?php

$ip_arr = array();

while(1)
{
   $line = trim(fgets(STDIN)); // reads one line from STDIN
   $ip = trim( strtok( $line, " ") );

   if( !array_key_exists( $ip, $ip_arr ) )
      $ip_arr[$ip] = 0;

   $regex = sprintf( "/%s/", $argv[1] );

   $cnt = preg_match_all( $regex, $line );

   if( $cnt < 1 ) continue;

   $ip_arr[$ip] += 1;

   if( $ip_arr[$ip] == 1  )
     {
//     printf( "%s\n", $argv[1] );
//     printf( "%d\n", $cnt );
//     printf( "%s\n", $line );

       printf( "-A BLOCK1 -s %s/24 -j DROP\n", $ip );

       $cmd = sprintf( "/sbin/iptables  -I BLOCK1  -d %s/24 -j DROP", $ip );
       system( $cmd );
     }
}

?>

Предположения:

1) BLOCK1 is a Chain already created. 
2) BLOCK1 is a Chain that is run/called from the INPUT CHAIN 
3) Periodically you will need to run "ipchains -S BLOCK1" and put output in /etc/sysconfig file. 
4) You are familiar with PHP 
5) You understand web log line items/fields and output.
1 голос
/ 23 сентября 2013

Это пример использования bash и iptables для динамического блокирования хакеров, злоупотребляющих sshd в CentOS. В этом случае я настроил sshd для запрета входа в систему с паролем (разрешает ключи). Я смотрю в / var / log / secure записи "Bye Bye", что является вежливым способом sshd сказать f-off ...

IP=$(awk '/Bye Bye/{print $9}' /var/log/secure |
     sed 's/://g' |sort -u | head -n 1)

[[ "$IP" < "123" ]] || {

  echo "Found $IP - blocking it..." >> /var/log/hacker.log

  /sbin/iptables -A INPUT -s $IP -j DROP

  service iptables save

  sed -i "/$IP/d" /var/log/secure

}

Я запускаю это в цикле каждую секунду, или минуту, или что угодно, что делает меня счастливым. Я проверяю значение $ IP, чтобы убедиться, что оно нашло полезное значение, и в этом случае я вызываю iptables, чтобы удалить его, и использую sed для очистки файла журнала $ IP, чтобы запись больше не добавлялась.

Я делаю небольшую предварительную обработку (не показана) для внесения в белый список некоторых важных IP-адресов, которые всегда действительны и могут иметь проблемы с подключением (из-за ошибки пользователя).

Время от времени я сортирую список фильтров iptables и создаю из них диапазоны IP-адресов (используя другой сценарий - и когда этот флажок установлен, обычно это диапазоны IP-адресов из Индии, Китая и России). Таким образом, мой общий набор правил фильтрации iptables остается от 50 до 500 записей; ipset не сильно улучшается в этом коротком списке.

0 голосов
/ 21 сентября 2008

MarkR верно, вы не должны этого делать. Самый простой способ - вызвать iptables из скрипта или написать конфигурацию iptables и «восстановить» ее.

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

В netfilter для Linux также есть некоторые файлы include в / usr / include / netfilter *. Это несколько низкоуровневые функции. Это то, что использует iptables. Это настолько близко к API, насколько это возможно без iptables.

Но этот API "грязный". Имейте в виду, что он был разработан для использования только iptables. Это не очень хорошо документировано, вы можете столкнуться с очень специфическими проблемами, API может довольно быстро измениться без какого-либо предупреждения, поэтому обновление вероятно сломает ваш код и т. Д.

...