一组通过 Linux 6.18 网络请求合并的补丁将帮助服务器更好地应对分布式拒绝服务“DDoS”攻击。多亏了一位谷歌工程师,Linux 6.18 内核代码中找到了一些显著的优化,这些优化可以在压力下更有效地处理 UDP 接收性能,例如在 DDoS 场景中。
合并到 Linux 6.18 的网络安全变更中,是谷歌工程师 Eric Dumazet 的这一系列补丁。Dumazet 在那里解释道:
“本系列文章是经过对 UDP 协议栈的仔细分析后得出的结果,旨在优化接收端,尤其是在一个或多个 UDP 套接字接收 DDoS 攻击时。
我在使用 IPv6 UDP 数据包,负载为 120 字节的情况下,测量到在 DDoS 攻击下的吞吐量提高了 47%。
16 个 CPU 正在接收针对单个套接字的流量。
即使在添加了 NUMA 感知的丢弃计数器之后,我们仍然遭受了数据包生产者和消费者之间的假共享问题。
1) 前四个补丁缩小了 struct ipv6_pinfo 的大小,并重新组织字段以获得更高效的 TX 路径。它们还应该通过消除一个缓存行缺失来惠及 TCP。
2) 第 5 和第 6 个补丁更改了 sk->sk_rmem_alloc 的读取和更新方式。它们减少了在 busylock 上的自旋锁竞争。
3) 补丁 7 和 8 改变了 sk_backlog(包括 sk_rmem_alloc)、sk_receive_queue 和 sk_drop_counters 的顺序,以获得更好的数据局部性。
4) 补丁 9 移除了哈希数组自旋锁,转而使用每个 UDP 套接字的自旋锁。
5) 最后一个补丁采用了 skb_attempt_defer_free(),在 TCP 使用它后取得了良好的效果。”
在 DDoS 攻击场景中,吞吐量提高了 47%!

Eric Dumazet 还在这个补丁中进一步补充,仅此一个补丁就能在遭受攻击的英特尔 Xeon Linux 服务器上每秒处理 1420 万个更多数据包:
“busylock 保护 UDP 套接字免受数据包洪泛攻击,但不幸的是,它没有保护主机本身。
在压力下,许多 CPU 在获取忙锁时可能会空转,而网络接口卡(NIC)不得不丢弃数据包。或者,如果启用了 RPS/RFS,数据包可能会在 CPU 队列中丢弃。
这个补丁用中间无锁队列替换了忙锁。(每个 NUMA 节点一个队列)。
这意味着需要获取 UDP 接收队列锁的 CPU 数量更少。
大多数 CPU 可以:
– 立即丢弃数据包。
– 或者将其排队在它们的 NUMA 感知无锁队列中。然后选择一个 CPU 来批量处理这个无锁队列。
这个批量只包含在同一 NUMA 节点上处理的数据包,因此对延迟的影响非常有限。
测试:
针对受害者 UDP 套接字的 DDoS 攻击,在具有 6 个 NUMA 节点(Intel(R) Xeon(R) 6985P-C)的平台上进行
之前:
nstat -n ; sleep 1 ; nstat | grep Udp
Udp6InDatagrams 1004179 0.0
Udp6InErrors 3117 0.0
Udp6RcvbufErrors 3117 0.0之后:
nstat -n ; sleep 1 ; nstat | grep Udp
Udp6InDatagrams 1116633 0.0
Udp6InErrors 14197275 0.0
Udp6RcvbufErrors 14197275 0.0我们可以看到,在遭受攻击时,这个主机现在每秒可以处理更多 14.2 M 的数据包,而受害套接字可以接收更多 11%的数据包。”
这项工作在 Linux 6.18 中落地的时间非常合适,因为这个内核版本预计将成为今年的长期支持(LTS)内核版本,因此未来将会有很多企业/服务器使用。
转自 Linux 6.18 Will Be A Big Improvement For Servers Encountering DDoS Attacks – Phoronix
Linuxeden开源社区