cppmm 18.03.2010 13:21

СкриптыДискриминация по национальному признаку или баним страны.

Так получилось, что понадобилось прикрыть доступ к серверу из некоторых стран. Понимаю, что кровавая гебня и всё такое, но задача есть, надо сделать.
Вот здесь находим архивчик с базой IP-адресов и их национальной принадлежностью. Далее за нас работает небольшой скрипт. Для работы скрипта понадобится дополнительно установить замечательную утилиту ipcalc.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash
#
TMPDIR=/tmp/geoiptban
IP_BBASE=$TMPDIR/bbase.csv
IP_EBASE=$TMPDIR/ebase.csv
DB_ZIP=$TMPDIR/db.zip
PERL=/usr/bin/perl
FILE_BCOUNTRY=$1
COUNTRY_DB_URL=http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
mkdir -p $TMPDIR
# Стягиваем и распаковываем базу айпишников.
wget -q -O $DB_ZIP $COUNTRY_DB_URL
unzip -p $DB_ZIP > $IP_BBASE
# Убираем лишние символы из базы, для простоты обработки.
if [ -e "$IP_BBASE" ]
then
cp $IP_BBASE $IP_EBASE
$PERL -pi -e 's/"//g' $IP_EBASE
else
echo "Source ip-base-file not found."
exit 0;
fi
# Обработка базы. Форматируем базу сперва в вид диапазонов ip-адресов, а потом в список подсетей.
# Получившиеся подсети скармливаем iptables'у.
if [ -e "$FILE_BCOUNTRY" ]
then
for country in $(cat ${FILE_BCOUNTRY})
do
grep $country $IP_EBASE | awk -F "," '{print $1," - ",$2}' > $TMPDIR/$country.il
for ((i=1;i<=$(wc -l ${TMPDIR}/${country}.il | awk '{print $1}');i++))
do
ipcalc $(head -n ${i} ${TMPDIR}/${country}.il | tail -n 1) | grep -v deaggregate >> $TMPDIR/$country.nl
done
done
for country_network_list in $(ls ${TMPDIR} | grep nl)
do
for ((i=1;i<=$(wc -l ${TMPDIR}/$country_network_list | awk '{print $1}');i++))
do
iptables -t filter -A INPUT -s $(head -n ${i} ${TMPDIR}/$country_network_list | tail -n 1) -j DROP
done
done
else
echo "List of blocked countries not found."
exit 0;
fi
rm -rf $TMPDIR



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

# cat country_list
RU US GB


Запускается скрипт очень просто:


# ./geoiptban.sh country_list
P.S. Если кто подскажет способ выбирать из файла определённую строку по номеру без использования конвееров(в моём случае head, tail) буду признателен, а то часто приходится такое делать.


Тэги: bash iptables network script
+ 6 -
Похожие Поделиться

warchief 18.03.2010 15:09 #
спасибо, как раз хотел создать топик-вопрос.
warchief 18.03.2010 15:18 #
подскажите, как нужно изменить строку iptables.... , чтобы забанить соедниения из стран только на определённом порту?
cppmm 18.03.2010 15:33 #
iptables -t filter -A INPUT -s $(head -n ${i} ${TMPDIR}/$country_network_list | tail -n 1) -p ${PROTO} --dport ${PORT} -j DROP
И добавить две переменные PROTO и PORT.
Тогда, если выставить, напрмиер PROTO=tcp, а PORT=80, будет закрыт доступ к http-серверу(80-ый порт по протоколу tcp).
redway 18.03.2010 22:56 #
А еще можно при помощи модуля geoip (входит в xtables-addons):

iptables -t mangle -I PREROUTING -m geoip --dst-cc UA -j DROP
cppmm 19.03.2010 08:57 #
Сначал я хотел сделать именно так, но скрипт мне показалось, написать проще, чем компилировать пакет с iptables и его модулями.
redway 19.03.2010 14:24 #
с установкой конечно придется немного повозиться, но там, помимо geoip, еще много вкусностей:

Цепочки:

DELUDE - при обращении к порту, на котором стоит правило DELUDE, iptables отправляет сообщение SYN-ACK на SYN, но в остальных случаях отправляется RST сообщение. Тем самым вводит в заблуждение сканер атакующей машины, показывая что целевой порт открыт, в то время как на самом деле порт закрыт.

TARPIT - коннект в пустоту. При обращении к порту, на котором стоит правило TARPIT, iptables подтверждает запрос на TCP-соединение отправляя атакующему сообщение SYN-ACK, а так же принудительное установление размера TCP-окна, равным нулю. Это приводит к тому, что атакующая сторона не может передать никаких данных, а все ее попытки разорвать соединение игнорируются. До истечения тайм-аута (12-24 минут)соединение находится в "подвисшем" состоянии.

TEE - при обращении к порту, на котором стоит правило TEE, iptables отправляет копию этого пакета на другую машину сегмента локальной сети. Как бы зеркалирует этот пакет и направляет его по другому маршруту.

Модули:

geoip - используя этот модуль можно строить более гибкие правила iptables основываясь на геоположении IP-адреса в сети Интернет.

ipp2p - используя этот модуль можно осуществить фильтрацию трафика популярных P2P сетей:eDonkey, eMule, Direct Connect, KaZaA, Gnutella, BitTorrent, AppleJuice, WinMX, SoulSeek, Ares.

и еще что-то.
warchief 19.03.2010 23:24 #
хм поставил последнюю версию xtables-addons, потом делаю:
iptables -t mangle -I PREROUTING -m geoip --dst-cc UA -j DROP

>>iptables v1.4.4: Couldn't load match `geoip':/lib/xtables/libipt_geoip.so: cannot open shared object file: No such file or directory

Подскажите, что не так?
warchief 19.03.2010 23:43 #
ок, с этим разобрался, теперь другая ошибка: /var/geoip/LE/DE.iv0: No such file or directory
iptables v1.4.4: Could not read geoip database


Где брать эти базы данных?
redway 20.03.2010 08:50 #
razum2um 21.04.2010 22:01 #
Если кто подскажет способ выбирать из файла определённую строку по номеру без использования конвееров(в моём случае head, tail) буду признателен, а то часто приходится такое делать

sed -n 4p
выбирает четвертую

с диапазоном хуже:
sed -n 4~1p
выбирает c четвертой и с шагом 1 (т.е. каждую) до конца.
Потом head`ить, если нужно не все, т.е. все-таки конвейер :(
cppmm 11.01.2011 13:29 #
Только сейчас коммент заметил.
Респект.
Вот это то, что мне нужно. Если в цикле номер инкрементировать и подставлять в $() получается замечательно.
sed -n 4p

Спасибо.
razum2um 11.01.2011 16:33 #
22.04.10 01:01
11.01.11 16:29
Только сейчас коммент заметил

ответ через границу десятилетий!
мылинукс в веках... эпично...
cppmm 11.01.2011 16:38 #
Да я как-то твой коммент тогда не заметил, хотя стоило бы. :)
razum2um 11.05.2011 18:01 #
забавно. теперь я буду искать в гугле:
"site:welinux.ru razum2um диапазон строк"

еще рецепт

диапазон строк (с первой по четвертую)
awk 'NR==1,NR==4' /etc/passwd

выборка (первая и четвертая)
awk 'NR==1;NR==4' /etc/passwd
cppmm 11.05.2011 18:55 #
Ну, вот. Опять ты выдал красивое решение, вместо моего костыля. :)
Просто, если в цикле пускать sed получалось долго и нудно. Поэтому я уже набросал себе под это дело скриптик на perl'е:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/perl -w                                                                                                                                                                                         
#

$start = $ARGV[1];
$stop = $ARGV[2];

open (FILE, "< $ARGV[0]");
while ( defined($line = <file>) && ($. <= $stop)) {
        if ($. >= $start) {
                print $line;
        }
}
</file>

m912 15.01.2011 10:56 #
использовать модуль geoip - тру.
Создавать кучу правил на INPUT/DROP - не тру:
КАЖДЫЙ входящий валидный пакет будет проходить ВСЕ эти DROP правила - непроизводительная нагрузка на ядро.
cppmm 15.01.2011 13:43 #
Делалось на скору руку, потому не стал заморачиваться с отдельными собственными цепочками. Скрипт в открытом доступе, никто не мешает доработать. ;)