
Вопросы борьбы со спамерами, ботами и прочей нечистью всегда актуальны. Хорошо когда список небольшой, с помощью iptables это решается элементарно, но вот когда адресов пару тысяч ... тут уже приходится не сладко.
И тут на помощь к нам приходит (барабанная дробь) ipset.
Ipset позволяет использовать большие таблицы IP и MAC адресов, подсетей, номеров портов совместно с iptables (подключение производится через одно правило, в таблице используется хэширование). Возможно быстрое обновление списка целиком.
Официальная страница - ipset.netfilter.org.
ipset представляет из себя модуль ядра ip_set, ряд вспомогательных библиотек и утилиту ipset для задания параметров.
Установка тривиальна, во всех современных дистрибутивах присутствует пакет с одноименным названием.
Модуль ядра можно проверить командой:
В Debian 7 и выше:
В Debian squeeze есть пакет xtables-addons, контент которого дублирует netfilter-extensions, установка:
# m-a -v -t auto-install xtables-addons
В Gentoo соответственно проверить ядро на присутствие модуля, и установить пакет:
CentOS / RHEL (используйте EPEL репозиторий):
Списки блокировок.
Где брать? Как отформотировать для использования?
Первое - список для удобства должен состоять только из ip адресов - по одному в строке, в любом текстовом файле.
Не так давно писал про Denyhosts, итогом работы является обновляемый список адресов в файле /etc/hosts.deny, выглядит вот так:
ALL: 222.186.15.139
ALL: 98.210.197.168
...
Тут надо просто выбросить первые 5 символов, вот так например:
Если необходимо отсортировать уникальные (удалить дубликаты):
Хорошие, обновляемые, готовые к использованию списки можно взять на форуме 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 -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 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 -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):
10.10.0.23 is in set blacklist.
Удаляем все ip адреса из blacklist set (F - flush):
Удаляем сам set (X):
*** После создания set нам необходимо пропустить его через какую-либо цепочку фильтра iptables.
Вспомним путь прИхождения внешнего пакета в правилах iptables, сверху вниз:
-t mangle PREROUTING
-t nat PREROUTING
-t mangle INPUT
-t filter INPUT
Или смотрим картинку.
Цепочка INPUT обрабатывает запросы, которые идут непосредственно на машину с iptables. Если надо блокировать трафик, который проходит от клиента к серверу через данную машину транзитно, то нужно использовать FORWARD, а то и PREROUTING.
Пример с INPUT:
** Правило не добавляем (-A), а вставляем (-I) в начало цепочки INPUT правил.
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 (часть вывода):
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 и логированием:
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
** Замечание - почему логирование стоит вторым в инсерте правил? .. потому что мы вставляем правило в начало цепочки, и, казуса, что пакет не дошёл до правила с логированием не случится, в случае если правила мы добавляем, то очередность должна быть обратной, всегда смотрите и проверяйте правила прохождения пакетов:
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 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 логи ловлю в отдельном файле:
Посмотреть через некоторое время, кто попал в сети можно так:
Если не знаете где логи можно грубо (может парсить долго!):
Все что осталось, - это написать скрипт, который забирает из файла список блокировок.
Каталог для нашего скрипта (можно использовать любой):
Скачиваем список ip адресов и распаковываем его (можно автоматизировать, добавив задание в cron):
# wget http://www.stopforumspam.com/downloads/listed_ip_1.zip
# unzip listed_ip_1.zip
Примерный вариант скрипта:
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 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 адресов:
68611 /etc/blacklist/listed_ip_7.txt
Посмотреть на наш ipset и его размер:
Name: blacklist
Type: hash:ip
Revision: 0
Header: family inet hashsize 4096 maxelem 65536
Size in memory: 142800
References: 0
////
Справочное руководство man ipset (англ).
Статья на англ. с графиками тестирования скорости обработки большого количества ip адресов.
Спасибо за внимание.
[29/09/2013 03:38 - zenon]
Интересности:
To block IP addresses based on geo location (country) here is a simple shellscript:
ipset -N geoblock nethash
for IP in $(wget -O – http://www.ipdeny.com/ipblocks/data/countries/{cn,kr,pk,tw,sg,hk,pe}.zone)
do
ipset -A geoblock $IP
done
iptables -A INPUT -m set –set geoblock src -j DROP
To auto-timeout a rule (and not generate any message if it already exists):
ipset add --exists test 91.83.231.25 120 (overwriting the default 10 seconds value)
To auto-learn a MAC address: (and define a range)
ipset add test 192.168.0.1,11:11:22:22:11:11
ipset add test 192.168.0.2 (this one will auto-learn)
[29/09/2013 13:35 - XliN]
[29/09/2013 14:13 - zenon]
Ну если стоит, то не проще man ipset?
Хотя вот например man, датирован примерно 2010 годом, и видимо аналога terse нет.
Да, выхлоп кучи адресов вместе с суммарной информацией не удобен.
[27/11/2013 18:49 - anonym]
[09/02/2014 21:51 - zenon]
Спамлисты с форума [url=http://www.stopforumspam.com/]stopforumspam.com[/url] реально спасают.
Выключил обновление спамлиста на пару дней, так сразу полез спам.
ASCII капчу научились обходить на раз-два, так что думаю её можно вообще выключить.
Попробовал вообще выключить блокировку ip адресов, результат - за полчаса около сотни спам-постов.
[11/02/2014 15:14 - zenon]
В продолжении предыдущего поста, IP адрес до жути активный попался, поставил на посмотреть логирование:
15707
Это за три дня.
Обновление спамлистов у меня происходит каждый в начале первого часа ночи, для загрузки ipset`а требуется время:
#!/bin/sh
ipset --flush blacklist-TMP
for ipaddr in $(cat /etc/stopforumspam/blacklist.ip)
do ipset --add blacklist-TMP $ipaddr
done
# time ./test.sh
./test.sh 1,93s user 14,98s system 25% cpu 1:05,06 total
И за это время на сайт успевает просочиться 4-5 спам комментариев.
Как этого избежать - использовать временный ipset, а потом их менять местами (swap), подсмотреть можно тут.
ipset -N new-set ....
ipset -A new-set ....
...
# Swap the old and new sets
ipset -W old-set new-set
# Get rid of the old set, which is now under new-set
ipset -X new-set
[17/12/2014 20:50 - Stas]
[19/12/2014 22:03 - zenon]
Размер хэша увеличить надо, например:
[25/12/2014 23:14 - Stas]
[26/09/2015 03:47 - HorekRediskovich]
ipset -N blacklist iptree --timeout 600
и совсем не понятны данные строчки:ipset add --exists test 91.83.231.25 120 (overwriting the default 10 seconds value)
[26/09/2015 04:32 - HorekRediskovich]
[25/01/2017 10:08 - Ян]
iptables -v -I INPUT -m set --match-set blacklist src -j DROP
есть ключ --match-set, а чем он отличается от --set ?[19/02/2017 17:06 - Влад]
[20/02/2017 12:10 - Stas]
Добавить комментарий