如何从阻止列表中快速添加规则到iptables?

时间:2014-12-29 21:11:10

标签: bash firewall iptables

我正在使用Ubuntu Server 14.04 32bit进行以下操作。

我正在尝试使用阻止列表将区域块(中国,俄罗斯......)添加到我的防火墙规则中,并且正在努力完成我的脚本完成所需的时间并理解为什么不同的脚本无法工作。

我最初使用http://whatnotlinux.blogspot.com/2012/12/add-block-lists-to-iptables-from.html作为示例,整理/更改了脚本的部分,使其非常接近以下内容:

#!/bin/bash

# Blacklist's names & URLs array
declare -A blacklists
blacklists[china]="http://www.example.com"
#blacklists[key]="url"

for key in ${!blacklists[@]}; do
  #Download blacklist
  wget --output-document=/tmp/blacklist_$key.gz -w 3 ${blacklists[$key]}
  iptables -D INPUT -j $key #Delete current iptables chain link
  iptables -F $key #Flush current iptables chain
  iptables -X $key #Delete current iptables chain
  iptables -N $key #Create current iptables chain
  iptables -A INPUT -j $key #Link current iptables chain to INPUT chain
  #Read blacklist
  while read line; do
  #Drop description, keep only IP range
  ip_range=`echo -n $line | sed -e 's/.*:\(.*\)-\(.*\)/\1-\2/'`
  #Test if it's an IP range
    if [[ $ip_range =~ ^[0-9].*$ ]]; then
    # Add to the blacklist
    iptables -A $key -m iprange --src-range $ip_range -j LOGNDROP
    fi
  done < <(zcat /tmp/blacklist_$key.gz | iconv -f latin1 -t utf-8 - | dos2unix)
done
# Delete files
rm /tmp/blacklist* 
exit 0

这似乎适用于短测试列表,但手动向iptables添加许多(200,000 +)个条目需要花费大量时间,我不知道为什么?根据我列出的列表,这需要花费10个小时来完成,这看起来很傻。

在查看iptables-save输出的格式后,我创建了一个新脚本,该脚本使用iptables-save保存工作iptables规则,然后将块的预期格式附加到此文件,例如: {{1} } ,最终使用iptables-restore加载文件,如下所示:

-A bogon -m iprange --src-range 0.0.0.1-0.255.255.255 -j LOGNDROP

这适用于测试平台上的大多数列表,但是如果包含特定列表将产生 iptables-restore:389971行失败 错误,这始终是最后一行(COMMIT)。我已经读过,由于iptables在重新加载规则时出现问题的方式,错误总是会说最后一行失败。

真正奇怪的是,在Ubuntu Desktop 14.04 64bit上测试这些相同的列表,第二个脚本工作正常。我已经尝试在桌面计算机上运行脚本,然后使用iptables-save来保存&#34;正确&#34;格式化的规则集版本,然后使用iptables-restore将此文件加载到服务器上的iptables,仍然收到错误。

我对如何排除故障感到困惑,为什么初始脚本需要很长时间才能将规则添加到iptables,以及可能导致第二个脚本中列表出现问题的原因。

3 个答案:

答案 0 :(得分:1)

如果您需要阻止大量IP地址,请改用ipset

第1步:创建IPset:

# Adjust the hashsize so that it's roughly 4 x (possible number of addresses to block)
ipset create BlockAddress hash:ip hashsize 4096

步骤2:将要阻止的地址添加到该IPset中:

# Put this in a loop, the loop reading a file containing list of addresses to block 
ipset add BlockAddress $IP_TO_BLOCK

最后,使用netfilter中的一个行替换所有要阻止的行:

iptables -t raw -A PREROUTING -m set --match-set BlockAddress src -j DROP

完成。 iptables-restore会很快。

重要提示: 强烈建议不要使用域名添加到netfilter中; netfilter首先需要进行DNS解析,如果DNS配置不正确和/或速度太慢,则会失败。而是,预先解析(或定期解析)要阻止的域名,并将找到的IP地址提供给“包含要阻止的地址列表的文件”。它应该是一个简单的脚本,每隔5分钟从crontab调用一次。


编辑1:

这是我用来获取facebook.com地址的cronjob示例,每5分钟调用一次:

#!/bin/bash
fbookfile=/etc/iptables.d/facebook.ip
for d in www.facebook.com m.facebook.com facebook.com; do
    dig +short "$d" >> "$fbookfile"
done
sort -n -u "$fbookfile" -o "$fbookfile"

每半小时,另一个cronjob将这些地址提供给ipset

#!/bin/bash
ipset flush IP_Fbook
while read ip; do
    ipset add IP_Fbook "$ip"
done < /etc/iptables.d/facebook.ip

注意:我必须这样做,因为例如,执行dig +short facebook.com会返回一个 IP地址。经过一番观察,返回的IP地址每隔约5分钟就会改变一次。由于我太忙了 来制作优化版本,所以我采取了简单的方法,每隔30分钟进行一次刷新/重建,以最大限度地减少CPU峰值。

答案 1 :(得分:1)

以下是我最终使用ipsets解决这个问题的方法。

#!/bin/bash

# Blacklist names & URLs array
declare -A blacklists
blacklists[China]="url"
# blacklists[key]="url"
# etc...

for key in ${!blacklists[@]}; do
  # Download blacklist
  wget --output-document=/tmp/blacklist_$key.gz -w 3 ${blacklists[$key]}

  # Create ipset for current blacklist
  ipset create $key hash:net maxelem 400000
  # TODO method for determining appropriate maxelem

    while read line; do
    # Add addresses from list to ipset
    ipset add $key $line -quiet
    done < <(zcat /tmp/blacklist_$key.gz | sed '1,2d' | sed s/.*://)

  # Add rules to iptables
  iptables -D INPUT -m set --match-set $key src -j $key # Delete link to list chain from INPUT
  iptables -F $key # Flush list chain if existed
  iptables -X $key # Delete list chain if existed
  iptables -N $key # Create list chain
  iptables -A $key -p tcp -m limit --limit 5/min -j LOG --log-prefix "Denied $key TCP: " --log-level 7
  iptables -A $key -p udp -m limit --limit 5/min -j LOG --log-prefix "Denied $key UDP: " --log-level 7
  iptables -A $key -p icmp -m limit --limit 5/min -j LOG --log-prefix "Denied $key ICMP: " --log-level 7
  iptables -A $key -j DROP # Drop after logging
  iptables -A INPUT -m set --match-set $key src -j $key
done

我并不熟悉ipsets,但这样可以更快地下载,解析和添加块。

我为每个列表添加了单独的链,以获得更详细的日志记录,如果您有多个,则会记录丢弃的ip来自哪个阻止列表。在我的实际框中,我使用了大约10个列表,并且添加了数十万个地址,没有任何问题!

答案 2 :(得分:0)

下载区

#!/bin/bash
# http://www.ipdeny.com/ipblocks/
zone=/path_to_folder/zones
if [ ! -d $zone ]; then mkdir -p $zone; fi
wget -c -N http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz
tar -C $zone -zxvf all-zones.tar.gz >/dev/null 2>&1
rm -f all-zones.tar.gz >/dev/null 2>&1

编辑您的 Iptables bash 脚本并添加以下几行:

#!/bin/bash
ipset=/sbin/ipset
iptables=/sbin/iptables
route=/path_to_blackip/

$ipset -F
$ipset -N -! blockzone hash:net maxelem 1000000
for ip in $(cat $zone/{cn,ru}.zone $route/blackip.txt); do
    $ipset -A blockzone $ip
done
$iptables -t mangle -A PREROUTING -m set --match-set blockzone src -j DROP
$iptables -A FORWARD -m set --match-set blockzone dst -j DROP

例子:其中"blackip.txt"是你自己的ip黑名单,"cn,ru" china-russia"

来源:blackip