【问题标题】:How to quickly add rules to iptables from blocklists?如何从阻止列表中快速向 iptables 添加规则?
【发布时间】:2021-01-30 04:50:49
【问题描述】:

我正在使用 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 规则,然后将预期的块格式附加到此文件,例如:-A bogon -m iprange --src-range 0.0.0.1-0.255.255.255 -j LOGNDROP,并最终使用 iptables-restore 来加载文件,如下所示:

#!/bin/bash

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

iptables -F # Flush iptables chains
iptables -X # Delete all user created chains
iptables -P FORWARD DROP # Drop all forwarded traffic
iptables -N LOGNDROP # Create LOGNDROP chain
iptables -A LOGNDROP -p tcp -m limit --limit 5/min -j LOG --log-prefix "Denied TCP: " --log-level 7
iptables -A LOGNDROP -p udp -m limit --limit 5/min -j LOG --log-prefix "Denied UDP: " --log-level 7
iptables -A LOGNDROP -p icmp -m limit --limit 5/min -j LOG --log-prefix "Denied ICMP: " --log-level 7
iptables -A LOGNDROP -j DROP # Drop after logging

# Build first part of iptables-rules
for key in ${!blacklists[@]}; do
  iptables -N $key # Create chain for current list
  iptables -A INPUT -j $key # Link input to current list chain
done

iptables-save | sed '$d' | sed '$d' > /tmp/iptables-rules.rules # Save WORKING iptables-rules and remove last 2 liens (COMMIT & comment)

for key in ${!blacklists[@]}; do  
  #Download blacklist
  wget --output-document=/tmp/blacklist_$key.gz -w 3 ${blacklists[$key]}
  zcat /tmp/blacklist_$key.gz | sed '1,2d' | sed s/.*:/-A\ $key\ -m\ iprange\ --src-range\ / | sed s/$/\ -j\ LOGNDROP/ >> iptables-rules.rules
done
echo 'COMMIT' >> /tmp/iptables-rules.rules
iptables-restore < /tmp/iptables-rules.rules
# Delete files
rm /tmp/blacklist* 
rm /tmp/iptables-rules.rules 
exit 0

这对于测试平台上的大多数列表都很​​有效,但是如果包含特定列表会产生 iptables-restore: line 389971 failed 错误,这始终是最后一行(提交)。我已经读过,由于 iptables 的工作方式,每当重新加载规则出现问题时,错误总是会说最后一行失败。

真正奇怪的是,在 Ubuntu Desktop 14.04 64bit 上测试这些相同的列表,第二个脚本工作得很好。我尝试在桌面机器上运行脚本,然后使用 iptables-save 保存规则集的“正确”格式版本,然后使用 iptables-restore 和 still将此文件加载到服务器上的 iptables > 收到错误。

我不知道如何解决这个问题,为什么初始脚本需要这么长时间才能将规则添加到 iptables,以及可能导致第二个脚本中的列表出现问题的原因。

【问题讨论】:

  • 要么在你的第一个代码的内部循环中添加一个echo started cmd iptables ....; iptables ... ; echo done cmd iptables ...,要么使用set -vx 来直观地确认延迟在哪里。我可以看到,鉴于您似乎拥有的规则大小,运行所有这些命令可能需要一段时间。 (根本)无法帮助您解决第二个想法,但是鉴于它的速度要快得多,因此尝试解决该问题是有意义的。鉴于您的问题空间的 SA 性质,您可能会考虑标记您的问题并将其移至 http://serverfault.com。祝你好运。
  • 我之前添加了一个回显来显示循环当前正在添加的规则,唯一的延迟似乎是这些命令可以运行的速度。我刚刚在安装了 FRESH 14.04.1 Ubuntu Server 32 位的虚拟机上运行了第二个脚本,它运行良好。这导致我更新物理测试机器上的所有包并重试,仍然失败!
  • 嗯。好的,所以您确定慢速机器的硬盘驱动器没有坏扇区或其他会导致这种情况的问题?两台机器上是否有相同的 amt 磁盘可用。两台机器上的 RAM 配置文件相同? “擦洗”测试是否显示磁盘或 RAM 中的任何弱点?最后,您能否在该机器上添加一个额外的磁盘,或者将其换成已知良好的磁盘?似乎你会想到这一切。 +1 坚持和耐心!祝你好运!
  • 不确定,但您可能会达到 iptables 和您的操作系统版本的某种限制。您可能希望通过 ipset 或 xtables-addons 使用 Geoip(如果您的内核支持它们。)我写的旧帖子中的更多信息:web-tech.ga-usa.com/2011/09/…web-tech.ga-usa.com/2011/09/…。 :)
  • @shelter,澄清一下,如果“慢”机器是指使用实际 iptables -A 命令而不是 iptables-restore 手动添加规则的机器,我的任何测试机器(虚拟或物理)的持续时间很长。限制,内存或其他是一个想法,但是 iptables-restore 脚本在具有相同操作系统和更少内存的 VM 上运行良好!我研究了 ipsets,但我还有一些阅读要做才能完全掌握。我担心的是,这种规模的防火墙规则肯定已经在企业界完成了,我不确定“正确”的方法

标签: bash firewall iptables


【解决方案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 步:将要阻止的地址添加到该 IP 集中:

# 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 Resolve,如果 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 峰值。

【讨论】:

    【解决方案2】:

    以下是我最终使用 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 个列表,并且毫无问题地添加了数十万个地址!

    【讨论】:

      【解决方案3】:

      下载区域

      #!/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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多