應對CC攻擊的自動防禦系統——原理與實現
0x00 系統效果
此DDOS應用層防禦系統已經部署在了http://www.yfdc.org網站上(如果訪問失敗,請直接訪問位於國內的伺服器http://121.42.45.55進行線上測試)。
此防禦系統位於應用層,可以有效防止非法使用者對伺服器資源的濫用:
只要是傳送高頻率地、應用層請求以實現大量消耗系統資源的攻擊方式,皆可有效防禦。
其實現的基本思想是:
定期分析所有訪問使用者在過去各個時間段內的請求頻率,將頻率高於指定閾值的使用者判定為資源濫用者,將其封殺一段時間,時效過後,防禦系統自動將其解封。
線上效果測試:
進入http://www.yfdc.org -> 點選右上側線上查詢,此時將會進入/shell/yf
域內,/shell/yf
是一個用bash scripts
寫的動態web-cgi
程式,使用者每一次提交資訊,此程式將會執行一些伺服器端的查詢操作,然後將資料處理後返回到客戶端。
為了防止非法使用者高頻率地訪問這個程式,而影響到其他正常使用者的訪問,故需要進行一些保護措施。
最終效果:
被封資訊頁面
在/shell/yf域內,按住F5不放,一直重新整理,幾秒後鬆開,就能看到被封資訊和解封時間。
只要某個使用者對/shell/yf的訪問超過了正常的頻率,服務將會對這個使用者關閉一段時間,期滿後自動解封。
0x01 系統原理
作業系統: CentOS 6.5 x86_64
開發語言: Bash Shell Scripts
Web伺服器: Apache Httpd
(此圖為系統結構的鳥瞰圖 可存至本地後放大檢視)
2.1 自定義日誌:/etc/httpd/logs/yfddos_log
(自定義日誌檔案的格式)
在httpd.conf的日誌引數中,加入如下兩行:
LogFormat "%a \"%U\" %{local}p %D %{%s}t " yfddos
CustomLog logs/yfddos_log yfddos
我們接下來重點分析日誌檔案/etc/httpd/logs/yfddos_log.
LogFormat "%a \"%U\" %{local}p %D %{%s}t " yfddos
解釋:
%a -> 使用者的IP
%U -> 請求的URL地址,但並不包含query string(The URL path requested, not including any query string.)
%{local}p -> 使用者請求的伺服器埠(一般為80)
%D -> 這個請求共消耗了伺服器多少微秒(The time taken to serve the request, in microseconds.)
%{%s}t -> 伺服器收到這個請求時,時間戳的值(seconds since 1970-01-01 00:00:00 UTC)
例子:
192.168.31.1 "/shell/yf" 80 118231 1417164313
譯為:IP為192.168.31.1的主機,在時間戳為1417164313的時候,訪問了/shell/yf,並由伺服器的80埠向其提供服務,共耗時118231微秒
或為:IP為192.168.31.1的主機,在2014-11-28 16:45:13的時候,訪問了/shell/yf,並由伺服器的80埠向其提供服務,共耗時0.118231秒
至於為什麼不使用httpd.conf中官方定義的日誌,原因如下:
- 使用者訪問日誌的一條記錄可大約控制在60Bytes以內,資料量小,便於後期分析,官方定義的日誌太過臃腫,影響分析速度
- 使用時間戳標誌時間,便於後期分析,官方定義的日誌時間引數為常規的表達方式,不便於直接進行處理
- httpd的日誌系統本身就是從舊到新進行排序記錄的,所以/etc/httpd/logs/yfddos_log日誌條目的時間戳,亦為從小到大進行排序的,資料記錄更加鮮明
2.2 yfddosd黑名單檔案格式
黑名單檔案格式
yfddosd黑名單檔案/etc/yfddos/web-yf-search.b格式如下:
# ip add-stamp rmv-stamp
1.2.3.4 1416046335 1416046395
1.2.3.5 1416046336 1416046396
1.2.3.6 1416046339 1416046399
每一行為一個黑名單條目,上面第一個條目的意義為:
IP地址 :1.2.3.4
開始時間:時間戳1416046335,即 2014-11-15 18:12:15
終止時間:時間戳1416046395,即 2014-11-15 18:13:15
直觀意義為:
IP地址:1.2.3.4,從2014-11-15 18:12:15開始,被封殺1分鐘,在2014-11-15 18:13:15時自動解封。
這個檔案將由駐留在系統中的daemon守護程式yfddosd進行維護更新。
2.3 守護程式yfddosd:防禦系統的邏輯核心
守護程式的原理圖
守護程式yfddosd是整個CC防禦系統的核心,而function analyze_and_insert_black()
則是yfddosd的核心。
yfddosd的配置引數:
yfddos_blackfilePath='/etc/yfddos/web-yf-search.b'
yfddos_accesslogPath='/etc/httpd/logs/yfddos_log'
function analyze_and_insert_black() {
# analyze_and_insert_black() :
# $1:max frequency(seems as abuse if above that) $2:blackip-ttl,time to live,unit is seconds (s)
# $3:the access log ${3} seconds before will be analyzed to generate the abuse ip lists that we will block
# example : analyze_and_insert_black "limit" "ttl" "time"
# example : analyze_and_insert_black "4" "10" "5"
# 分析在過去5s內的使用者訪問日誌 如果有人在這5s內訪問量>=4 系統將視其為資源濫用者 將其加入服務黑名單
# 一條黑名單的作用時間為10s 即在10s之後 系統自動刪除此黑名單條目 服務則繼續向其開放
# global vars:
# stamp logtmpfile yfddos_blackfilePath
# ......
}
函式analyze_and_insert_black
有三個輸入引數:
例子: analyze_and_insert_black "4" "10" "5"
解釋: 分析日誌檔案/etc/httpd/logs/yfddos_log中,在過去5s內的使用者訪問日誌,如果有IP在這5s內訪問量>=4,守護程式yfddosd將視其為資源濫用者,
然後將這個IP加入到黑名單檔案/etc/yfddos/web-yf-search.b中,此條黑名單的作用時間為10s,在10s之後,守護程式yfddosd將刪除此黑名單條目。
例子: analyze_and_insert_black "150" "2700" "905"
解釋: 分析日誌檔案/etc/httpd/logs/yfddos_log中,在過去905s內的使用者訪問日誌,如果有IP在這905s內訪問量>=150,守護程式yfddosd將視其為資源濫用者,
然後將這個IP加入到黑名單檔案/etc/yfddos/web-yf-search.b中,此條黑名單的作用時間為2700s,在2700s之後,守護程式yfddosd將刪除此黑名單條目。
簡記為: analyze_and_insert_black "limit" "ttl" "time"
解釋: 分析日誌檔案/etc/httpd/logs/yfddos_log中,在過去(time)s內的使用者訪問日誌,如果有IP在這(time)s內訪問量>=limit,守護程式yfddosd將視其為資源濫用者,
然後此IP將會被加入到黑名單檔案/etc/yfddos/web-yf-search.b中,作用時間為(ttl)s,在(ttl)s之後,守護程式yfddosd將自動刪除此條目。
從上述中可看出,守護程式yfddosd至少需要完成如下三個任務:
- 分析日誌檔案/etc/httpd/logs/yfddos_log中指定時間內的使用者訪問記錄
- 將資源濫用者的IP加入檔案/etc/yfddos/web-yf-search.b,並設定封殺TTL引數值
- 將/etc/yfddos/web-yf-search.b中已經過期的條目全部及時刪除
守護程式yfddosd
是如何實現上面三個邏輯的:
分析日誌檔案/etc/httpd/logs/yfddos_log中指定時間內的使用者訪問記錄:
(1) 取出/etc/httpd/logs/yfddos_log中過去time秒的訪問日誌資料,使用二分法將這一操作的時間複雜度壓縮到K*log2(N)以內, 其中N為/etc/httpd/logs/yfddos_log中日誌總行數,K為一次測試的耗時量,一般為1ms以內,即如有1048576條訪問記錄,這一操作將僅需要20*1ms (2) 使用正則RE對這些資料進行二次處理,過濾出所有訪問指定URL的使用者IP(這個URL為想要防禦的http服務url,例如在http://www.yfdc.org系統中, 所防禦的就是/shell/yf,這個服務向訪問者提供資訊的search與get服務),再次使用sort與uniq對這些IP進行處理,以統計出每個IP的訪問次數並進行高低排序
將資源濫用者的IP加入檔案/etc/yfddos/web-yf-search.b,並設定封殺TTL引數值
將所有訪問次數超過閾值limit的IP更新到黑名單檔案/etc/yfddos/web-yf-search.b中,每個黑名單條目的封殺時間為ttl秒
將/etc/yfddos/web-yf-search.b中已經過期的條目全部及時刪除
遍歷/etc/yfddos/web-yf-search.b中所有黑名單條目,結合當前時間戳,將所有已經過期的條目一一刪去
下面是守護程式yfddosd狀態機的虛擬碼:(略去了一些處理細節)
#init and FSM start work...
counter=0
while true
do
sleep 5
counter=counter+1
delete obsolete items #將/etc/yfddos/web-yf-search.b中已經過期的條目全部刪除
if # every 5 seconds : 5s
then
analyze_and_insert_black "6" "10" "5"
# 分析在過去5s內訪問的使用者 如果有人其訪問量大於等於6 系統將視其為資源濫用者
# 遂將其加入服務黑名單 其作用時間為10s 在10s之後 daemon程式自動刪除這個ip黑名單條目
fi
if #every 5*3 seconds : 15s
then
analyze_and_insert_black "14" "45" "15"
fi
if #every 5*3*4+5 seconds : 65s
then
analyze_and_insert_black "40" "840" "65"
fi
if #every 5*3*4*3*5+5 seconds : 905s : 15min
then
analyze_and_insert_black "150" "2700" "905"
fi
if #every 5*3*4*3*5*4+5 seconds : 3605s : 1h
then
analyze_and_insert_black "300" "7200" "3605"
fi
if #every 5*3*4*3*5*4*3+5 seconds : 10805s : 3h
then
analyze_and_insert_black "400" "21600" "10805"
if #在每天的00:01-04:59時間區間 一天僅執行一次
then
#備份日誌
fi
fi
done
防禦者應斟酌調整每個檢測時間點的引數值(封殺時間ttl與判定閾值limit),以調節系統應對CC攻擊到來時的反應時間。
0x02 原始碼
#!bash
##################################### vim /usr/local/bin/yfddosd.sh :
##################################### nohup bash /usr/local/bin/yfddosd.sh &>"/etc/yfddos/""yfddosd-log-`date +%Y-%m-%d`" &
##################################### yfddos daemon
mkdir /etc/yfddos
yfddos_blackfilePath='/etc/yfddos/web-yf-search.b'
yfddos_accesslogPath='/etc/httpd/logs/yfddos_log'
### refresh tll
logtmpfile=`mktemp`
stamp=`date +%s`
touch "$yfddos_blackfilePath"
if grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$yfddos_blackfilePath" &>/dev/null
then
cat "$yfddos_blackfilePath" | while read i
do
deadstamp=`echo "$i" | grep -Po '[0-9]+$'`
if [ "$stamp" -le "$deadstamp" ]
then
echo "$i" >>"$logtmpfile"
fi
done
fi
chmod o+r "$logtmpfile"
mv -f "$logtmpfile" "$yfddos_blackfilePath"
if ! grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$yfddos_blackfilePath" &>/dev/null
then
echo '255.255.255.255 0 0' >> "$yfddos_blackfilePath"
fi
function analyze_and_insert_black() {
# analyze_and_insert_black() :
# $1:max frequency(seems as abuse if above that) $2:blackip-ttl,time to live,unit is seconds (s)
# $3:the access log ${3} seconds before will be analyzed to generate the abuse ip lists that we will block
# example : analyze_and_insert_black "limit" "ttl" "time"
# example : analyze_and_insert_black "4" "10" "5"
# 分析在過去5s內的使用者訪問日誌 如果有人在這5s內訪問量>=4 系統將視其為資源濫用者 將其加入服務黑名單
# 一條黑名單的作用時間為10s 即在10s之後 系統自動刪除此黑名單條目 服務則繼續向其開放
# global vars:
# stamp logtmpfile yfddos_blackfilePath
local threshold="$1"
local ttl="$2"
local stamp_pre="$3"
local i=0
local num=""
local fre=0
local ip=0
local localbuf=0
local linenum=0
local deadstamp=0
stamp_pre="$((stamp-stamp_pre))"
#二分查詢初始化
local temp=0
local yf_x='1'
local yf_y=`cat "$logtmpfile" | wc -l`
if [ "$yf_y" -le "1" ]
then
yf_y=1
fi
local yf_I=$(((yf_x+yf_y)/2))
temp=`cat "$logtmpfile" | wc -l`
if [ "$temp" -gt "0" ]
then
temp=`sed -n '$p' "$logtmpfile" | grep -Po '[0-9]+ $'`
if [ "$temp" -lt "$stamp_pre" ]
then
num=""
else
while true #使用二分查詢的方法 快速地分析訪問日誌
do
temp=`sed -n "${yf_x}p" "$logtmpfile" | grep -Po '[0-9]+ $'`
if [ "$temp" -ge "$stamp_pre" ]
then
break
fi
if [ "$((yf_y-yf_x))" -le "1" ]
then
yf_x="$yf_y"
break
fi
temp=`sed -n "${yf_I}p" "$logtmpfile" | grep -Po '[0-9]+ $'`
if [ "$temp" -lt "$stamp_pre" ]
then
yf_x="$yf_I"
yf_y="$yf_y"
yf_I="$(((yf_x+yf_y)/2))"
continue
fi
yf_x="$yf_x"
yf_y="$yf_I"
yf_I="$(((yf_x+yf_y)/2))"
continue
done
temp=`sed -n "${yf_x}p" "$logtmpfile" | grep -Po '[0-9]+ $'`
if [ "$temp" -ge "$stamp_pre" ]
then
num="$yf_x"
else
num=""
fi
fi
if [ -n "$num" ]
then
sed -n "${num},\$p" "$logtmpfile" | grep -Po '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort -n | uniq -c | sort -rn | while read i
do
fre=`echo "$i" | grep -Po '[0-9]+' | head -1`
ip=`echo "$i" | grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' `
if [ "$fre" -ge "$threshold" ]
then #insert illegal ips : cat "$yfddos_blackfilePath"
# ip add-stamp rmv-stamp
#1.2.3.4 1416046335 1416046395
temp=`grep -Pn "${ip//./\\.} " "$yfddos_blackfilePath"`
if [ -n "$temp" ]
then
linenum=`echo "$temp" | grep -Po '^[0-9]+' | head -1`
deadstamp=`echo "$temp" | grep -Po '[0-9]+$' | sort -rn | head -1 `
if [ "$((stamp+ttl))" -gt "$deadstamp" ]
then
sed -i "${linenum}s/.*/${ip} ${stamp} $((stamp+ttl))/g" "$yfddos_blackfilePath"
fi
else
sed -i "\$a ${ip} ${stamp} $((stamp+ttl))" "$yfddos_blackfilePath"
fi
else
break
fi
done
fi
fi
}
#init and yfddosd's FSM start work...
counter=0
while true
do
sleep 5
counter=$((counter+1))
echo -n `date +%Y-%m-%d\ %H:%M:%S`" ""counter ${counter}:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
echo -n "refresh tll:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
### refresh tll
#refresh ttl: analyze file: "$yfddos_blackfilePath" if some items'ttl has been reach the date , we will remove it and open service to the ip had been banned before.
#insert illegal ips : cat "$yfddos_blackfilePath"
# ip add-stamp rmv-stamp
#1.2.3.4 1416046335 1416046395
#sed -i "/^.* $((stamp-5))$/d;/^.* $((stamp-4))$/d;/^.* $((stamp-3))$/d;/^.* $((stamp-2))$/d;/^.* $((stamp-1))$/d;/^.* $((stamp))$/d;/^$/d" "$yfddos_blackfilePath"
logtmpfile=`mktemp`
stamp=`date +%s`
touch "$yfddos_blackfilePath"
if grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$yfddos_blackfilePath" &>/dev/null
then
cat "$yfddos_blackfilePath" | while read i
do
deadstamp=`echo "$i" | grep -Po '[0-9]+$'`
if [ "$stamp" -le "$deadstamp" ]
then
echo "$i" >>"$logtmpfile"
fi
done
fi
chmod o+r "$logtmpfile"
mv -f "$logtmpfile" "$yfddos_blackfilePath"
if ! grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$yfddos_blackfilePath" &>/dev/null
then
echo '255.255.255.255 0 0' >> "$yfddos_blackfilePath"
fi
logtmpfile=`mktemp`
stamp=`date +%s`
cat "$yfddos_accesslogPath" | grep -P ' "/shell/yf" ' >"$logtmpfile"
if true # every 5 seconds : 5s
then
echo -n "analyze_and_insert_black 6 10 5:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
#analyze yfddos log : analyze_and_insert_black() $1:max frequency(seems as abuse if above that) $2:blackip-ttl $3:the access log ${3} seconds before will be analyzed to generate the abuse ips that we will block
analyze_and_insert_black "6" "10" "5"
# 分析在過去5s內訪問的使用者 如果有人其訪問量大於等於6 系統將視其為資源濫用者 遂將其加入服務黑名單 其作用時間為10s 在10s之後 daemon程式自動刪除這個ip黑名單條目
fi
if [ "$((counter%(3)))" -eq "0" ] #every 5*3 seconds : 15s
then
echo -n "analyze_and_insert_black 14 45 15:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
# example : analyze_and_insert_black "limit" "ttl" "time"
analyze_and_insert_black "10" "45" "15"
fi
if [ "$((counter%(3*4+1)))" -eq "0" ] #every 5*3*4+5 seconds : 65s
then
echo -n "analyze_and_insert_black 40 840 65:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
# example : analyze_and_insert_black "limit" "ttl" "time"
analyze_and_insert_black "25" "840" "65"
fi
if [ "$((counter%(3*4*3*5+1)))" -eq "0" ] #every 5*3*4*3*5+5 seconds : 905s : 15min
then
echo -n "analyze_and_insert_black 150 2700 905:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
# example : analyze_and_insert_black "limit" "ttl" "time"
analyze_and_insert_black "150" "2700" "905"
fi
if [ "$((counter%(3*4*3*5*4+1)))" -eq "0" ] #every 5*3*4*3*5*4+5 seconds : 3605s : 1h
then
echo -n "analyze_and_insert_black 300 7200 3605:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
# example : analyze_and_insert_black "limit" "ttl" "time"
analyze_and_insert_black "300" "7200" "3605"
fi
if [ "$((counter%(3*4*3*5*4*3+1)))" -eq "0" ] #every 5*3*4*3*5*4*3+5 seconds : 10805s : 3h
then
echo -n "analyze_and_insert_black 400 21600 10805:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
# example : analyze_and_insert_black "limit" "ttl" "time"
analyze_and_insert_black "400" "21600" "10805"
#### "${yfddos_accesslogPath}" backup : 在每天的00:01-04:59時間區間內 備份日誌一次
if [ "`date +%H`" -le "5" ] && ! [ -f "${yfddos_accesslogPath}-`date +%Y-%m-%d`" ]
then
service httpd stop
mv "${yfddos_accesslogPath}" "${yfddos_accesslogPath}-`date +%Y-%m-%d`"
service httpd start
fi
fi
rm -fr "$logtmpfile"
echo "sleep:"`cat /proc/uptime | grep -Po '[0-9\.]+' | head -1`" "
done
相關文章
- CC攻擊的原理是什麼?如何防禦CC攻擊?2023-03-14
- CC攻擊的原理是什麼?防禦CC攻擊的方法有哪些?2022-11-15
- CC攻擊原理是什麼?網站被CC攻擊如何防禦?2023-10-25網站
- cc攻擊防禦解決方法2022-06-06
- 【知識科普】高防伺服器防禦CC攻擊的原理2022-10-25伺服器
- 伺服器如何防禦CC攻擊2022-10-22伺服器
- 什麼是CC攻擊?網站被CC攻擊該如何防禦?2022-06-13網站
- DDoS 攻擊與防禦:從原理到實踐2024-05-16
- CC攻擊的原理和應對的策略2022-12-07
- 淺談 JavaScript DDoS 攻擊原理與防禦2015-05-17JavaScript
- 淺談JavaScript DDoS攻擊原理與防禦2015-05-18JavaScript
- 淺談JS DDoS攻擊原理與防禦2015-05-16JS
- WEB攻擊與防禦2018-03-31Web
- CSRF攻擊與防禦2024-11-01
- 淺談DDOS攻擊攻擊與防禦2012-07-26
- 【網路安全】如何有效地防禦DDOS攻擊和CC攻擊?2022-01-20
- 【知識分享】伺服器防禦cc攻擊的方法2023-03-31伺服器
- DDOS攻擊原理,種類及其防禦2019-01-24
- 淺談DDos攻擊與防禦2018-06-23
- 【網路安全入門知識】如何有效防禦DDoS攻擊和CC攻擊?2022-01-06
- XXE攻擊攻擊原理是什麼?如何防禦XXE攻擊?2023-02-13
- 【網路安全經驗分享】CC攻擊防禦方法有哪些?2022-08-31
- 應對網路攻擊:提前預警+積極防禦2017-07-03
- WMI 的攻擊,防禦與取證分析技術之防禦篇2020-08-19
- Java HTTP Host 頭攻擊原理以及如何防禦2019-02-21JavaHTTP
- CSRF(Cross Site Request Forgery)攻擊原理和防禦2018-10-18ROS
- 網路攻擊盯上民生領域,應對DDoS和APT攻擊,如何有效防禦?2022-05-24APT
- WMI 的攻擊,防禦與取證分析技術之攻擊篇2020-08-19
- CSS keylogger:攻擊與防禦2019-01-03CSS
- 生成樹欺騙攻擊與防禦策略2023-09-28
- 淺談 CC 攻擊的防護方法2019-01-07
- 網路攻擊無視cc+ddos完美防禦刪前速看2020-09-16
- Jtti:國外jsp空間租用怎麼防禦cc攻擊2023-05-10JttiJS
- CC攻擊:CC攻擊的原理便是攻擊者控制某些主機不停地發許2019-09-03
- 高防伺服器主要防禦的攻擊2020-01-18伺服器
- 面對境外網路的攻擊,該如何有效防禦?2022-04-29
- 瞭解cc攻擊才能對應解決2020-06-04
- ARP病毒攻擊技術分析與防禦2006-11-14