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

22

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

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

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

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

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

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


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

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


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

tylerl
источник
5
Разве ipset ( ipset.netfilter.org ) не предназначен для решения подобных проблем?
Джимми Хедман
@JimmyHedman: Вы должны сделать это ответом. А затем добавьте предложение в бенчмарк, выполняя все 3 способа :)
MikeyB
Мне интересно, можете ли вы дать немного больше информации о том, какую проблему вы пытаетесь решить? Возможно, блокировка IP-адресов 1M не является способом решения проблемы?
SpacemanSpiff
Было бы очень полезно узнать, почему вы хотите заблокировать такое количество адресов, и хотите ли вы фильтровать входящий или форвардный трафик.
Джулиано,
Здесь вы можете увидеть, как ipset делает правила iptables примерно в 11 раз быстрее, чем обычные правила iptables. daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset Надеюсь, что это поможет.
Чужой Торрес

Ответы:

15

попробуйте использовать 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

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

PQD
источник
Это звучит так, как будто это может работать, эффективно уменьшая временную сложность поиска правил брандмауэра с O (n) до O (log n), эффективно создавая дерево поиска в iptables.
Пер фон Цвайгбергк
Если вы решите пойти по этому пути, вероятно, было бы полезно использовать какой-либо алгоритм для построения сбалансированного двоичного дерева поиска из списка IP-адресов, а затем просто вывести структуру этого дерева поиска в виде набора правил IPtables.
Пер фон Цвайгбергк
@Per von Zweigbergk - действительно ... или просто подрежьте дерево рано, где нет необходимости делать более глубокие поиски. хотя загрузка этого безбожного количества правил займет много времени.
PQD
Это очень хороший подход. Очевидно, что для его обслуживания требуется немного обработки, но я думаю, что это правильная идея.
Tylerl
3
@pQd после предыдущих сбоев с iptables и др., я реализовал решение в apache, используя RewriteMap с базой данных Berkeley. Но мой самый быстрый механизм, использующий iptables в цикле, загружал около 100 правил в секунду, в то время как iptables-restore выполнял весь набор за 4 секунды. Это на первоклассном настольном компьютере. Механизм RewriteMap незаметно влияет на производительность.
Tylerl
11

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

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

Если хочешь

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

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

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

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

cstamas
источник
Насколько я видел, ipset достигает максимума в 65k IP-адресов. Есть ли какой-либо тип набора, который может обрабатывать записи 1M?
Tylerl
7
Если вы используете тип hash: ip set, у вас может быть очень большое количество адресов. Я пробовал 1000000, и производительность была довольно хорошей. Если вы установили правило -state -stte ESTABLISHED -m state перед проверкой своего набора, вы можете убедиться, что проверяете этот набор только на новых соединениях, что повысит производительность при работе с большим количеством пакетов.
Мэтью Ифе
Стоит отметить, что использование памяти ipset с адресами 1M начинает увеличиваться. Согласно этому сообщению в списке рассылки netfilter, текущая формула 2015 года для размера хэша ipset составляет H * 40byte + (N/4 + N%4) * 4 * element sizeоколо 64 МБ для 1M адресов в хэш-слоте 1,5 м. Использование решения apache / berkdb сохраняет данные на диске и загружает только страницы с активными адресами.
М Конрад
5

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

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

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

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

Пер Цвайгбергк
источник
Преобразование серверной архитектуры клиента в BSD на самом деле не вариант. Хотя бы думая из коробки, по крайней мере.
Tylerl
2
Вам не нужно будет преобразовывать всю серверную архитектуру в BSD, достаточно создать брандмауэр, чтобы поставить его перед реальным сервером. (Достаточно легко сделать в виртуальной машине.)
Per von Zweigbergk
2

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

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

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

FIB_TRIE Примечания

Джоэл К
источник
2

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

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

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

plitter
источник
1

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

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

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

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

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

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

tylerl
источник