DDOS-deflate工具:ddos.sh脚本解读(预防DDOS攻击脚本)
[root@server ddos]# cat ddos.sh
#!/bin/sh
##############################################################################
# DDoS-Deflate version 0.6 Author: Zaf <zaf@vsnl.com> #
##############################################################################
# This program is distributed under the "Artistic License" Agreement #
# #
# The LICENSE file is located in the same directory as this program. Please #
# read the LICENSE file before you make copies or distribute this program #
##############################################################################
load_conf() # 定义一个加载DDOS配置文件的函数,DDOS配置文件存在则加载,否则输出head()并退出。
{
CONF="/usr/local/ddos/ddos.conf"
if [ -f "$CONF" ] && [ ! "$CONF" == "" ]; then
source $CONF
else
head
echo "\$CONF not found."
exit 1
fi
}
head() # 定义固定文本的函数
{
echo "DDoS-Deflate version 0.6"
echo "Copyright (C) 2005, Zaf <zaf@vsnl.com>"
echo
}
showhelp() # 定义显示帮助信息的函数
{
head
echo 'Usage: ddos.sh [OPTIONS] [N]'
echo 'N : number of tcp/udp connections (default 150)'
echo 'OPTIONS:'
echo '-h | --help: Show this help screen'
echo '-c | --cron: Create cron job to run this script regularly (default 1 mins)'
echo '-k | --kill: Block the offending ip making more than N connections'
}
unbanip() # 等待指定时间后,删除无效的规则链,解除拒绝的IP
{
UNBAN_SCRIPT=`mktemp /tmp/unban.XXXXXXXX` # mktemp创建临时文件,文件名参数为:文件名.XXXX。使用iptables操作拒绝IP访问服务器的脚本文件。
TMP_FILE=`mktemp /tmp/unban.XXXXXXXX`
UNBAN_IP_LIST=`mktemp /tmp/unban.XXXXXXXX` # 已拒绝的IP都放到这个文件中
echo '#!/bin/sh' > $UNBAN_SCRIPT
echo "sleep $BAN_PERIOD" >> $UNBAN_SCRIPT # 等待600s
if [ $APF_BAN -eq 1 ]; then # APF_BAN值为1
while read line; do
echo "$APF -u $line" >> $UNBAN_SCRIPT
echo $line >> $UNBAN_IP_LIST
done < $BANNED_IP_LIST
else # APF_BAN值为0
while read line; do #
echo "$IPT -D INPUT -s $line -j DROP" >> $UNBAN_SCRIPT # 把上一次被拒绝的IP地址重新设置为允许,即删除对应的DROP规则链
echo $line >> $UNBAN_IP_LIST # 重新设置允许的IP都写入该文件
done < $BANNED_IP_LIST # 输入的文件,历史访问次数统计信息
fi
echo "grep -v --file=$UNBAN_IP_LIST $IGNORE_IP_LIST > $TMP_FILE" >> $UNBAN_SCRIPT # IGNORE_IP_LIST文件根据UNBAN_IP_LIST文件中的匹配规则,筛选出匹配不上的IP地址,并写入到临时文件中。
echo "mv $TMP_FILE $IGNORE_IP_LIST" >> $UNBAN_SCRIPT # 将TMP_FILE文件重命名为IGNORE_IP_LIST,即不删除DROP规则链的IP地址。仍然设置为拒绝访问服务器。
# 删除以下三个临时文件
echo "rm -f $UNBAN_SCRIPT" >> $UNBAN_SCRIPT
echo "rm -f $UNBAN_IP_LIST" >> $UNBAN_SCRIPT
echo "rm -f $TMP_FILE" >> $UNBAN_SCRIPT
. $UNBAN_SCRIPT & # 后台执行脚本UNBAN_SCRIPT
}
add_to_cron() # 定义更新定时任务的函数
{
rm -f $CRON # 若ddos.cron定时任务存在,删除定时任务
sleep 1
service crond restart # 重启crond服务
sleep 1
echo "SHELL=/bin/sh" > $CRON
if [ $FREQ -le 2 ]; then # 检查间隔小于等于2分钟,检查时间间隔的取值范围一般为0-59,单位分钟。
echo "0-59/$FREQ * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1" >> $CRON
else # 检查间隔大于2分钟
let "START_MINUTE = $RANDOM % ($FREQ - 1)" # 若FREQ是5,START_MINUTE为0 1 2 3
let "START_MINUTE = $START_MINUTE + 1" # START_MINUTE为1 2 3 4
let "END_MINUTE = 60 - $FREQ + $START_MINUTE" # END_MINUTE = 60 - 5 + [1 2 3 4] = [56 57 58 59]
echo "$START_MINUTE-$END_MINUTE/$FREQ * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1" >> $CRON # 0-59之间的第一个检查时间START_MINUTE,最后一个检查时间END_MINUTE
fi
service crond restart # 重启crond服务
}
load_conf # 加载ddos.conf配置文件
while [ $1 ]; do
case $1 in
'-h' | '--help' | '?' )
showhelp # 显示帮助信息的函数
exit
;;
'--cron' | '-c' ) # 添加定时任务
add_to_cron
exit
;;
'--kill' | '-k' ) # 启用拒绝IP的功能
KILL=1
;;
*[0-9]* )
NO_OF_CONNECTIONS=$1 # 指定阈值,用于手动执行ddos.sh脚本时使用,默认的阈值为ddos.conf文件中的NO_OF_CONNECTIONS
;;
* )
showhelpcatcat
exit
;;
esac
shift
done
TMP_PREFIX='/tmp/ddos' # 临时文件前缀
TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX" # 创建一个临时文件的命令
BANNED_IP_MAIL=`$TMP_FILE` # 执行创建一个临时文件
BANNED_IP_LIST=`$TMP_FILE` # 执行创建一个临时文件
echo "Banned the following ip addresses on `date`" > $BANNED_IP_MAIL # 在当前时间下禁止以下IP地址
echo >> $BANNED_IP_MAIL # 空一行
BAD_IP_LIST=`$TMP_FILE`
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST # 统计访问服务器的IP地址机器访问次数,并把结果写入文件BAD_IP_LIST
cat $BAD_IP_LIST # 显示BAD_IP_LIST文件中的统计信息
if [ $KILL -eq 1 ]; then # KILL的值等于1
IP_BAN_NOW=0
while read line; do
CURR_LINE_CONN=$(echo $line | cut -d" " -f1) # 次数
CURR_LINE_IP=$(echo $line | cut -d" " -f2) # IP地址
if [ $CURR_LINE_CONN -lt $NO_OF_CONNECTIONS ]; then # 次数小于阈值,跳出当前整个循环。
break
fi
IGNORE_BAN=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST` # 计算统计信息中的IP地址在IGNORE_IP_LIST文件中的IP个数,即白名单IP
if [ $IGNORE_BAN -ge 1 ]; then # 若在文件IGNORE_IP_LIST文件中的IP个数大于等于1
continue # 继续循环
fi
IP_BAN_NOW=1
echo "$CURR_LINE_IP with $CURR_LINE_CONN connections" >> $BANNED_IP_MAIL # 说明某个IP访问多少次
echo $CURR_LINE_IP >> $BANNED_IP_LIST # 把IP写入到BANNED_IP_LIST文件中
echo $CURR_LINE_IP >> $IGNORE_IP_LIST # 把IP写入到IGNORE_IP_LIST文件中
if [ $APF_BAN -eq 1 ]; then
$APF -d $CURR_LINE_IP # 当APF_BAN的值为1时,使用APF的方式拒绝IP
else
$IPT -I INPUT -s $CURR_LINE_IP -j DROP # 当APF_BAN不等于1时,使用iptables的方式添加规则拒绝指定IP访问服务器
fi
done < $BAD_IP_LIST # 访问服务器的统计信息作为输入
if [ $IP_BAN_NOW -eq 1 ]; then # IP_BAN_NOW的值为1
dt=`date`
if [ $EMAIL_TO != "" ]; then
cat $BANNED_IP_MAIL | mail -s "IP addresses banned on $dt" $EMAIL_TO # 把被拒绝的IP地址,发送到邮箱EMAIL_TO
fi
unbanip # 取消拒绝IP地址
fi
fi
rm -f $TMP_PREFIX.* # 删除创建的临时文件
ddos.sh 脚本总结:
-
脚本结构说明:
声明了5个函数,分别为load_conf、head、showhelp、unbanip、add_to_cron。各函数作用如下:
load_conf:加载ddox.conf文件的内容
head:输出的固定表头
showhelp:显示帮助信息
unbanip:等待指定时间后,删除全部无效的规则链,解除拒绝的IP。
add_to_cron:添加定时任务 -
主体说明【除函数声明外的部分】:
①创建临时文件BAD_IP_LIST,并把访问服务器的统计信息写入其中。
②KILL参数决定是否屏蔽IP,当KILL的值为1时,访问次数超过阈值的才会被屏蔽,并指定了屏蔽方式时APF还是iptables,建议使用iptables。
③当IP_BAN_NOW的值为1时,发送拒绝IP的消息给指定邮箱EMAIL_TO,然后执行unbanip函数,即等待BAN_PERIOD时间后,将已拒绝的IP地址对应的iptables规则链删除,允许其访问服务器。
④最后删除所有的临时文件。 -
整体流程说明:
首先通过netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -nr 获取到访问服务器的IP地址和次数的统计信息,然后对访问次数超过阈值的IP地址进行拒绝访问操作,即添加DROP的规则链,最后等待BAN_PERIOD时间后,删除之前添加的DROP规则链。以上流程设置定时任务,默认是每分钟都进行一次。