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