1. 程式人生 > >iptables+ipset自動封閉和解封頻繁訪問web服務的惡意IP

iptables+ipset自動封閉和解封頻繁訪問web服務的惡意IP

轉載自https://blog.csdn.net/firehive/article/details/81260169

iptables直接針對ip進行封禁,在ip數量不大的時候是沒什麼問題的,但當有大量ip的時候效能會嚴重下降,iptables是O(N)的效能。而ipset就像一個集合,把需要封閉的ip地址寫入這個集合中,ipset 是O(1)的效能,可以有效解決iptables直接封禁大量IP的效能問題。

1. 如果是RedHat/CentOS,首先用yum(Ubuntu/Debian用將yum換為apt-get既可 )安裝ipset。

yum install ipset -y

2.ipset建立基於ip hash的集合名稱

   例如 blacklist表示集合的名字是blacklist

   hashsize 4096 表示初始值為4096個,如果滿了,這個 hash 會自動擴容為之前的兩倍。最大能儲存的數量是 maxelem指定的值;hashsize 的預設值是 1024

   maxelem 1000000表示最大元素個數為100000 ,ipset預設值為65536

   timeout 3600 表示封禁3600s;  

   iptables開啟封禁80,443策略。 

ipset create blacklist hash:ip hashsize 4096 maxelem 1000000 timeout 3600
iptables -A INPUT -p tcp -m set --match-set blacklist src -m multiport --dports 443,80 -j DROP

   如果我們不希望有過期時間,可以不加timeout這個引數

ipset create blacklist hash:ip

 當然,也可以封禁黑名單IP的所有請求。

iptables -A INPUT -m set --match-set blacklist src -j DROP

3.基於自定義訪問頻率閾值或者請求敏感關鍵字來建立自動篩選惡意IP的指令碼/data/iptables_ipset_deny.sh。

FILES:nginx的access.log檔案

sensitive: 敏感關鍵字

threshold: 一分鐘內請求頻率閾值

#!/bin/bash
FILES="/data/nginx/logs/access.log"
sensitive="sensitive_word"
threshold=1000
 
ip_file="/tmp/ip_file"
sensitive_file="/tmp/sensitive_file"
DATE=`date -d '1 minutes ago' +%Y:%H:%M`
 
grep ${DATE} ${FILES} | awk '{print $1}' | sort | uniq -c | sort -n | tail -n 1 > ${ip_file}
grep ${DATE} ${FILES} | grep -i ${sensitive} | awk '{print $1}' | sort -n | uniq > ${sensitive_file}
 
ip_file_number=`awk '{print $1}' ${ip_file}`
ip_file_ip=`awk '{print $2}' ${ip_file}`
 
if [[ $ip_file_number -gt $threshold ]];then
    ipset add blacklist ${ip_file_ip} timeout 3600
fi
 
if [ -s ${sensitive_file} ];then
    for sensitive_ip in `cat ${sensitive_file}`
    do
        ipset add blacklist ${sensitive_ip}
    done
fi

 4. 用crontab定時啟動指令碼。

echo "* * * * * bash /data/iptables_ipset_deny.sh" >> /etc/crontab

注意:在自己的實際操作過程中發現,寫好的從nginx中分析得到的黑名單ip指令碼加入到ipset中;如果是手動執行這個指令碼的話,是正常的,如果做成定時任務,就一直沒有成功,ipset中沒有新增ip;搗鼓了好半天,發現是需要指定ipset這個命令路徑在/usr/sbin下面,因此在指令碼中加上指令碼的完整路徑即可,如/usr/sbin/ipset add blacklist x.x.x.x

這裡需要了解/usr/sbin和/usr/bin的區別了:/sbin目錄下的命令通常只有管理員才可以執行,/bin下的命令管理員和一般的使用者都可以使用

ipset 命令

ipset create blacklist hash:ip,port hashsize 4096 maxelem 1000000 timeout 100 #加入集合 
ipset del blacklist x.x.x.x # 從 blacklist 集合中刪除內容 
ipset list blacklist # 檢視 blacklist 集合內容 
ipset list # 檢視所有集合的內容 
ipset flush blacklist # 清空 blacklist 集合 
ipset flush # 清空所有集合 
ipset destroy blacklist # 銷燬 blacklist 集合 
ipset destroy # 銷燬所有集合 
  如ipset save blacklist > 1.txt  # 輸出 banip 集合內容到1.txt
    ipset save > 1.txt  # 輸出所有集合內容到1.txt
ipset save blacklist # 輸出 blacklist 集合內容到標準輸出 
ipset save # 輸出所有集合內容到標準輸出 
ipset restore # 根據輸入內容恢復集合內容 
  如 ipset restore  <1.txt  # 根據1.txt內容恢復集合內容

service ipset save    #執行 add,del 這類添刪操作後都需要儲存
service ipset restart #重啟ipset

ipset test blacklist x.x.x.x. #測試x.x.x.x.這個ip是否在blacklist集合中

其他關於ipset不錯的文章

Linux iptables 擴充套件 ipset 使用教程http://www.zhoutao.org/blog/2017/11/757.html
linux 基於ipset+iptables 保護api介面被暴力訪問https://blog.csdn.net/huliwho/article/details/80975549