Я столкнулся с ситуацией, когда клиенту нужно внести в черный список набор из чуть менее 1 миллиона отдельных IP-адресов (без подсетей), и производительность сети вызывает беспокойство. Хотя я бы предположил, что правила IPTables будут иметь меньшее влияние на производительность, чем маршруты, это всего лишь предположение.
Есть ли у кого-нибудь веские доказательства или другие основания для предпочтения IPTables или нулевой маршрутизации в качестве решения для занесения в черный список длинных списков IP-адресов? В этом случае все автоматизировано, так что простота использования на самом деле не проблема.
После некоторого тестирования и разработки выяснилось, что ни один из этих вариантов не работает. Похоже, что и поиск маршрутов, и 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/:
Если хочешь
тогда 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 нулевые маршруты по-прежнему являются префиксами, просто очень конкретными)
Возможно, вам придется скомпилировать собственное ядро, чтобы использовать его, но это помогает.
Для потомков: по 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
. Этот инструмент мощный, простой и плохо документирован. Я бы рекомендовал прочитать как можно больше из как можно большего количества источников, поскольку вы можете найти много интересных материалов, разбросанных по сети, которые не являются частью какой-либо официальной документации.