Назад | Перейти на главную страницу

Использовать IPtables или нулевой маршрут для внесения в черный список около 1 миллиона IP-адресов?

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

Есть ли у кого-нибудь веские доказательства или другие основания для предпочтения IPTables или нулевой маршрутизации в качестве решения для занесения в черный список длинных списков IP-адресов? В этом случае все автоматизировано, так что простота использования на самом деле не проблема.

РЕДАКТИРОВАТЬ 26 ноября 11

После некоторого тестирования и разработки выяснилось, что ни один из этих вариантов не работает. Похоже, что и поиск маршрутов, и iptables выполняют линейный поиск по набору правил, и обработка такого количества правил занимает слишком много времени. На современном оборудовании помещение 1M элементов в черный список iptables замедляет работу сервера примерно до 2 дюжин пакетов в секунду. Итак, IPTables и нулевые маршруты отсутствуют.

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

По-видимому, единственное решение для блокировки такого количества IP-адресов - это индексированный поиск на уровне приложения. Не правда ли?


Больше информации:

Сценарий использования в этом случае - блокировка списка IP-адресов «известных нарушителей» от доступа к статическому контенту на веб-сервере. FWIW, блокировка через Apache Deny from работает одинаково медленно (если не более того), как и при линейном сканировании.


К вашему сведению: окончательное рабочее решение заключалось в использовании apache mod_rewrite в сочетании с картой Berkeley DB для поиска по черному списку. Индексированная природа БД Berkeley позволяла масштабировать список с производительностью O (log N).

попробуйте использовать iptables и построить многоуровневое дерево, чтобы уменьшить количество поисков.

iptables -N rules_0_0_0_0_2
iptables -N rules_64_0_0_0_2
iptables -N rules_128_0_0_0_2
iptables -N rules_192_0_0_0_2
iptables -N rules_0_0_0_0_4
iptables -N rules_16_0_0_0_4

iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0/2 -j rules_0_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 64.0.0.0/2 -j rules_64_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 128.0.0.0/4 -j rules_128_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 192.0.0.0/4 -j rules_192_0_0_0_2

iptables -A rules_0_0_0_0_2 -s 0.0.0.0/4 -j rules_0_0_0_0_4
iptables -A rules_0_0_0_0_2 -s 16.0.0.0/4 -j rules_16_0_0_0_4

и так далее - добавление уровней вложенности; очевидно, вам понадобится автоматический способ построения правил, и у вас должны быть цепочки только для сетей, в которых у вас есть один или несколько нарушителей - таким образом вы можете значительно уменьшить количество поисков, которые должны быть выполнены, и я думаю, что это может на самом деле работают.

Это именно то, что ipset для.

Со своего сайта http://ipset.netfilter.org/:

Если хочешь

  • хранить несколько IP-адресов или номеров портов и сравнивать их с коллекцией по iptables одним махом;
  • динамически обновлять правила iptables для IP-адресов или портов без потери производительности;
  • выражать сложные наборы правил на основе IP-адресов и портов с помощью одного правила iptables и получать преимущества от скорости наборов IP

тогда ipset может быть подходящим инструментом для вас.

Он написан членом основной команды netfilter Йожефом Кадлечиком (который также написал цель REJECT), так что это лучший выбор, который я могу придумать.

Он даже включен в последние ядра.

Я сам не тестировал это, но когда я услышал описание вашей проблемы, я сразу подумал: "pf"(как из OpenBSD).

pf имеет концепцию таблицы адресов который может быть именно тем, что вы ищете.

По мнению некоторых очень беглое исследование, которое я провел, кажется, что у этого есть потенциал для масштабирования лучше, чем ipset. В соответствии с глава PF FAQ, посвященная параметрам времени выполненияИз коробки без настройки pf поддерживает до 1000 таблиц, по умолчанию во всех таблицах содержится 200000 записей. (100000, если в системе <100 МБ физической памяти). Это заставляет меня поверить, что по крайней мере стоит подумать о том, чтобы попробовать это проверить, чтобы увидеть, работает ли он на каком-либо полезном уровне.

Конечно, я предполагаю, что вы используете свои серверы в Linux, поэтому вам понадобится отдельный брандмауэр, работающий под управлением какой-либо ОС с pf (например, OpenBSD или FreeBSD). Вы также можете улучшить пропускную способность, полностью отказавшись от какой-либо фильтрации пакетов с отслеживанием состояния.

Вы исследовали использование FIB_TRIE вместо FIB_HASH.

FIB_TRIE должен намного лучше масштабироваться для вашего количества префиксов. (/ 32s нулевые маршруты по-прежнему являются префиксами, просто очень конкретными)

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

FIB_TRIE Примечания

Для потомков: по ipset docs размер набора по умолчанию - 65536, его можно изменить с помощью опций.

maxelem Этот параметр действителен для команды создания всех наборов типов хэша. Он определяет максимальное количество элементов, которое может быть сохранено в наборе, по умолчанию 65536. Пример: ipset create test hash:ip maxelem 2048.

Я поместил это здесь, так как пока не могу комментировать.

Несколько полезных замечаний для тех, кто столкнется с этой проблемой в будущем:

Во-первых, не анализируйте трафик, который вам не нужен. Если вы, например, блокируете TCP-трафик, фильтруйте только SYN-пакеты, таким образом вы попадете в фильтр только один раз за соединение. Ты можешь использовать -m state если хотите, но отслеживание соединений имеет свои накладные расходы, которых следует избегать, если производительность является проблемой.

Во-вторых, добавление миллиона правил в iptables занимает много времени: несколько минут. Если вам нужно отслеживать такое количество объектов, вам, вероятно, лучше держать это в стороне от netfliter. Огромный размер набора правил действительно имеет значение.

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

В-четвертых, что наиболее важно, перенос вашей рабочей нагрузки в пользовательское пространство - неплохая идея. Это позволяет вам написать собственный жесткий код или использовать готовое решение, адаптированное к вашему набору проблем. Как уже упоминалось, мое собственное решение этой проблемы заключалось в использовании поиска в BDB, инициированного системой apache mod_rewrite. Это имело дополнительное преимущество: запускался только один поиск за сеанс и только после того, как был отправлен действительный запрос. В этом случае производительность была чрезвычайно высокой, а стоимость блочного списка была почти незначительной.

Вы можете делать аналогичные манипуляции с пользовательским пространством с помощью iptables, используя -j QUEUE цель в сочетании с libnetfilter_queue. Этот инструмент мощный, простой и плохо документирован. Я бы рекомендовал прочитать как можно больше из как можно большего количества источников, поскольку вы можете найти много интересных материалов, разбросанных по сети, которые не являются частью какой-либо официальной документации.