在一台服务器上,我们试图阻止中国的任何访问。
我们希望通过 iptables 而不是通过 .htaccess 来实现这一点。
然而,我们遇到的问题是,当一次添加多个 iptables 时(我们这里谈论的是中国的 1000 多个 IP 子网),一个会失败(出现错误“iptables:未知错误 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
但是,我对 shell 脚本不是特别熟悉,并且不确定在这个脚本的哪个位置我可以添加某种延迟,如果可能的话。请问有人能给我指出正确的方向吗?谢谢。
答案1
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 手册页以获取更多详细信息。
答案2
我同意 dsumsky 的观点,你可能需要一种新方法。但要为每加载 4 个条目延迟 1 秒,要插入的代码应如下所示:
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