脚本编程

Linux系统防CC攻击自动拉黑IP增强版Shell脚本

Jager · 11月5日 · 2014年 · · 20170次已读

最新更新:张戈博客已推出功能更强大的轻量级CC攻击防御脚本工具CCKiller==>传送门

前天没事写了一个防CC攻击的Shell脚本,没想到这么快就要用上了,原因是因为360网站卫士的缓存黑名单突然无法过滤后台,导致WordPress无法登录!虽然,可以通过修改本地hosts文件来解决这个问题,但是还是想暂时取消CDN加速和防护来测试下服务器的性能优化及安全防护。

前天写的Shell脚本是加入到crontab计划任务执行的,每5分钟执行一次,今天实际测试了下,可还是可以用的,但是感觉5分钟时间有点过长,无法做到严密防护。于是稍微改进了下代码,现在简单的分享下!

一、Shell代码

#!/bin/bash
#Author:ZhangGe
#Desc:Auto Deny Black_IP Script.
#Date:2014-11-05
#取得参数$1为并发阈值,若留空则默认允许单IP最大50并发(实际测试发现,2M带宽,十来个并发服务器就已经无法访问了!)
if [[ -z $1 ]];then
        num=50
else 
        num=$1
fi

#巧妙的进入到脚本工作目录
cd $(cd $(dirname $BASH_SOURCE) && pwd)

#请求检查、判断及拉黑主功能函数
function check(){
        iplist=`netstat -an |grep ^tcp.*:80|egrep -v 'LISTEN|127.0.0.1'|awk -F"[ ]+|[:]" '{print $6}'|sort|uniq -c|sort -rn|awk -v str=$num '{if ($1>str){print $2}}'`
        if [[ ! -z $iplist ]];
                then
                >./black_ip.txt
                for black_ip in $iplist
                do
                        #白名单过滤中已取消IP段的判断功能,可根据需要自行修改以下代码(请参考前天写的脚本)
                        #exclude_ip=`echo $black_ip | awk -F"." '{print $1"."$2"."$3}'`
                        #grep -q $exclude_ip ./white_ip.txt
                        grep -q $black_ip ./white_ip.txt
                        if [[ $? -eq 0 ]];then
                                echo "$black_ip (white_ip)" >>./black_ip.txt
                        else
                                echo $black_ip >>./black_ip.txt     
                                iptables -nL | grep $black_ip ||(iptables -I INPUT -s $black_ip -j DROP & echo "$black_ip  `date +%Y-%m-%H:%M:%S`">>./deny.log & echo 1 >./sendmail)
                        fi
                done
                #存在并发超过阈值的单IP就发送邮件
                if [[ `cat ./sendmail` == 1 ]];then sendmsg;fi
        fi
}

#发邮件函数
function sendmsg(){
        netstat -nutlp | grep "sendmail" >/dev/null 2>&1 || /etc/init.d/sendmail start >/dev/null 2>&1
        echo -e "From: 发邮件地址@qq.com\nTo:收邮件地址@qq.com\nSubject:Someone Attacking your system!!\nIts Ip is" >./message
        cat ./black_ip.txt >>./message
        /usr/sbin/sendmail -f 发邮件地址@qq.com -t 收邮件地址@qq.com -i <./message
        >./sendmail
}

#间隔10s无限循环检查函数
while true
do 
        check
        #每隔10s检查一次,时间可根据需要自定义
        sleep 10
done

二、执行脚本

将以上代码保存为deny_blackip.sh之后,进入到脚本文件所在目录,然后使用如下命令后台执行脚本(后面的50表示并发数,可自行调整):

nohup ./deny_blackip.sh 50 &

执行后会出现如下信息:

[[email protected]_Server iptables]# nohup ./deny_blackip.sh 50 & 
[1] 23630
[[email protected]_Server iptables]# nohup: ignoring input and appending output to `nohup.out'

表示如果脚本产生输出信息,将会写入到nohup.out文件,可以看到当前目录已经生成了一个空的nohup.out:

[[email protected]_Server iptables]# ll nohup.out
-rw------- 1 root root 0 Nov  5 21:15 nohup.out

好了,现在你执行执行ps aux 应该可以找到如下进程:

root     23630  0.0  0.2   5060  1224 pts/0    S    21:15   0:00 /bin/bash ./deny_blackip.sh
root     23964  0.0  0.0   4064   508 pts/0    S    21:19   0:00 sleep 10

一切顺利!每10s将检查一次服务器请求,如果某个IP超过50个并发,立即拉黑,并发一封邮件给你!

三、效果测试

测试很简单,先使用nohup启动脚本,然后在另一台Linux或Windows安装webbench,然后模拟50+并发去抓取该服务器的某个页面,20s之内可见到效果,下面是我的测试截图:

①、模拟CC攻击的服务器截图:
Linux系统防CC攻击自动拉黑IP增强版Shell脚本

②、被CC攻击的服务器截图:

Linux系统防CC攻击自动拉黑IP增强版Shell脚本

③、攻击IP被拉黑后的报警邮件:

Linux系统防CC攻击自动拉黑IP增强版Shell脚本

测试时,模拟55个并发攻击了20s,立马就被拉黑了,效果很明显!

四、附加说明

①、脚本发邮件需要安装sendmail,若未安装请执行yum -y install sendmail安装并启动即可;

②、若要停止后台运行的脚本,只要使用ps aux命令找到该脚本的pid线程号,然后执行kill -9 pid号即可结束;

③、关于脚本的单IP并发限制,我实际测试同时打开博客多个页面并持续刷新,顶多也就产生十来个并发,所以单IP超过50个并发就已经有很大的问题了!当然,文章的阈值设为50也只是建议值,你可以根据需求自行调整(如果网站静态文件未托管到CDN,那么一个页面可能存在10多个并发);

④、写这个脚本,主要是为了弥补用crontab执行时间间隔最低只能是1分钟的不足,可以让CC防护更严密,甚至每隔1S执行一次!虽说脚本不怎么占用资源,不过还是建议10s执行一次为佳,不用太过极端是吧?

⑤、对于白名单过滤,只要将白名单IP保存到脚本同一目录下的white_ip.txt文件中即可,若发现攻击IP在白名单中,脚本不会直接拉黑,而是发一封邮件给你,让你自己判断这个白名单攻击你是为毛?如果白名单需要支持IP段,请参考我前天写的脚本即可。

就啰嗦这么多,主要还是自己用,然后分享出来给有需要的人一些参考,个人vps服务器虽说很少有人攻击,但是基本的安装防护还是必须要做的!希望本文对你有所帮助!

53 条回应
  1. 勇耳陵2014-11-6 · 11:17

    技术大牛

    • Jager2014-11-6 · 14:09

      呵呵,谬赞了。

  2. 林薇薇2014-11-6 · 18:08

    虽然看不懂,但是好像很厉害,赞一个吧!

  3. yangge20502015-1-5 · 20:05

    请问我用的是Postfix,这个脚本需要修改吗?谢谢。

    • Jager2015-1-5 · 22:18

      邮件服务器?至少端口需要修改下吧~~实际使用最好读懂代码会比较靠谱~~

      • yangge20502015-1-6 · 17:08

        不是邮件服务器,是安装了Postfix发送注册验证和提醒用的,主要是希望用你编写的脚本自动ban ip,但又不确定Postfix是否能正常发送邮件提醒。

        • Jager2015-1-6 · 17:45

          建议你使用failban来完成这个需求,更专业一些。

          • yangge20502015-1-6 · 18:57

            failban 适用于多次猜密码,我是设置只能使用密钥连接SSH,而且没用FTP,用的是SFTP。

            我还是继续用APF+DDoS-Deflate吧。

            • Jager2015-1-7 · 20:07

              嗯,实际上这个脚本也可以完成你的需求,不过要修改代码,端口啥的。

  4. 爱福利2015-1-7 · 17:52

    不好意思,之前使用时忘了修改邮箱,给博主大大造成困扰,万分抱歉。另外感谢提供这么好用的脚本!!

    • Jager2015-1-7 · 20:08

      没事,你的网站攻击还挺频繁的。

  5. 测试2015-1-16 · 10:08

    现在博客用的什么方式防御cc 呢,能分享下配置吗
    我一会儿压力测试一下你网站哈 😆

    • Jager2015-1-16 · 12:18

      👿 你觉得你很牛逼么?你这是压力测试?测了一上午?只会藏头露尾么?

  6. 阿狸2015-1-24 · 17:46

    请问白名单里除了ip可以设置为域名吗?

    • Jager2015-1-24 · 22:53

      只能是ip,域名的话,可以将域名解析为多个IP,加入白名单。

      • 阿狸2015-1-25 · 20:14

        现在的情况是他们用的好像是adsl,我知道是他用的一个二级域名了,但是ip他会经常换。不固定的,还有其他好办法吗?

        • Jager2015-1-25 · 22:42

          那就在禁用之前,先使用ping或者nslookup来得到这个域名的解析IP,然后做白名单排除即可。

          • 阿狸2015-1-28 · 18:29

            我用上这个了哈,很好用,但是有点小问题,就是black_ip.txt文件里同一个ip会出现很多次,现在导致black_ip.txt文件好大,咋办呢?能不能每个ip不要重复啊。

            • Jager2015-1-28 · 19:25

              这个应该难不倒你吧?
              找到代码中这2行:

              echo "$black_ip (white_ip)" >>./black_ip.txt
              echo $black_ip >>./black_ip.txt

              修改为:

              grep $black_ip  ./black_ip.txt || echo "$black_ip" >>./black_ip.txt
              grep $black_ip  ./black_ip.txt || echo "$black_ip (white_ip)" >>./black_ip.txt
              • 阿狸2015-4-11 · 22:27

                遇到个新问题,就是咱们这个在black_ip.txt文件里可以写入一个ip段吗?比如58.215.111.*这样的,如果可以该怎么写呢?谢谢了哈。

                • Jager2015-4-12 · 12:40

                  脚本是自动拉黑一个IP,而非IP段,如果你要拉黑IP段的话,建议手工拉黑,在Linux下执行如下命令:

                  iptables -I INPUT -s 58.215.111.0/24 -j drop

                  这个表示禁用一个段,也就是111.1~111.254.

                  • 阿狸2015-4-12 · 14:59

                    我意思是能不能在black_ip.txt里添加这个ip段呢?如果可以该怎么写呢?因为在black_ip.txt里添加的话我看起来更直观,而且如果解封我直接删除了就行,比较方便一点。

                    • Jager2015-4-12 · 21:25

                      那要新增代码

                    • 阿狸2015-4-13 · 21:18

                      还有个小问题搞不明白,比如我有个a.html页面,里面包含了b.css c.css d.js e.js,当访问a.html的时候这个并发数是一个还是五个呢?或者说nohup ./deny_blackip.sh 50 &这里的50个连接数算不算b.css c.css d.js e.js?还是只是一个a.html算并发数呢?百度了半天没找到适合我的答案,谢谢了哈。

                    • Jager2015-4-14 · 15:28

                      当然算在里面,html里面的单个资源请求都会算在里面,具体验证方法也很简单新建一个测试WEB,就你一个人访问,打开html后,用脚本里面的那个netstat命令查看并发数就知道了,绝对是多个请求。
                      为什么默认是50,因为我的网站已经做了动静分离,用了七牛CDN,所以静态css js 图片都不在服务器上了。

  7. 莫离莫弃2015-2-11 · 11:48

    网站被攻击了,想用这脚本,有没有详细点的教程啊,希望发下

    • Jager2015-2-11 · 11:54

      我的每一篇文章都是最详细的教程,使用门槛为小白级别(本文需要掌握基本的linux操作知识)。请按照步骤操作,实在不会可以购买我的有偿服务-linux系统运维。

  8. 桶子2015-5-7 · 14:25

    博主您好,我在执行脚本的时候开始说没权限,我chmod之后执行提示没有该文件,什么个情况呢?

    [email protected]:~# nohup ./deny_blackip.sh 10 &
    [6] 11252
    [email protected]:~# nohup: ignoring input and appending output to `nohup.out’
    nohup: failed to run command `./deny_blackip.sh’: No such file or directory

    [6] Exit 127 nohup ./deny_blackip.sh 10

    • 桶子2015-5-7 · 14:32

      我给该脚本赋予权限之后文件名后面多了一个*号

      • Jager2015-5-7 · 15:44

        执行命令不在脚本同一个目录。
        你可以把 ./deny_blackip.sh 改成脚本文件的绝对路径,比如 /root/deny_blackip.sh

        • 桶子2015-5-7 · 16:14

          即使用绝对路径也不行,奇怪的就是我对文件赋予权限之后文件名后面多了个*号:
          如下:-rwxrwxrwx 1 root root 2150 May 7 14:10 deny_blackip.sh*
          不知道是怎么回事?
          脚本的话我就是注释掉了您的邮件提醒方法,然后我系统是ubutun。

          • 桶子2015-5-7 · 17:14

            找到原因了,文件类型是doc的,已经改成Unix,ok,感谢博主

  9. unmn2015-6-17 · 23:15

    在阿里云的SLB基础上面,实现不了。

  10. nichicon2015-7-11 · 23:02

    群主 能联系下吗 重金有偿请破解一个华为linux系统的庭网关 telnet可以开 shell命令无效

  11. nichicon2015-7-11 · 23:03

    我的企鹅 1163654748

  12. 清风2015-8-6 · 16:45

    你好博主看到你的文章感到受益颇多但是里面有几个问题需要请教!
    1、就是自动拉黑后的IP记录到哪里去了?是记录到.htaccess文件里吗?
    2、虚拟空间可以使用这个代码吗? 空间可以用SSH控制台。

    • Jager2015-8-6 · 19:06

      虚拟主机没权限操作防火墙的,用不到。

  13. haiwan2015-8-10 · 0:27

    博主,你好 使用来 脚本 虽然没有成功收到邮件。但我查看发件箱确实有攻击记录未发出。有联系方式吗 想跟你请教学习 linux下的CC 防护。

    • Jager2015-9-20 · 16:57

      已经写更好的防御工具,后面会发布,请等候。

  14. haiwan2015-8-10 · 1:47

    I’m sorry to have to inform you that your message could not
    be delivered to one or more recipients. It’s attached below.

    For further assistance, please send mail to postmaster.

    If you do so, please include this problem report. You can
    delete your own text from the attached returned message.

    The mail system
    你好 帮看看一下 这个如何解决噢

    • Jager2015-9-20 · 16:57

      邮件发送失败,sendmail问题吧

  15. 老陈2015-9-17 · 0:09

    ./deny_blackip.sh: line 20: ./iplist/black_ip.txt: 没有那个文件或目录
    ./deny_blackip.sh: line 31: ./iplist/denylog.txt: 没有那个文件或目录
    ./deny_blackip.sh: line 20: ./iplist/black_ip.txt: 没有那个文件或目录
    DROP all — 117.135.175.151 0.0.0.0/0
    您好nohup.out 记录是这样的会有影响么?

    • Jager2015-9-20 · 16:56

      已开发更好的工具,请等待博客发布。

      • Justin2015-12-17 · 21:37

        你好在吗,你新开发的工具在那呢?[color=red][/color]

        • Jager2015-12-17 · 22:45

          看文章第一句话,有个传送门。

  16. 紫外线2015-11-25 · 10:17

    Jager您好,我用了这个代码以后原来挺管用,现在不知道为什么安装完以后的black_ip.txt随时都是在变化的,比如刚在里面有个ip211.3.23.21,过会再打开就是另外一个ip了,原来的时候拉黑的ip都不会变化会一直在里面的,麻烦您看看我是不是哪里操作的不对?谢谢。

    • Jager2015-11-25 · 12:32

      这个脚本设计的时候就是每次清空blackip的,因为需要发邮件,如果每次都是累加,那么邮件信息就包含了以前的黑IP了,如果你要累加也很简单,文章中代码去掉第20行即可(>./black_ip.txt)。当然,我也开发了更强大的防御工具,CCKiller,你可以试试:https://zhang.ge//5066.html

  17. sd2016-12-8 · 21:46

    脚本如何加白名单呢

  18. 李盛奎博客2017-10-30 · 4:29

    看了你的很多文章,技术相当到位,学习了!

  19. CE安全网2018-3-31 · 2:24

    今天被c了一天 ? 来取取经

  20. 天河2019-1-11 · 22:57

    邮箱配置怎么做 直接输入自己邮箱就可以了吗 请求博主 简单的说一下如何配置邮箱 拉黑发信 谢谢博主

  21. 失控的疯子2019-3-3 · 19:15

    怎么样添加开机自动启啊,能不能给个代码?