Блокируем много IP адресов с помощью ipset и iptables

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

И тут на помощь к нам приходит (барабанная дробь) ipset.
Ipset позволяет использовать большие таблицы IP и MAC адресов, подсетей, номеров портов совместно с iptables (подключение производится через одно правило, в таблице используется хэширование). Возможно быстрое обновление списка целиком.

Официальная страница — ipset.netfilter.org.
ipset представляет из себя модуль ядра ip_set, ряд вспомогательных библиотек и утилиту ipset для задания параметров.
Установка тривиальна, во всех современных дистрибутивах присутствует пакет с одноименным названием.
Модуль ядра можно проверить командой:

# modprobe ipt_set

В Debian 7 и выше:

# apt-get install ipset

В Debian squeeze есть пакет xtables-addons, контент которого дублирует netfilter-extensions, установка:

# aptitude install xtables-addons-source xtables-addons-common
 # m-a -v -t auto-install xtables-addons

В Gentoo соответственно проверить ядро на присутствие модуля, и установить пакет:

# emerge --ask --verbose ipset

CentOS / RHEL (используйте EPEL репозиторий):

# yum install ipset

Списки блокировок.
Где брать? Как отформотировать для использования?
Первое — список для удобства должен состоять только из ip адресов — по одному в строке, в любом текстовом файле.
Не так давно писал про Denyhosts, итогом работы является обновляемый список адресов в файле /etc/hosts.deny, выглядит вот так:

...
 ALL: 222.186.15.139
 ALL: 98.210.197.168
 ...

Тут надо просто выбросить первые 5 символов, вот так например:

# cat /etc/hosts.deny | sed 's/ALL: //' >> denyhosts_blacklists.list

Если необходимо отсортировать уникальные (удалить дубликаты):

# sort denyhosts_blacklists.list  | uniq > sorted_blacklists.listХорошие, обновляемые, готовые к использованию списки можно взять на форуме stopforumspam.com, будьте внимательны — есть суточное ограничение на количество скачиваний.
/…./
Блокируем.
В ipset нет таблиц, а есть set различных типов. Типы позволяют задавать ip адреса из определенной подсети (ipmap тип), связки ip адресов с MAC адресами (macipmap), порты из заданного диапазона (portmap), набор ip адресов или сетей (iphash, nethash), разные комбинации этих set-ов, или даже хранить ip адреса в set только определенное время (iptree). Более подробно советую посмотреть man ipset(8).Для нашей задачи подходит тип iphash. Создаем (N -new) set с именем blacklist, и смотрим его содержимое:

# ipset -N blacklist iphash
 # ipset -L blacklist
 Name: blacklist
 Type: hash:ip
 Revision: 0
 Header: family inet hashsize 1024 maxelem 65536
 Size in memory: 16480
 References: 0
 Members:

Добавляем (A — add) ip адреса blacklist и смотрим (L — list) содержимое set:

# ipset -A blacklist 192.168.0.211
 # ipset -A blacklist 10.10.0.23
 # ipset -L blacklist
 Name: blacklist
 Type: hash:ip
 Revision: 0
 Header: family inet hashsize 1024 maxelem 65536
 Size in memory: 16512
 References: 0
 Members:
 10.10.0.23
 192.168.0.222

Удаляем ip адреса из blacklist set (D — delete):

# ipset -D blacklist 192.168.0.222
 # ipset -L blacklist
 Name: blacklist
 Type: hash:ip
 Revision: 0
 Header: family inet hashsize 1024 maxelem 65536
 Size in memory: 16512
 References: 0
 Members:
 10.10.0.23

Проверяем, есть ли ip в blacklist set (T — test):

# ipset -T blacklist 10.10.0.23
 10.10.0.23 is in set blacklist.

Удаляем все ip адреса из blacklist set (F — flush):

# ipset -F blacklist

Удаляем сам set (X):

# ipset -X blacklist

*** После создания set нам необходимо пропустить его через какую-либо цепочку фильтра iptables.
Вспомним путь прИхождения внешнего пакета в правилах iptables, сверху вниз:

-t raw PREROUTING
 -t mangle PREROUTING
 -t nat PREROUTING
 -t mangle INPUT
 -t filter INPUT

Или смотрим картинку.
Цепочка INPUT обрабатывает запросы, которые идут непосредственно на машину с iptables. Если надо блокировать трафик, который проходит от клиента к серверу через данную машину транзитно, то нужно использовать FORWARD, а то и PREROUTING.
Пример с INPUT:
** Правило не добавляем (-A), а вставляем (-I) в начало цепочки INPUT правил.

# iptables -v -I INPUT -m set --match-set blacklist src -j DROP
 DROP  all opt -- in * out *  0.0.0.0/0  -> 0.0.0.0/0   match-set blacklist src

Т.е. мы подключили модуль set (-m set), потом указали какое совпадение set использовать (—match-set blacklist). src — это флаг, который показывает какие ip сравнивать с set, src (source — источник) или dst (destination — назначение) . Если нужно проверить и src и dst, то флаг задается так src,dst.
Посмотрим цепочку INPUT, на предмет нашего правила ipset (часть вывода):

# iptables -L INPUT -n -v --line-numbers
 Chain INPUT (policy DROP 189 packets, 12489 bytes)
 num   pkts bytes target     prot opt in     out     source               destination
 1        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set blacklist src
 2     108K 2115M ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
 3    18702 1834K ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0
 4     3266  331K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
 5       23   920 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
 6        0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:!0x17/0x02 ctstate
 ...
 ...

Хорошо видно, что наше правило (1) встало на первое место, т.е. пакеты при прохождении не минуют наш blacklist set.Пример с FORWARD и логированием:

# iptables -v -I FORWARD -m set --match-set blacklist src -j DROP
 DROP  all opt -- in * out *  0.0.0.0/0  -> 0.0.0.0/0   match-set blacklist src
 # iptables -v -I FORWARD -m set --match-set blacklist src -j LOG --log-prefix "DROP blacklist entry"
 DROP  all opt -- in * out *  0.0.0.0/0  -> 0.0.0.0/0   match-set blacklist src

** Замечание — почему логирование стоит вторым в инсерте правил? .. потому что мы вставляем правило в начало цепочки, и, казуса, что пакет не дошёл до правила с логированием не случится, в случае если правила мы добавляем, то очередность должна быть обратной, всегда смотрите и проверяйте правила прохождения пакетов:

# iptables -L FORWARD -n -v --line-numbers
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination
 1        0     0 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set blacklist src LOG flags 0 level 4 prefix "DROP blacklist entry"
 2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set blacklist src
 3      983 55096 TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU
 4    19889 2051K ACCEPT     all  --  eth1   ppp0    0.0.0.0/0            0.0.0.0/0
 5    19375   11M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate NEW,RELATED,ESTABLISHED
 6        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID

… — все в порядке: сначала в LOG (1), потом в DROP (2), потом остальные правила.
/../
Удалять правила можно вот так:

# iptables -D INPUT -m set --match-set blacklist src -j DROP
 # iptables -D FORWARD -m set --match-set blacklist src -j DROP
 # iptables -D FORWARD -m set --match-set blacklist src -j LOG --log-prefix "DROP blacklist entry"

** Логи ipset и iptables искать в логах ядра, потому что это «ядерные» модули.
Я использую syslog-ng, kernel логи ловлю в отдельном файле:
Посмотреть через некоторое время, кто попал в сети можно так:

# grep "DROP blacklist entry" /var/log/syslog-ng/kernel.log

Если не знаете где логи можно грубо (может парсить долго!):

# grep -r "DROP blacklist entry" /var/log/*

Все что осталось, — это написать скрипт, который забирает из файла список блокировок.
Каталог для нашего скрипта (можно использовать любой):

# mkdir /etc/blacklist

Скачиваем список ip адресов и распаковываем его (можно автоматизировать, добавив задание в cron):

# cd /etc/blacklist
 # wget http://www.stopforumspam.com/downloads/listed_ip_1.zip
 # unzip listed_ip_1.zip

Примерный вариант скрипта:

#!/bin/bash
 echo -n "Applying blacklist to IPSET..."
 ipset -N blacklist iphash
 xfile=$(cat /etc/blacklist/listed_ip_1.txt)
 for ipaddr in $xfile
 do
 ipset -A blacklist $ipaddr
 done
 echo "...Done"
 echo -n "Applying blacklist to Netfilter..."
 iptables -v -I INPUT -m set --match-set blacklist src -j DROP
 iptables -v -I INPUT -m set --match-set blacklist src -j LOG --log-prefix "DROP blacklist entry"
 echo "...Done"

////**** Вариант скрипта предварительный, хотя много нового в нем не будет, но подправлю позже чуть.

upd: Замечание по правилу iptables — если firewall настроен как положено, (политики DROP), и открыты только нужные порты, следует указать более конкретное правило, для конкретного порта:

iptables -I INPUT  -m set --match-set blacklist src -p TCP --destination-port 80 -j REJECT
 iptables -I INPUT  -m set --match-set blacklist src -p TCP --destination-port 80 -j LOG --log-prefix "DROP blacklist entry INPUT"

… вот что теперь я наблюдаю у себя в логах:

...
 /var/log/syslog-ng/kern.log:Sep 28 22:44:02 HGATE kernel: [71402.569028] DROP blacklist entry INPUTIN=ppp0 OUT= MAC= SRC=218.6.12.99 DST=88.87.92.60 LEN=48 TOS=0x08 PREC=0x60 TTL=114 ID=19401 DF PROTO=TCP SPT=61453 DPT=80 WINDOW=8192 RES=0x00 SYN URGP=0
 /var/log/syslog-ng/kern.log:Sep 29 01:14:18 HGATE kernel: [80411.694498] DROP blacklist entry INPUTIN=ppp0 OUT= MAC= SRC=79.134.234.200 DST=88.87.92.60 LEN=60 TOS=0x08 PREC=0x60 TTL=57 ID=12861 DF PROTO=TCP SPT=54571 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0
 /var/log/syslog-ng/kern.log:Sep 29 01:37:20 HGATE kernel: [81792.214677] DROP blacklist entry INPUTIN=ppp0 OUT= MAC= SRC=176.8.88.134 DST=88.87.92.60 LEN=48 TOS=0x08 PREC=0x60 TTL=123 ID=11004 DF PROTO=TCP SPT=58019 DPT=80 WINDOW=8192 RES=0x00 SYN URGP=0

Можно посмотреть сколько заблокированных (посчитаем количество линий в файле) IP адресов:

# wc -l /etc/blacklist/listed_ip_7.txt
 68611 /etc/blacklist/listed_ip_7.txt
Посмотреть на наш ipset и его размер:
# ipset --list -terse
 Name: blacklist
 Type: hash:ip
 Revision: 0
 Header: family inet hashsize 4096 maxelem 65536
 Size in memory: 142800
 References: 0

Источник http://linuxru.org/linux/324

Запись опубликована в рубрике *CentOS. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Я не спамер This plugin created by Alexei91