На одном сервере мы пытаемся заблокировать любой доступ для страны Китай.
Мы хотим реализовать это с помощью iptables, а не через .htaccess.
Однако проблема, с которой мы сталкиваемся, заключается в том, что при одновременном добавлении нескольких iptables (а здесь мы говорим о более 1000 IP-подсетях для Китая) одна из них выйдет из строя (с ошибкой iptables: Unknown error 18446744073709551615, а затем все остальные после потерпит неудачу) означает, что мы должны iptables -F
чтобы продолжить добавление этих правил.
Некоторые тесты показывают, что проблема, по-видимому, заключается в попытке запустить сразу несколько партий (или даже 10+ одновременно, кажется, выдает ошибку), а не сервер, которому просто не нравятся некоторые конкретные правила.
Поэтому я подумал, может ли попытка добавить режим сна (или другую задержку) между каждым запуском правила iptables улучшить процесс?
Сейчас мы пробовали множество способов реализовать эти iptables, но мы хотели бы, если возможно, использовать этот скрипт от nixCraft которые можно увидеть ниже.
#!/bin/bash
### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
ISO="af cn"
### Set PATH ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep
### No editing below ###
SPAMLIST="countrydrop"
ZONEROOT="/root/iptables"
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"
cleanOldRules(){
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
}
# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
# clean old rules
cleanOldRules
# create a new iptables list
$IPT -N $SPAMLIST
for c in $ISO
do
# local zone file
tDB=$ZONEROOT/$c.zone
# get fresh zone file
$WGET -O $tDB $DLROOT/$c.zone
# country specific log message
SPAMDROPMSG="$c Country Drop"
# get
BADIPS=$(egrep -v "^#|^$" $tDB)
for ipblock in $BADIPS
do
$IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
$IPT -A $SPAMLIST -s $ipblock -j DROP
done
done
# Drop everything
$IPT -I INPUT -j $SPAMLIST
$IPT -I OUTPUT -j $SPAMLIST
$IPT -I FORWARD -j $SPAMLIST
# call your other iptable script
# /path/to/other/iptables.sh
exit 0
Однако я не особо знаком со сценариями оболочки и не уверен, в какой момент в этом сценарии я мог бы добавить какую-то задержку между обработкой iptables, если это вообще возможно. Пожалуйста, может ли кто-нибудь указать мне правильное направление? Спасибо.
Netfilter / iptables плохо масштабируется при использовании с большим количеством правил, поскольку предполагается, что они должны согласовываться последовательно. Но, начиная с ядра Linux 2.6.36, появилась новая функция, которая называется Наборы IP что помогает устранить такие правила с помощью методов хеширования. Вкратце, как это работает:
1) создать набор IP
ipset create set01 hash:net
2) добавить диапазоны IP в набор
ipset add set01 192.168.1.0/24
ipset add set01 192.168.2.0/24
ipset add set01 192.168.3.0/24
ipset add set01 192.168.4.0/24
...
...
3) подключите набор с правилом netfilter / iptables, которое отклоняет любой пакет с исходным IP-адресом из набора set01
iptables -A INPUT -m set --match-set set01 src -j REJECT
Как видите, вместо того, чтобы создать 4 почти одинаковых правила iptables, я создал один набор IP-адресов set01, затем добавил к нему несколько диапазонов IP-адресов (просто пример, на самом деле их могут быть миллионы) и, наконец, я заблокировал их с помощью единое правило iptables. Поэтому вместо того, чтобы поддерживать длинный список похожих правил iptables, создайте набор (-ы) IP-адресов в соответствии с файлами зон и затем заблокируйте его за один шаг.
Пожалуйста, проверьте соответствующую страницу руководства ipset для получения более подробной информации.
Я согласен с Дсумским, что вам может понадобиться новый подход. Но для задержки на 1 секунду для каждых 4 загруженных записей код для вставки будет примерно таким:
i=0 # delay iterator
BADIPS=$(egrep -v "^#|^$" $tDB)
for ipblock in $BADIPS
do
# delay to help rules load properly.
if [[ $i == 5 ]]
then
sleep 1
i=0
fi
i=$((i+1))
$IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
$IPT -A $SPAMLIST -s $ipblock -j DROP
done
Вы можете поэкспериментировать с кодом с таким блоком кода:
#!/bin/bash
i=0
while [ 1 ]
do
i=$((i+1))
if [[ $i == 5 ]]
then
sleep 1
i=0
fi
echo hello $i
done