ddos攻击怎么办?附解决方案

5月 21, 202469 mins read

前言   
 

开互联网公司的主要成本是服务器和带宽。产品形态主要是网站和app。搞网站一是软件产品本身的研发,而是防DDoS攻击。为何DDoS是网上主要的攻击手段?因为它成本低,不需要破解。  

 

网站受到DDoS的症状  

1.服务器CPU被大量占用  

如果服务器某段时期能突然出现CPU占用率过高,那么就可能是网站受到CC攻击影响。  

服务器无响应了:  

 

2.带宽被大量占用  

占用带宽资源通常是DDoS攻击的一个主要手段,毕竟对很多小型企业或者个人网站来说,带宽的资源可以说非常有限,网络的带宽被大量无效数据给占据时,正常流量数据请求很很难被服务器进行处理。如果服务器上行带宽占用率达到90%以上时,那么你的网站通常出现被DDoS攻击的可能。  

 

3服务器连接不到,网站也打不开  

如果网站服务器被大量DDoS攻击时,有可能会造成服务器蓝屏或者死机,这时就意味着服务器已经连接不上了,网站出现连接错误的情况。当然出现这种请求时我们最好是确认一下服务器是否是硬件故障等所导致出现的问题,否者在进行服务器连接时就要做好相关的防御首段。  

 

4.域名ping不出IP  

可能这种情况站长们可能会比较少考虑到,这其实也是DDoS攻击的一种表现,只是攻击着所针对的攻击目标是网站的DNS域名服务器。在出现这种攻击时,ping服务器的IP是正常联通的,但是网站就是不能正常打开,并且在ping域名时会出现无法正常ping通的情况。  

 

判断是否被攻击  

查看网络连接  

  •  

  •  

  •  

  •  

  •  

netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
输出:
ESTABLISHED 4
TIME_WAIT 3

netstat -na命令观察到有大量的SYN_RECEIVED、TIME_WAIT、FIN_WAIT_1等状态存在,而ESTABLISHED很少,则可判定肯定是遭受了资源耗尽攻击。  

 

如果ESTABLISHED非常地高,那么可能是有人在恶意攻击,进一步判断,可以把下面命令保存为脚本执行一下:  

  •  

  •  

  •  

  •  

  •  

  •  

for i in `netstat -an | grep -i ':80 '|grep 'EST' | awk '{print $5}' | cut -d : -f 1 | sort | uniq -c | awk '{if($1 > 50) {print $2}}'`

do
  echo $i
  echo $i >> /tmp/evilip
done

 

如果输出了多个结果,那么可能表示有人在企图进行DDOS攻击,想用TCP连接来拖死你的服务器,输出的ip就是发出请求的服务器地址,并且保存在了/tmp/evilip里面。如果没有结果,可以调整一下阈值,把50改成40试一试。  

 

如果SYN_RECV非常高,那么表示受到了SYN洪水攻击。  

 

如果上面的值看不出什么异常的话,我们来抓包分析下,可能并非基于TCP的攻击。抓包命令:  

  •  

tcpdump -w tmp.pcap port not 22

抓包感觉差不多了就ctrl+c结束,结果在保存在当前目录下的tmp.pcap文件中,我们可以使用命令  

  •  

tcpdump -r tmp.pcap -nnA

来查看,也可以拖回本地用wireshark打开分析等,个人喜好了。如果出现大量的ICMP包或者大量的UDP包,那么可能就是针对性的ICMP洪水以及UDP洪水了。  

 

TCP连接攻击  

TCP连接攻击算是比较古老的了,防御起来也相对比较简单,主要是利用大量的TCP连接来消耗系统的网络资源,通常同一个IP会建立数量比较大的TCP连接,并且一直保持。应对方法也比较简单,可以将以下命令保存为脚本,定时ban掉那些傀儡机ip  

  •  

  •  

  •  

  •  

  •  

  •  

for i in `netstat -an | grep -i ':80 '|grep 'EST' | awk '{print $5}' | cut -d : -f 1 | sort | uniq -c | awk '{if($1 > 50) {print $2}}'`
do
echo $i
echo $i >> /tmp/banip
/sbin/iptables -A INPUT -p tcp -j DROP -s $i
done

banip文件里面记录了所有被ban的ip地址信息,方面进行反渗透以及证据保存等等。为了更好地加固系统,我们可以使用iptables来限制一下,单个ip的最大连接数。  

  •  

iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT

限制每个ip的连接数为10。如果是大些业务系统的话,需要注意,上面的做法可能导致一些共用IP的用户访问中断。需要谨慎。  

 

SYN洪水攻击  

SYN洪水是利用TCP/IP协议的设计缺陷来进行攻击的,采用一些策略以及配置可以适当的降低攻击的影响,但并不能完全消除。  

  •  

  •  

  •  

sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.tcp_syn_retries = 0
sysctl -w net.ipv4.tcp_max_syn_backlog=2048

tcp_syncookies设置为1表示启用syncookie,可以大大降低SYN攻击的影响,但是会带来新的安全缺陷。   
 

 

tcp_syn_retries 表示syn重试次数,重传次数设置为0,只要收不到客户端的响应,立即丢弃该连接,默认设置为5次。  

 

tcp_max_syn_backlog表示syn等待队列,改小这个值,使得SYN等待队列变短,减少对系统以及网络资源的占用。  

 

当攻击者的资源非常的多,上面这些方法限制可能就没有什么防护效果了,面对大流量DDoS攻击还是要考虑采用多机负载或者选择墨者安全高防来应对了,一般来说多机负载的成本可能更高,所以大部分人还是选择高防硬防产品来防御。  

 

防御措施  

目前没有一招制敌的办法。只能多措并举,多管齐下。  

 

网站静态化  

备份网站,方便切换。有点靠谱。  

隐藏真实IP,采用CDN。源服务器前面有 CDN。如果攻击域名,CDN 可以挡住;如果直接攻击源服务器,可以考虑采用弹性 IP。  

加大带宽,说了白说,小公司哪买得起那么大的带宽?  

安装专业抗DDoS防火墙。装不起。  

尽量避免NAT的使用。不明白。  

买阿里或华为的DDoS高防服务。太贵,买不起。  

当然,针对Linux服务器,还是能做一些基本防护的。  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

TCP/IP内核参数优化
net.ipv4.tcp_max_syn_backlog = 4096   #表示SYN队列的长度,加大队列长度可以容纳更多等待连接的网络连接数
net.ipv4.tcp_syncookies = 1       #表示开启SYN Cookies功能。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭,1表示打开;
net.ipv4.tcp_synack_retries = 2     #下面这两行表示定义SYN重试次数
net.ipv4.tcp_syn_retries = 2   
 
#提高TCP连接能力
net.ipv4.tcp_rmem = 32768
net.ipv4.tcp_wmem = 32768
net.ipv4.tcp_sack = 0   #打开tcp_sack功能,1表示"关闭",0表示"打开"

然后运行 sysctl -p 使上面配置生效  

 

iptables 防火墙预防  

先查看服务器上连接web端口(比如80端口)的哪个ip是最多的,如果发现可疑ip,就果断将其断开与服务器连接  

 

查看80端口的连接情况  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# netstat -an | grep “:80” | grep ESTABLISHED


下面的命令表示获取服务器上ESTABLISHED连接数最多的前10个ip,排除了内部ip段192.168|127.0开头的。
[root@test3-237 ~]# /bin/netstat -na|grep ESTABLISHED|awk ‘{print $5}’|awk -F: ‘{print $1}’|sort|uniq -c|sort -rn|head -10|grep -v -E ‘192.168|127.0’
4001 140.205.140.205
2388 124.65.197.154
1807 111.205.224.15
18 10.51.58.16

将上面140.205.140.205、124.65.197.154、111.205.224.15的这三个ip的包丢弃  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# iptables -A INPUT -s 140.205.140.205 -p tcp -j DROP
[root@test3-237 ~]# iptables -A INPUT -s 124.65.197.154 -p tcp -j DROP
[root@test3-237 ~]# iptables -A INPUT -s 111.205.224.15 -p tcp -j DROP
[root@test3-237 ~]# service iptables save
[root@test3-237 ~]# service iptables restart

不过上面的方法对于伪造源IP地址的SYN FLOOD攻击就无效了!  

  •  

  •  

  •  

  •  

防止同步包洪水(Sync Flood)
防止同步包洪水(Sync Flood),可以缩短SYN-Timeout时间:
[root@test3-237 ~]# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
[root@test3-237 ~]# iptables -A INPUT -i eth0 -m limit --limit 1/sec --limit-burst 5 -j ACCEPT

其中:  

–limit 1/s 限制syn并发数每秒1次,可以根据自己的需要修改防止各种端口扫描  

  •  

[root@test3-237 ~]# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ping洪水攻击(Ping of Death)  

  •  

[root@ ~]# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

控制单个IP的最大并发连接数  

如下设置表示:允许单个IP的最大连接数为 30  

  •  

[root@test3-237 ~]# iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT

控制单个IP在一定的时间(比如60秒)内允许新建立的连接数。  

如下设置表示:单个IP在60秒内只允许最多新建30个连接  

  •  

  •  

[root@test3-237 ~]# iptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --update --seconds 60 --hitcount 30 -j REJECT
[root@test3-237 ~]# iptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --set -j ACCEPT

如果出现报错:  

  •  

iptables: Invalid argument. Run `dmesg’ for more information.

解决办法:  

 

增加 xt_recent模块的参数值即可,默认是20  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# cat /sys/module/xt_recent/parameters/ip_pkt_list_tot
20
[root@test3-237 ~]# echo 50 > /sys/module/xt_recent/parameters/ip_pkt_list_tot
[root@test3-237 ~]# cat /sys/module/xt_recent/parameters/ip_pkt_list_tot
50

禁止外部ping  

  •  

[root@test3-237 ~]# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

用iptables屏蔽IP(如下禁止213.8.166.237连接本机的80端口)  

  •  

[root@test3-237 ~]# iptables -A INPUT -s 213.8.166.227 -p tcp -m tcp -m state --state NEW --dport 80 --syn -j REJECT

允许某ip连接(如下允许13.78.66.27连接本机的80端口)  

  •  

[root@test3-237 ~]# iptables -A INPUT -s 13.78.66.27 -p tcp -m tcp -m state --state NEW --dport 80 --syn -j ACCEPT

DDoS deflate是一款免费的用来防御和减轻DDoS攻击的脚本。它通过netstat监测跟踪创建大量网络连接的IP地址,在检测到某个结点超过预设的限制时,该程序会通过APF或IPTABLES禁止或阻挡这些IP.  

DDoS deflate其实是一个Shell脚本,使用netstat和iptables工具,对那些链接数过多的IP进行封锁,能有效防止通用的恶意扫描器,但它并不是真正有效的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中,但堵塞了预定时间后会从它之中删除。  

如何确认是否受到DDOS攻击?  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
   1 Address
   1 servers)
   2 103.10.86.5
   4 117.36.231.253
   4 19.62.46.24
   6 29.140.22.18
   8 220.181.161.131  
   2911 167.215.42.88

每个IP几个、十几个或几十个连接数都还算比较正常,如果像上面成百上千肯定就不正常了。比如上面的167.215.42.88,这个ip的连接有2911个!这个看起来就很像是被攻击了!  

 

下面就说下通过DDoS deflate脚本来自动屏蔽DDOS攻击的ip  

  •  

  •  

  •  

  •  

1)下载DDoS deflate安装脚本,并执行安装。
[root@test3-237 ~]# wget http://www.inetbase.com/scripts/ddos/install.sh
[root@test3-237 ~]# chmod 0700 install.sh
[root@test3-237 ~]# ./install.sh

卸载DDos default的操作如下:  

  •  

  •  

  •  

  •  

  •  

--------------------------------------------------------------------------
# wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
# chmod 0700 uninstall.ddos
# ./uninstall.ddos
--------------------------------------------------------------------------

2)配置DDoS deflate下面是DDoS deflate的默认配置位于/usr/local/ddos/ddos.conf ,内容如下:  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# cat /usr/local/ddos/ddos.conf
##### Paths of the script and other files
PROGDIR="/usr/local/ddos"
PROG="/usr/local/ddos/ddos.sh"
IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"     //IP地址白名单
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
FREQ=1            //检查时间间隔,默认1分钟。设置检测时间间隔,默认是分钟,由于系统使用crontab功能,最小单位是分钟
 
##### How many connections define a bad IP? Indicate that below.
NO_OF_CONNECTIONS=150       //最大连接数,超过这个数IP就会被屏蔽,一般默认即可。默认是150,这是一个经验值,如果服务器性能比较高,可以设置200以上,以避免误杀
 
##### APF_BAN=1 (Make sure your APF version is atleast 0.96)
##### APF_BAN=0 (Uses iptables for banning ips instead of APF)
APF_BAN=0           //使用APF还是iptables屏蔽IP。推荐使用iptables,将APF_BAN的值改为0即可。设置为1表示使用APF,如果使用APF则需要先安装,centos中默认就没有安装
 
##### KILL=0 (Bad IPs are'nt banned, good for interactive execution of script)
##### KILL=1 (Recommended setting)
KILL=1            //是否屏蔽IP,默认即可
 
##### An email is sent to the following address when an IP is banned.
##### Blank would suppress sending of mails
EMAIL_TO="root"       //当IP被屏蔽时给指定邮箱发送邮件,推荐使用,换成自己的邮箱即可。如果不希望发送邮件,设置为空,即EMAIL_TO=""
 
##### Number of seconds the banned ip should remain in blacklist.
BAN_PERIOD=600       //禁用IP时间(锁定ip的时间),默认600秒,可根据情况调整

需要注意的是  

DDos default安装完成后在/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文件,内容如下:  

  •  

  •  

  •  

[root@test3-237 ~]# cat /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变量产生的,如果修改了此值,可以通过运行如下命令更新(实际也是在安装是运行了如下命令):  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# /usr/local/ddos/ddos.sh -c
Stopping crond:                      [ OK ]
Starting crond:                      [ OK ]
Stopping crond:                      [ OK ]
Starting crond:                      [ OK ]

或者  

  •  

  •  

  •  

  •  

  •  

[root@test3-237 ~]# /usr/local/ddos/ddos.sh --cron
Stopping crond:                      [ OK ]
Starting crond:                      [ OK ]
Stopping crond:                      [ OK ]
Starting crond:                      [ OK ]

3)DDos default选项  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

# /usr/local/ddos/ddos.sh -h    #查看选项
# /usr/local/ddos/ddos.sh -k n   #杀掉连接数大于n的连接。n默认为配置文件的NO_OF_CONNECTIONS
 比如:
 [root@test3-237 ~]# /usr/local/ddos/ddos.sh -k 150
   2 103.110.186.75
   1 servers)
   1 Address
# /usr/local/ddos/ddos.sh -c    #按照配置文件创建一个执行计划。使得ddos.conf文件配置后生效

一个实用的防御脚本  

Linux服务器中一旦受到DDOS的攻击(比如IDC机房服务器被攻击了,关机,拔网线,降流量),目前只能通过封IP来源来暂时解决。然而IP来源变化多端,光靠手工来添加简直是恶梦,所以还是想办法写个shell脚本来定时处理,这才是比较靠谱的办法。  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

#!/bin/bash
/bin/netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -rn|head -10|grep -v -E '192.168|127.0'|awk '{if ($2!=null && $1>4) {print $2}}'>/tmp/dropip
for i in $(cat /tmp/dropip)
do
  /sbin/iptables -A INPUT -s $i -j DROP
  echo “$i kill at `date`”>>/var/log/ddos
done

以上脚本中最重要的是第二行,即:  

获取ESTABLISHED连接数最多的前10个ip并写入临时文件/tmp/dropip,排除了内部ip段192.168|127.0开头的.通过for循环将dropip里面的ip通过iptables全部drop掉,然后写到日志文件/var/log/ddos。  

 

下面是针对连接数屏蔽IP:  

  •  

  •  

  •  

  •  

  •  

  •  

#!/bin/sh 
/bin/netstat -ant |grep 80 |awk '{print $5}' |awk -F":" '{print $1}' |sort |uniq -c |sort -rn |grep -v -E '192.168|127.0' |awk '{if ($2!=null && $1>50)}' > /root/drop_ip.txt 
for i in `cat /root/drop_ip.txt` 
do 
 /sbin/iptables -I INPUT -s $i -j DROP; 
done 

安装nginx版安全狗  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

[root@icool ~]# wget http://safedog.cn/safedogwz_linux_Nginx64.tar.gz
[root@icool ~]# tar -zvxf safedogwz_linux_Nginx64.tar.gz
[root@icool ~]# cd safedogwz_linux_Nginx64
[root@icool safedogwz_linux_Nginx64]# chmod 755 install.py
[root@icool]# ls
install_files install.py uninstall.py
[root@icool]# ./install.py -A     //卸载安全狗就用uninstall.py
.......
 step 3.5, start service...                                   [ok]
 step 3.6, save safedog install info...                             [ok]
  Tips:
 (1)Run the command to setup Server Defense Module: sdui
 (2)Explore more features by tapping the command to join Cloud Management Center (fuyun.safedog.cn) with your account: sdcloud -h
 
If you need any help about installation,please tap the command: ./install.py -h
Install Completely!

温馨提示:  

1)安装完成后,记得一定要重新启动Nginx服务,网站安全狗软件即可生效。  

2)运行时,安装脚本默认将自动获取Nginx服务的安装路径;若自动获取失败则将提示输入Nginx服务的安装路径(绝对路径),需要根据所安装的Nginx的目录,填写真实的安装路径。  

3)当出现提示:Are you sure to uninstall?[y/n]时,输入y  

Image NewsLetter
Icon primary
Newsletter

私たちのニュースレターを購読する

ボタンをクリックすることで、私たちの利用規約に同意したことになります