• 如何在 Linux 上模拟和缓解 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}\nTotal time:%{time_total}s\n' -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}\nTotal time:%{time_total}s\n' -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
    08:55:49        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
    08:55:50      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    08:55:50         eth0  22274.00    629.00   1174.64     37.78      0.00      0.00      0.00      0.02
    08:55:50           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
    09:15:48.287047 IP 172.31.82.28.27095 > 172.31.88.139: Flags [S], seq 1288268370, win 512, length 0
    09:15:48.287050 IP 172.31.82.28.27131 > 172.31.88.139: Flags [S], seq 2084255254, win 512, length 0
    09:15:48.287052 IP 172.31.82.28.27116 > 172.31.88.139: Flags [S], seq 677393791, win 512, length 0
    09:15:48.287055 IP 172.31.82.28.27141 > 172.31.88.139: Flags [S], seq 1276451587, win 512, length 0
    09:15:48.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}\nTotal time:%{time_total}s\n'-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 带来的问题,因此只能缓解其造成的影响。

    原文链接:https://blog.devgenius.io/linux-how-to-simulate-and-mitigate-ddos-attacks-62a3cb2f5978

  • 相关阅读:
    Tensorflow2.0语法
    Neural Networks and Deep Learning--Introduction to Deep Leraning
    机器学习---吴恩达---Week11(机器学习应用举例分析)
    机器学习---吴恩达---Week10(机器学习概述与单变量线性回归方程分析)
    机器学习---吴恩达---Week9_2(推荐系统)
    机器学习---吴恩达---Week9_1(异常检测)
    机器学习---吴恩达---Week8_2(非监督学习_PCA)
    机器学习---吴恩达---Week8(非监督学习_集群算法)
    机器学习---吴恩达---Week7(支持向量机学习SVM)
    机器学习---吴恩达---Week6_2(机器学习系统设计)
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/16142354.html
Copyright © 2020-2023  润新知