Linux下防御DDOS攻击工具(DDoS deflate)分析与改造
工作过程描述:
同一个IP链接到服务器的连接数到达设置的伐值后,所有超过伐值的IP将被屏蔽,同时把屏蔽的IP写入ignore.ip.list文件中,与此同时会在tmp中生成一个脚本文件,这个脚本文件马上被执行,但是一运行就遇到sleep 预设的秒,当睡眠了这么多的时间后,解除被屏蔽的IP,同时把之前写入ignore.ip.list文件中的这个被封锁的IP删除,然后删除临时生成的文件。
一个事实:如果被屏蔽的IP手工解屏蔽,那么如果这个IP继续产生攻击,那么脚本将不会再次屏蔽它(因为加入到了ignore.ip.list),直到在预设的时间之后才能起作用,加入到了ignore.ip.list中的IP是检测的时候忽略的IP。可以把IP写入到这个文件以避免这些IP被堵塞,已经堵塞了的IP也会加入到ignore.ip.list中,但堵塞了预定时间后会从它之中删除。
安装:
wget http://www.inetbase.com/scripts/ddos/install.sh
chmod 0700 install.sh
./install.sh
卸载:
wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
chmod 0700 uninstall.ddos
./uninstall.ddos
安装完成后在/usr/local/ddos目录下产生了ddos.conf、ddos.sh、ignore.ip.list和LICENSE这四个文件,ddos.conf是配置文件,ddos.sh是一个Shell文件,ignore.ip.list是存放忽略IP的文件,LICENSE是版权声明文件,安装完成后还在/etc/cron.d/下生产了ddos.cron文件,内容如下:
SHELL=/bin/sh
0-59/1 * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1
意思是每隔一分钟执行一下/usr/local/ddos/ddos.sh
这个cron任务是依赖ddos.conf文件中的NO_OF_CONNECTIONS变量产生的,如果修改了此值,可以通过运行如下命令更新(实际也是在安装是运行了如下命令):
/usr/local/ddos/ddos.sh -c 或 /usr/local/ddos/ddos.sh –cron
以下主要针对ddos.conf和ddos.sh进行分析:
ddos.conf内容:
##### Paths of the script and other filesPROGDIR="/usr/local/ddos"PROG="/usr/local/ddos/ddos.sh"IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"CRON="/etc/cron.d/ddos.cron"APF="/etc/apf/apf"IPT="/sbin/iptables"##### frequency in minutes for running the script##### Caution: Every time this setting is changed, run the script with --cron##### option so that the new frequency takes effect# 设置检测时间间隔,默认是分钟,由于系统使用crontab功能,最小单位是分钟FREQ=1##### How many connections define a bad IP? Indicate that below.# NO_OF_CONNECTIONS默认是150,这是一个经验值,如果服务器性能比较高,可以设置200以上,以避免误杀NO_OF_CONNECTIONS=150##### APF_BAN=1 (Make sure your APF version is atleast 0.96)##### APF_BAN=0 (Uses iptables for banning ips instead of APF)# 使用APF屏蔽IP,如果设置为0就使用iptables,如果使用APF则需要先安装,比如centos中默认就没有安装APF_BAN=0##### KILL=0 (Bad IPs are'nt banned, good for interactive execution of script)##### KILL=1 (Recommended setting)KILL=1##### An email is sent to the following address when an IP is banned.##### Blank would suppress sending of mails# 如果不希望发送邮件,设置为空EMAIL_TO=""##### Number of seconds the banned ip should remain in blacklist.# 解锁的时间,单位为秒,可以设置更长时间BAN_PERIOD=86400
ddos.sh内容:
# 载入配置文件load_conf(){ CONF="/usr/local/ddos/ddos.conf" # $CONF是文件,使用source载入 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}# 显示帮助,比如如果要收到干掉当前超过N个连接的IP,使用sh ddos.sh -k 150, sh ddos.sh -h 显示帮助, sh ddos.sh -c创建cron jobshowhelp(){ 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 '}# 解除对IP的封锁unbanip(){ UNBAN_SCRIPT=`mktemp /tmp/unban.XXXXXXXX` # 产生随机文件,解除IP封锁时 TMP_FILE=`mktemp /tmp/unban.XXXXXXXX` # 临时文件 UNBAN_IP_LIST=`mktemp /tmp/unban.XXXXXXXX` # 将被解除封锁的IP echo '#!/bin/sh' > $UNBAN_SCRIPT # 产生解除IP封锁的脚本内容 echo "sleep $BAN_PERIOD" >> $UNBAN_SCRIPT # $BAN_PERIOD睡眠时间,表示$UNBAN_SCRIPT睡眠多久后继续,这个变量在配置文件中定义 if [ $APF_BAN -eq 1 ]; then # 使用APF堵塞IP while read line; do echo "$APF -u $line" >> $UNBAN_SCRIPT echo $line >> $UNBAN_IP_LIST done < $BANNED_IP_LIST else # 使用iptables封锁IP while read line; do echo "$IPT -D INPUT -s $line -j DROP" >> $UNBAN_SCRIPT # 解除IP封锁 echo $line >> $UNBAN_IP_LIST # 把将要解除堵塞的IP写入$UNBAN_IP_LIST,跟当前的$BANNED_IP_LIST是对应的 done < $BANNED_IP_LIST # 输入重定向,行对于$line变量,是当前需要堵塞的IP,脚本运行过程中产生 fi echo "grep -v --file=$UNBAN_IP_LIST $IGNORE_IP_LIST > $TMP_FILE" >> $UNBAN_SCRIPT # 从$IGNORE_IP_LIST中去掉$UNBAN_IP_LIST,把结果写入$TMP_FILE echo "mv $TMP_FILE $IGNORE_IP_LIST" >> $UNBAN_SCRIPT # 移动$TMP_FILE到$IGNORE_IP_LIST,$IGNORE_IP_LIST在配置文件中定义,则本次操作是覆盖 echo "rm -f $UNBAN_SCRIPT" >> $UNBAN_SCRIPT # 删除$UNBAN_SCRIPT echo "rm -f $UNBAN_IP_LIST" >> $UNBAN_SCRIPT # 删除$UNBAN_IP_LIST echo "rm -f $TMP_FILE" >> $UNBAN_SCRIPT # 删除$TMP_FILE,经过上面的移动操作,$TMP_FILE其实已经不存在 . $UNBAN_SCRIPT & # 在后台运行$UNBAN_SCRIPT}# 添加到计划任务add_to_cron(){ rm -f $CRON # 删除/etc/cron.d/ddos.cron sleep 1 service crond restart # 计划任务重启 sleep 1 echo "SHELL=/bin/sh" > $CRON # 创建计划任务 if [ $FREQ -le 2 ]; then # $FREQ在配置文件中定义,表示多少分钟执行一次,如果小于2,Linux最小是每分钟 # 以下语句得到 0-59/1 * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1,每分钟以root执行ddos.sh,把输出结果丢弃 echo "0-59/$FREQ * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1" >> $CRON else # 大于1分钟设置 let "START_MINUTE = $RANDOM % ($FREQ - 1)" # $RANDOM是环境变量随机数 let是shell内建命令,就是执行计算 let "START_MINUTE = $START_MINUTE + 1" let "END_MINUTE = 60 - $FREQ + $START_MINUTE" echo "$START_MINUTE-$END_MINUTE/$FREQ * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1" >> $CRON fi service crond restart}# 加载配置load_conf# 判断$1,是第一个参数,提供帮助,如果没有提供则不会进入循环while [ $1 ]; do case $1 in '-h' | '--help' | '?' ) showhelp # 显示帮助 exit ;; '--cron' | '-c' ) add_to_cron # 添加到计划任务 exit ;; '--kill' | '-k' ) KILL=1 # KILL在配置文件中指定,用来指定是否堵塞IP ;; *[0-9]* ) NO_OF_CONNECTIONS=$1 # 第二个参数,指定阀值,NO_OF_CONNECTIONS在配置文件中指定,这里覆盖 ;; * ) showhelp exit ;; esac shift # 减少变量,就是现在$1是原来的$2,shift后可以指定减少几个doneTMP_PREFIX='/tmp/ddos'TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX"BANNED_IP_MAIL=`$TMP_FILE` # 产生临时文件,发送邮件,邮件内容BANNED_IP_LIST=`$TMP_FILE` # 产生临时文件,存放已经被堵塞的IPecho "Banned the following ip addresses on `date`" > $BANNED_IP_MAIL 构建邮件内容echo >> $BANNED_IP_MAILBAD_IP_LIST=`$TMP_FILE` # 产生临时文件,存放当前可能被堵塞的IPnetstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LISTcat $BAD_IP_LIST # 输出这个列表if [ $KILL -eq 1 ]; then # 如果配置为需要堵塞 IP_BAN_NOW=0 while read line; do CURR_LINE_CONN=$(echo $line | cut -d" " -f1) # 当前这个IP有多少个连接 CURR_LINE_IP=$(echo $line | cut -d" " -f2) # 当前IP if [ $CURR_LINE_CONN -lt $NO_OF_CONNECTIONS ]; then # 如果这个IP链接数小于预设,终止(因为数据经过排序) break fi IGNORE_BAN=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST` # 计算当前IP在$IGNORE_IP_LIST出现了多少次 if [ $IGNORE_BAN -ge 1 ]; then # 如果当前IP已经在$IGNORE_IP_LIST,跳过,可以通过这个方式设置永不堵塞某些IP continue fi IP_BAN_NOW=1 # 进入到这里表示当前必定有IP要被堵塞 echo "$CURR_LINE_IP with $CURR_LINE_CONN connections" >> $BANNE_IP_MAIL # 把堵塞信息写入邮件内容 echo $CURR_LINE_IP >> $BANNED_IP_LIST # 添加堵塞了的IP到当前堵塞列表,$BANNED_IP_LIST会应用到下面的unbanip函数 echo $CURR_LINE_IP >> $IGNORE_IP_LIST # 添加堵塞了的IP到$IGNORE_IP_LIST if [ $APF_BAN -eq 1 ]; then $APF -d $CURR_LINE_IP else $IPT -I INPUT -s $CURR_LINE_IP -j DROP # 开始iptables封锁 fi done < $BAD_IP_LIST if [ $IP_BAN_NOW -eq 1 ]; then # $IP_BAN_NOW等于1表示有IP被封锁了 dt=`date` if [ $EMAIL_TO != "" ]; then # $EMAIL_TO设置不为空则发邮件,留空则不发邮件 cat $BANNED_IP_MAIL | mail -s "IP addresses banned on $dt" $EMAIL_TO # $EMAIL_TO在配置文件中指定 fi unbanip # 同时开始运行解除堵塞程序 fifirm -f $TMP_PREFIX.* # 清除临时产生的文件
可以看到如果有堵塞IP,将调用mail发送邮件,但是作为前端代理,视乎没有必要特意去安装sendmail,所以我们可以使用curl把数据推送到远程,由另一台专门的服务器发送这些信息,改造如下:
if [ $EMAIL_TO != "" ]; then cat $BANNED_IP_MAIL | mail -s "IP addresses banned on $dt" $EMAIL_TOelse curl --data "d=IP addresses banned on $dt -- $(cat $BANNED_IP_MAIL)" "http://domain.com/blockip.php" >> /dev/nullfi
除此,尽管默认到达150才堵塞,但你可能希望把那些超过100链接的IP都记录下来,可以在cat $BAD_IP_LIST之后添加如下代码:
NUM_CONNECTIONS=100 # 超过100就记录# 按照日期存放CNTS_LOG="/usr/local/ddos/$(date +%Y)/$(date +%m)/"mkdir -p $CNTS_LOGCNTS_LOG="$CNTS_LOG$(date +%Y%m%d).log"while read line; do CURR_CONN=$(echo $line | cut -d" " -f1) CURR_IP=$(echo $line | cut -d" " -f2) if [ $CURR_CONN -lt $NUM_CONNECTIONS ]; then break fi echo "$CURR_IP with $CURR_CONN connections at `date`" >> $CNTS_LOGdone < $BAD_IP_LIST
- 03-25工业 4.0 正在推动企业光纤接入
- 03-25深入了解 5G 基础设施
- 03-25开展网络行为风险分析的五种手段
- 03-25美国国家安全局是如何入侵你的电脑的?
- 11-18攻击者利用SSL进行加密攻击和通信
- 11-18骗子利用Google Ads从假加密货币钱包中抽走数十万美金
- 11-18手把手教你如何实现一个简单的数据加解密算法
- 11-18安全事件响应计划的五个步骤
- 01-11全球最受赞誉公司揭晓:苹果连续九年第一
- 12-09罗伯特·莫里斯:让黑客真正变黑
- 12-09谁闯入了中国网络?揭秘美国绝密黑客小组TA
- 12-09警示:iOS6 惊现“闪退”BUG
- 03-21虎牙2023年全年营收70亿元
- 03-21未来,政企深度用云需要一朵怎样的“云”?
- 03-21知乎盐言故事推出“3A计划”:加速AI应用 自
- 03-21苹果CEO库克:对于苹果供应链,没有比中国更
- 03-21华为与伙伴共探全光网络“三进三退”千亿新