近期發現有一個ip不停的刷我們網站各種頁面靜態資源,平均每分鐘刷了三五千次,於是乎心血來潮寫了這個腳本。網站查了很久都說iptables沒法直接達到這種需求,索性就自己來寫腳本了。腳本沒有注意格式,因爲我的習慣強行加格式更難查看格式對不對。
1、iptables添加自定義鏈:
iptables -N DDOS
2、編寫腳本內容如下:
vim /mnt/auto_ddos.sh
#!/bin/bash
#獲取access日誌每分鐘單個ip訪問次數超過500次的ip,並將此ip加入iptables,24小時後解封
log_path=/alidata/weblogs/access/www.xxx.com_access.log #nginx的access日誌路徑
month=env LANG=en_US.UTF-8 date|awk '{print $2}'
#獲取當月月份,以英文顯示,因爲日誌時間格式月份是這個格式
date=date +%d/${month}/%Y:%H:%M
#日誌時間格式,到分鐘
grep “${date}” ${log_path}|awk ‘{print $1}’|sort |uniq -c|sort -nr|grep -v 184.109.153.13 >/mnt/number_ip.txt #獲取單個ip單分鐘訪問次 數,184.109.153.13是公司公網ip,不能封自己
line=cat /mnt/number_ip.txt|wc -l
#獲取當前分鐘訪問ip個數
for line in seq $line
do
number_ip=sed -n ${line}p /mnt/number_ip.txt
#訪問次數 訪問的ip
number=sed -n ${line}p /mnt/number_ip.txt|awk '{print $1}'
#訪問次數
ip=sed -n ${line}p /mnt/number_ip.txt|awk '{print $2}'
#訪問的ip
time_new=date +%s
#當前時間
if [ ${number} -gt 500 ];then #如果當前分鐘訪問次數超過500次
/sbin/iptables -nL DDOS|grep ${ip} #防火牆還沒有加入這個ip
if [ $? != 0 ];then
iptables -A DDOS -s ${ip} -j DROP #那就將這個ip加入防火牆封掉
grep ${ip} /mnt/ip_ddos.txt #已經封掉的ip所在文件內查找是否有這個ip
if [ {time_new} ${ip}" >>/mnt/ip_ddos.txt #如果沒有就將當前時間和這個ip寫入文件記錄下來
fi
fi
fi
done
#24小時後解封ip
line=cat /mnt/ip_ddos.txt|wc -l
#計算已經封掉的ip總數
for line in seq $line
do
time_old=sed -n ${line}p /mnt/ip_ddos.txt|awk '{print $1}'
#獲取ip被封的時間
time_new=date +%s
#獲取當前時間
time_finish=echo $((time_new-time_old))
#計算被封時間到現在是否過了24小時
ip=sed -n ${line}p /mnt/ip_ddos.txt|awk '{print $2}'
#獲取被封的ip
if [ ${time_finish} -gt 86400 ];then #如果被封的時間超過24小時
/sbin/iptables -nL DDOS|grep ${ip} #並且他還在防火牆裏面待着
if [ $? = 0 ];then
iptables -D DDOS -s KaTeX parse error: Expected 'EOF', got '#' at position 21: …-j DROP #̲那麼就讓他重獲自由
sed -…{ip}/d" /mnt/ip_ddos.txt #並且在已經被封的ip列表將他除名
fi
fi
done
3、編寫定時任務:
crontab -e
-
-
-
-
- sleep 58;/bin/sh /mnt/auto_ddos.sh
因爲定時任務每分鐘執行的話都是第0-1秒開始執行的,所以我們先sleep 58秒,到每分鐘的第59秒執行這個腳本,這樣才能獲取當前分鐘的單個ip訪問次數的總和是最大的。
- sleep 58;/bin/sh /mnt/auto_ddos.sh
-
-
-