防禦CC只能放大招

  什麼是CC

攻 擊者藉助代理服務器生成指向受害主機的合法請求,實現DDOS和僞裝就叫:CC,全稱叫ChallengeCollapsar。相信大家都有這樣的經歷,有時候訪問網站超級慢,甚至是無法訪問,到服務器上看發現同一個IP或者多個IP訪問一分鐘之內訪問了幾百萬次,這就是被CC攻 擊了,CC攻 擊屬於DDos攻 擊的一種,攻 擊者會利用大量的“肉雞”對目標網站發起請求,而且頻率超級超級的快,這樣子就會導致服務器承受不住而癱瘓。CC攻 擊雖然看起來和正常訪問幾乎沒什麼區別,有時候甚至還會模仿正規的搜索引擎,把自己僞裝成百度、谷歌等等

  如何防禦

防禦CC攻 擊首先需要從根本上做起,禁止網站代理訪問,儘量將網站做成靜態頁面,限制連接數量,修改最大超時時間,當然也有非常直接的方法,就是從日誌中分析出所有可能是"肉雞"的IP地址然後將其寫入iptables防火牆中拒絕訪問,此文就具體的介紹如何使用腳本實現自動化的拒絕這些IP訪問

  分析日誌格式

使用head命令查看前幾行的的日誌格式從而分析,但說白了關心的東西也就那麼幾點,首先是第一個字段,這是請求過來的真是IP地址,其次則是,requesthost後面說跟着的字段,則是請求訪問的域名

47.52.16.198 - - [01/Oct/2018:03:24:17 +0800] requesthost:"www.a.com"; "GET /ocs/v2.php/apps/notifications/api/v2/notifications HTTP/1.1" requesttime:"0.299"; 200 74 "-" - -"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36" "-"

分析完成後,我們接下來需要確定一下整體的思路流程

  1. 把一分鐘之內訪問超過100次的IP地址給拒絕訪問

  2. 拒絕的IP地址需要記錄到一個日誌當中

  3. 每次進行檢測前把之前的IP解除拒絕訪問

  4. 解除拒絕訪問的IP地址也需要記錄到一個日誌當中

這裏給大家介紹一個實際的生產案列,在之前的碰壁當中,使用腳本自動化去實現防禦CC會存在誤封掉正常的請求,因爲真的有些客戶會一直去點擊刷新頁面(我也很無奈,我也很無語),所以面對這種情況,建議是將IP使用iptables去轉發,呈現客戶一個純靜態的頁面,提示用戶請求次數過多一分鐘之後在嘗試訪問,最後一分鐘之後自動解封。

  awk處理字符串

awk是一種編程語言,用於在linux/unix下對文本和數據進行處理。數據可以來自標準輸入(stdin)、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大編程工具。它在命令行中使用,但更多是作爲腳本來使用。awk有很多內建的功能,比如數組、函數等,這是它和C語言的相同之處,靈活性是awk最大的優勢。

語法形式

awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)

常用命令選項

-F fs fs指定輸入分隔符,fs可以是字符串或正則表達式,如-F:
-v var=value 賦值一個用戶定義變量,將外部變量傳遞給awk
-f scripfile 從腳本文件中讀取awk命令
-m[fr] val 對val值設置內在限制,-mf選項限制分配給val的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。

在這裏使用a.txt文本做幾個簡單的操作演示,a.txt內容如下:
1:2:3
6#5#4
7:8:9

#截取指定段
[root@test ~]# awk -F ':|#' '{print $2}' a.txt
2
5
8

#匹配字符後字符串
[root@center ~]# awk -F':|#' '$1 ~ "^[0-9]"' a.txt 
1:2:3
6#5#4
7:8:9

  sort排序

sort命令是在Linux裏非常有用,它可以將文件進行排序,並將排序結果標準輸出。sort命令既可以從特定的文件,也可以從stdin中獲取輸入。

語法形式

sort(選項)(參數)

常用命令選項

-b:忽略每行前面開始出的空格字符;
-c:檢查文件是否已經按照順序排序;
-d:排序時,處理英文字母、數字及空格字符外,忽略其他的字符;
-f:排序時,將小寫字母視爲大寫字母;
-i:排序時,除了040至176之間的ASCII字符外,忽略其他的字符;
-m:將幾個排序號的文件進行合併;
-M:將前面3個字母依照月份的縮寫進行排序;
-n:依照數值的大小排序;
-o<輸出文件>:將排序後的結果存入制定的文件;
-r:以相反的順序來排序;
-t<分隔字符>:指定排序時所用的欄位分隔字符;
+<起始欄位>-<結束欄位>:以指定的欄位來排序,範圍由起始欄位到結束欄位的前一欄位。

在這裏使用a.txt文本做幾個簡單的操作演示,a.txt內容如下:
D-127.0.0.1
C-10.0.0.1
B-172.16.0.1
A-192.168.0.1

#簡單排序
[root@center ~]# cat a.txt | sort
A-192.168.0.1
B-172.16.0.1
C-10.0.0.1
D-127.0.0.1

#反向排序
[root@center ~]# cat a.txt | sort -r
D-127.0.0.1
C-10.0.0.1
B-172.16.0.1
A-192.168.0.1

  uniq去除重複

uniq命令用於報告或忽略文件中的重複行,一般與sort命令結合使用。
語法形式

uniq(選項)(參數)

常用命令選項

-c或——count:在每列旁邊顯示該行重複出現的次數;
-d或--repeated:僅顯示重複出現的行列;
-f<欄位>或--skip-fields=<欄位>:忽略比較指定的欄位;
-s<字符位置>或--skip-chars=<字符位置>:忽略比較指定的字符;
-u或——unique:僅顯示出一次的行列;
-w<字符位置>或--check-chars=<字符位置>:指定要比較的字符。

在這裏使用a.txt文本做幾個簡單的操作演示,a.txt內容如下:
192.168.0.1
192.168.0.1
192.168.0.1
10.0.0.1

#去除重複並統計重複個數
[root@center ~]# cat a.txt | uniq -c
    3 192.168.0.1
    1 10.0.0.1

*這裏要注意的是要先排好序然後才能正常統計,所以一般會和sort搭配使用

  腳本案例

有了前面的三個的介紹,那麼接下來看下面的示例腳本相信你會更容易一些

#########################################################################
# File Name: CC_Attack.sh
# Author: K-Joker
# mail: [email protected]
# Created Time: Sun 30 Sep 2018 07:53:19 AM CST
#########################################################################

#!/bin/bash

#定義訪問日誌的路徑
Log_Path=/var/log/nginx/access.log

#定義臨時存放一分鐘之前的日誌文件路徑
Tmp_Log=/tmp/tmp_last_min.log
#定義一個存放一分鐘訪問量高於10次的IP地址臨時文件
Tmp_IP=/tmp/tmp_ip

#定義防禦***腳本的日誌
Attack_Log=/var/log/nginx/attack.log



################################
#統計一分鐘之前的日誌相關信息的方法
################################
AccessLog()
{
	
	#將一分鐘之前的日誌輸出到一個臨時的文件中
	egrep "$OneMinAgo:[0-5]+" $Log_Path > $Tmp_Log
	#將這一分鐘的日誌輸出到一個臨時的文件中
	egrep "$NowTime:[0-5]+" $Log_Path >> $Tmp_Log

}



####################################################
#將一分鐘內訪問次數超過10次的IP轉發到另外的一個頁面的方法
####################################################
Block_IP()
{

	#把一分鐘內訪問超過10次的IP地址統計到一個臨時文件中
	awk '{print $1,$6}' $Tmp_Log | awk -F'requesthost:"|";' '{print $1,$2}' | sort -n | uniq -c | awk '$1>10 {print $2,$3}' > $Tmp_IP
	#重寫Tmp_IP文件格式
	sed -i 's/[ ][ ]*/,/g' $Tmp_IP
	#統計將要轉發的IP個數
	count=`wc -l $Tmp_IP | awk '{ print $1 }'`

	#判斷IP數量是否大於0
	if [ $count -ne 0 ]
	then
		for recording in `cat $Tmp_IP`
		do
			ip=`echo $recording | awk -F',' '{print $1}'`
			domain=`echo $recording | awk -F',' '{print $2}'`
			#添加規則將請求轉發到其他服務器上的80和443端口
			iptables -I FORWARD -s $ip  -j ACCEPT
			iptables -t nat -I POSTROUTING -s $ip -j SNAT --to-source 172.31.243.145
			iptables -t nat -I PREROUTING -i eth0 -p tcp -s $ip --dport 80 -j DNAT --to-destination 112.74.169.181:80
			iptables -t nat -I PREROUTING -i eth0 -p tcp -s $ip --dport 443 -j DNAT --to-destination 112.74.169.181:443
			#將IP記錄到日誌文件當中
			echo "`date` [INFO] $ip -- $domain Too many requests Forward Warning Page !" >> $Attack_Log
		done
	fi

}



#########################
#解封一分鐘之前的IP地址方法
#########################
UnBlock_IP()
{

	#統計之前被轉發的IP個數
	count=`wc -l $Tmp_IP | awk '{ print $1 }'`

	#判斷IP數量是否大於0
	if [ $count -ne 0 ]
	then
		for ip in `cat $Tmp_IP | awk -F',' '{ print $1 }'`
		do
			#將請求轉發到警告服務器上的80和443端口的規則移除
			iptables -D FORWARD -s $ip  -j ACCEPT
			iptables -t nat -D POSTROUTING -s $ip -j SNAT --to-source 172.31.243.145
			iptables -t nat -D PREROUTING -i eth0 -p tcp -s $ip --dport 80 -j DNAT --to-destination 112.74.169.181:80
			iptables -t nat -D PREROUTING -i eth0 -p tcp -s $ip --dport 443 -j DNAT --to-destination 112.74.169.181:443
			#將IP記錄到日誌文件當中
			echo "`date` [INFO] $ip -- Delimitation time !" >> $Attack_Log
		done
	fi

}



#########
#程序主體
#########
while true

	#定義一分鐘之前的時間
	OneMinAgo=`date -d "-1 min" +%Y:%H:%M`
	#定義目前的時間
	NowTime=`date +%Y:%H:%M`

	#執行解除轉發規則方法
	UnBlock_IP
	sleep 2s
	
	#執行統計方法
	AccessLog
	sleep 2s

	#執行轉發規則方法
	Block_IP
	if [ `wc -l $Tmp_IP | awk '{ print $1 }'` -ne 0 ]
	then
		sleep 50s
	else
		sleep 5s
	fi

done	

這裏需要注意幾點的是,案例裏的閾值設爲10次每分鐘是爲了能測出效果,還有就是執行轉發是否休眠時間需要根據服務器性能而定,腳本可以使用nohup放在後臺直接執行,無需使用計劃任務,當然也可以修改一下然後放計劃任務裏面執行,這裏需要注意計劃任務是否有權限執行iptables這個命令

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章