如何缓解DDoS(分布式拒绝服务)导致的性能下降

描述

在我的上一篇文章谈到了如何使用 tcpdump 和 wireshark,并带您了解了几个用例。今天我们来看看另一个常见的问题,如何缓解 DDoS(分布式拒绝服务)导致的性能下降。

什么是 DDoS?

DDoS 的前身是 DoS(Denial of Service),即拒绝服务攻击,是指利用大量合理请求占用过多目标资源,使目标服务无法响应正常的请求.

DDoS(Distributed Denial of Service)采用基于 DoS 的分布式架构,利用多台主机同时攻击目标主机。这样,即使目标服务部署了网络防御设备,仍然无法应对大量的网络请求。

从攻击原理来看,DDoS 可分为以下几种。

  • 用尽带宽:无论是服务器还是路由器、交换机等网络设备,带宽都有一个固定的上限。当带宽耗尽时,会出现网络拥塞,无法传输其他正常的网络数据包。
  • 耗尽系统资源:网络服务的正常运行需要一定的系统资源,如CPU、内存等物理资源,以及连接表等软件资源。一旦资源耗尽,系统将无法处理其他正常的网络连接。
  • 耗尽应用资源:应用程序的运行通常还需要与其他资源或系统进行交互。如果应用程序一直忙于处理无效请求,也会导致正常请求的处理速度变慢,甚至没有响应。

无论哪种类型的 DDoS,危害都是巨大的。那么,如何发现系统遭受了 DDoS 攻击,如何应对这种攻击呢?让我带您了解一个现实生活中的用例。

案例准备

您需要遵循:

  • 3 台 Linux 主机:应用程序、攻击者、客户端

  • 预安装 dockersarhping3tcpdumpcurl

应用服务器

让我们在应用主机上启动一个简单的 nginx 服务:

[root@app ~]# docker run -itd --name=nginx --network=host nginx
a8b3685d5eef0ffa2dead081b88d50d777db04bedbdb77ba886ca89b4bb690d2
[root@app ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
a8b3685d5eef   nginx     "/docker-entrypoint.…"   24 seconds ago   Up 21 seconds             nginx

客户端

然后,在客户端主机中,使用 curl 访问 Nginx 正在监听的端口,并确认 Nginx 已经正常启动:

[root@client ~]# curl -s -w 'Http code: %{http_code}
Total time:%{time_total}s
' -o /dev/null http://172.31.88.139
Http code: 200
Total time:0.002437s

从这里可以看出,正常情况下,我们访问 Nginx 只需要 2ms(0.002s)。

攻击者

现在,让我们从攻击者主机那里运行 hping3 命令来模拟 Dos 攻击:

# -S means set syn,-p means port 80
# -i u10 send a packet frame every 10 m-seconds
$ hping3 -S -p 80 -i u10 --flood 192.168.0.30
HPING 172.31.88.139 (eth0 172.31.88.139): S set, 40 headers + 0 data bytes
hping in flood mode, no replies will be shown

缓解攻击

现在让我们回到客户端主机,再次尝试 curl 命令:

[root@client ~]# curl -s -w 'Http code: %{http_code}
Total time:%{time_total}s
' -o /dev/null http://172.31.88.139
Http code: 000
Total time:10.001s
curl: (28) Connection timed out after 10000 milliseconds

这次普通客户端的连接超时,其并没有收到 Nginx 服务的响应。

这里发生了什么事呢?让我们回到主机应用程序,并检查当前的网络状态:

[root@app ~]# sar -n DEV 1
0849        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
0850      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
0850         eth0  22274.00    629.00   1174.64     37.78      0.00      0.00      0.00      0.02
0850           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

从这次 sar 的输出可以看出,网络接收到的 PPS 已经达到 2 万多,但是 BPS 只有 1174kB。因此,可以计算每个包的大小只有 54B()。

包大小不算大,但这是个什么样的包呢?让我们使用 tcpdump 来捕获:

[root@app ~]# tcpdump -i eth0 -n tcp port 80
0948.287047 IP 172.31.82.28.27095 > 172.31.88.139: Flags [S], seq 1288268370, win 512, length 0
0948.287050 IP 172.31.82.28.27131 > 172.31.88.139: Flags [S], seq 2084255254, win 512, length 0
0948.287052 IP 172.31.82.28.27116 > 172.31.88.139: Flags [S], seq 677393791, win 512, length 0
0948.287055 IP 172.31.82.28.27141 > 172.31.88.139: Flags [S], seq 1276451587, win 512, length 0
0948.287068 IP 172.31.82.28.27154 > 172.31.88.139: Flags [S], seq 1851495339, win 512, length 0
...

在该输出中,Flags [S] 表示这是一个 SYN 数据包。而大量的 SYN 数据包表明这是一次 SYN Flood 攻击。如果我们用 wireshark 来观察,可以更加直观地看到 SYN Flood 的过程:

拒绝服务

事实上,SYN Flood 是互联网上最经典的 DDoS 攻击。从上图也可以看出它的原理:

  • 客户端构造大量 SYN 包,请求建立 TCP 连接;
  • 服务器收到包后,会向源 IP 发送一个 SYN+ACK 包,并等待三次握手的最后一个 ACK 包,直到链接超时。

这种等待状态的 TCP 连接通常也称为半开连接(Half-Open Connection)。由于连接表(Connection Table)的大小是有限的,而大量的半开连接会导致连接表快速填满,从而无法建立新的 TCP 连接。

从下面的 TCP 状态图可以看到,此时服务器端的 TCP 连接会处于 SYN_RECEIVED 状态:

拒绝服务

我们可以使用 netstat 来查看所有连接的状态,但需要注意的是 SYN_REVEIVED 的状态通常缩写为 SYN_RECV

[root@app ~]# netstat -n -p | grep SYN_REC
tcp        0      0 172.31.88.139:80          172.31.82.28:12503      SYN_RECV    -
tcp        0      0 172.31.88.139:80          172.31.82.28:13502      SYN_RECV    -
tcp        0      0 172.31.88.139:80          172.31.82.28:15256      SYN_RECV    -
tcp        0      0 172.31.88.139:80          172.31.82.28:18117      SYN_RECV    -
...

从结果中可以发现,存在大量的 SYN_RECV 状态的连接,源 IP 地址为 172.31.82.28。现在,让我们统计一下正处于 SYN_RECV 状态的连接数:

[root@app ~]# netstat -n -p | grep SYN_REC | wc -l
193

找出源 IP 后,只需丢弃相关数据包即可解决 SYN 攻击的问题。此时,iptables 可以帮你完成这个任务:(注意:Serban 在评论中建议“在这种情况下,DROP 比可能 REJECT 更好”)

[root@app ~]# iptables -I INPUT -s 172.31.82.28 -p tcp -j REJECT

执行上述命令后,让我们再次从客户端主机尝试 curl

$ curl -w 'Http code: %{http_code}
Total time:%{time_total}s
'-o /dev/null--connect-timeout 10 http://172.31.88.139
Http code: 200
Total time:1.572171s

但一般来说,SYN Flood 攻击中的源 IP 是不固定的(例如,您可以通过将 --rand-source 选项添加到 hping3 命令来随机化源 IP)。此时,刚才的方法并不适用。

幸运的是,我们还有许多其他方法可以达到类似的目的。例如,我们可以通过两种方式限制同步数据包的速率:

# Limit the number of syn concurrency to 1 per second
$ iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT
#Limit the number of newly established connections for a single IP in 60 seconds to 10
$ iptables -I INPUT -p tcp --dport 80 --syn -m recent --name SYN_FLOOD --update --seconds 60 --hitcount 10 -j REJECT

到目前为止,我们已经初步限制了 SYN Flood 攻击。但这还不够,因为我们的案例只是单一的攻击源。

如果多台机器同时发送 SYN Flood,则该方法可能直接失效。因为您可能无法通过 SSH 连接到机器(SSH 也是基于 TCP 的),更不用说执行上面的那些排查命令了。

TCP 优化

为了缓解多台机器的 SYN Flood 攻击,我们可以将半开连接容量从默认的 256 增加到 1024:

$ sysctl net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_max_syn_backlog = 256
$ sysctl -w net.ipv4.tcp_max_syn_backlog=1024net.ipv4.tcp_max_syn_backlog = 1024

另外,每当连接状态为 SYN_RECV 的连接时,如果连接失败,内核会自动重试,默认重试次数为 5 次。您可以通过执行以下命令将其减少到 1 次:

$ sysctl -w net.ipv4.tcp_synack_retries=1
net.ipv4.tcp_synack_retries = 1

此外,TCP SYN Cookies 也是一种特殊的防御 SYN Flood 攻击的机制。SYN Cookies 根据连接信息(包括源地址、源端口、目的地址、目的端口等)和加密种子(如系统启动时间)计算哈希值(SHA1)。该哈希值称为 cookie。启用 SYN Cookies 后,无需再保持半开连接状态,同时半开连接的数量也将没有限制。

$ sysctl -w net.ipv4.tcp_syncookies=1
net.ipv4.tcp_syncookies = 1

需要注意的是,上面 sysctl 命令所修改的配置是临时的,重启后将会丢失。您可以通过将它们添加到 /etc/sysctl.conf 文件中使其持久化。例如:

$ cat /etc/sysctl.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_max_syn_backlog = 1024
$ sysctl -p

结论

今天,我们谈到了在分布式拒绝服务 (DDoS) 情况下的缓解措施。DDoS 利用大量伪造请求,使目标服务消耗大量资源来处理这些无效的请求,进而无法正常响应正常用户请求。

由于 DDoS 分布的流量大和难以追踪等特点,目前没有办法完全防御 DDoS 带来的问题,因此只能缓解其造成的影响。

 

 

 

原文标题:如何在 Linux 上模拟和缓解 DDoS 攻击

文章出处:【微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分