云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

阿里云_云解析视频_返现

小七 141 0

Cloudflare架构和BPF如何吞噬世界

最近,在布拉格举行的Linux网络会议netdev0x13上,我做了一个题为"Linux at Cloudflare"的简短演讲。谈话最后主要是关于BPF。看来,不管这个问题-BPF是回答。这里是一份稍有调整的版本说话。在Cloudflare我们在服务器上运行Linux。我们运营两类数据中心:大型"核心"数据中心、处理日志、分析攻击、计算分析和"边缘"服务器群,从180个地点提供客户内容世界。在本次讲座,我们将重点介绍"边缘"服务器。在这里,我们使用了最新的Linux特性,优化了性能,并对DoS非常关心恢复力。我们的边缘服务是特殊的,因为我们的网络配置-我们广泛使用选播路由。Anycast意味着我们所有的数据都会公布相同的IP地址集中心。这个设计有很大的优势。首先,它保证了最终用户的最佳速度。无论您位于何处,您都会到达最近的数据中心。然后,anycast帮助我们分散DoS流量。在攻击过程中,每个位置都接收到总流量的一小部分,这样就更容易吸收和过滤掉不需要的信息交通。选播允许我们保持所有边缘数据中心的网络设置统一。我们在数据中心内部采用了相同的设计——我们的软件堆栈在边缘服务器上是统一的。所有软件都运行在服务器。在原则上,每台机器都能处理每一项任务——我们运行着许多不同的、要求很高的任务。我们有一个完整的HTTP栈,神奇的Cloudflare Workers,两套DNS服务器-权威和解析程序,以及许多其他面向公众的应用程序,如Spectrum和翘曲。甚至尽管每台服务器都运行着所有的软件,但是请求通常会在它们通过堆栈的过程中跨越许多机器。例如,在处理。让我将为您介绍入站数据包处理的早期阶段:(1)首先,数据包到达我们的路由器。路由器执行ECMP,并将数据包转发到我们的Linux服务器上。我们使用ECMP将每个目标IP分布在至少16台机器上。在服务器上,我们使用xdpebpf接收数据包。在XDP中,我们执行两个阶段。首先,我们运行容量DoS缓解,丢弃属于非常大的第3层攻击的数据包。(3)然后,仍然在XDP中,我们执行第4层负载平衡。所有非攻击数据包都被重定向到机器上。这被用来解决ECMP问题,为我们提供细粒度的负载平衡,并允许我们优雅地停止服务器服务。(4)在重定向之后,数据包到达指定的机器。在这一点上,它们被正常的Linux网络栈接收,通过通常的iptables防火墙,并被调度到一个适当的网络套接字上。(5)最后,数据包被应用程序接收。例如,HTTP连接由"协议"服务器处理,负责执行TLS加密和处理HTTP、HTTP/2和QUIC协议。它在请求处理的早期阶段,我们使用了最酷的Linux新特性。我们可以把有用的现代功能分为三个c类别:DoS搬运荷载balancingSocket dispatchLet让我们更详细地讨论DoS处理。如前所述,ECMP路由之后的第一步是Linux的XDP堆栈,其中我们运行DoS缓解措施。历史上我们对容量攻击的缓解是用经典的BPF和iptables风格的语法表示的。最近,我们对它们进行了调整,以在xdpebpf上下文中执行,结果发现这非常困难。继续阅读我们的D入口:L4Drop:XDP DDoS缓解SXDPCAP:XDP数据包捕获基于XDP的DoS缓解讲座Arthur FabreXDP在实践中:将XDP集成到我们的DDoS缓解管道(PDF)期间,我们遇到了许多eBPF/XDP限制。其中之一就是缺乏并发原语。很难实现无种族标记桶之类的东西。后来我们发现Facebook工程师Julia Kartseva也有同样的问题。今年2月,随着bpf_spin_锁的引入,这个问题得到了解决帮手。什么时候我们的现代体积DoS防御是在XDP层完成的,我们仍然依赖iptables来缓解应用层7。在这里,更高级别的防火墙功能很有用:connlimit、hashlimits和ipsets。我们还使用xt_bpf iptables模块在iptables中运行cBPF以匹配包的有效负载。我们在过去:经验教训在XDP和iptables之后引入BPF工具,我们有最后一个内核端DoS防御层。考虑一下当我们的UDP缓解失败时的情况。在这种情况下,我们可能会留下大量的数据包撞击我们的应用程序UDP套接字。这可能会使套接字溢出,导致数据包丢失。这是有问题的-好的和坏的包都会被不加区别地丢弃。对于DNS这样的应用程序来说,这是灾难性的。过去为了减少危害,我们为每个IP地址运行一个UDP套接字。一个未缓和的洪水是糟糕的,但至少它没有影响到其他服务器IP的流量地址。现在那个建筑已经不适合了。我们正在运行超过30000个DNS IP,并且运行的UDP套接字数量不是最佳的。我们的现代解决方案是运行一个带有复杂eBPF套接字过滤器的UDP套接字-使用SO\u ATTACH_BPF套接字选项。我们在过去的博客中讨论过在网络套接字上运行eBPF岗位:eBPF,socket,Hop Distance和手工编写eBPF assembly sockmap-TCP拼接的未来提到的eBPF速率限制了数据包。它将状态-包计数-保存在eBPF映射中。我们可以确定一个单一的被淹IP不会影响其他流量。虽然在这个项目的工作过程中,我们在eBPF中发现了一个相当令人担忧的bug,但是这个方法很有效验证人:eBPF can不算?!我想在UDP套接字上运行eBPF对分开。分开在DoS中,在XDP中,我们还运行第4层负载平衡器层。这是一个新项目,我们还没谈太多。在某些情况下,我们需要从XDP问题相对简单——我们的代码需要查找从包中提取的5元组的"socket"内核结构。这通常很简单-有一个bpf_sk_lookup helper可用于此。不出所料,出现了一些并发症。一个问题是当启用SYN cookies时,无法验证接收到的ACK包是否是三方握手的有效部分。我的同事lorenzbauer正在努力增加对这个角落的支持案例。之后在DoS和负载平衡层中,包被传递到通常的Linux TCP/UDP堆栈上。这里我们做一个套接字分派-例如,发送到端口53的数据包被传递到属于我们的DNS的套接字上服务器。我们尽我们所能使用普通的Linux特性,但是当您在服务器。令人信服Linux使用"AnyIP"技巧来正确路由数据包相对容易。确保数据包被发送到正确的应用程序是另一回事。不幸的是,我们的socket调度逻辑不够灵活。对于像TCP/80这样的流行端口,我们希望在多个应用程序之间共享端口,每个应用程序在不同的IP范围内处理它。不支持现成的Linux。您可以在特定的IP地址或所有IP地址(使用0.0.0.0)调用bind(),为了解决这个问题,我们开发了一个自定义内核补丁,它添加了一个SO\u BINDTOPREFIX套接字选项。顾名思义,它允许我们对选定的IP前缀调用bind()。这解决了多个应用程序共享53或80等常用端口的问题,然后我们遇到了另一个问题。对于我们的频谱产品,我们需要监听所有65535个端口。运行这么多的侦听套接字不是一个好主意(参见我们以前的战争故事博客),所以我们不得不另辟蹊径。经过一些实验之后,我们学会了使用一个晦涩难懂的iptables模块TPROXY。读一读这里:滥用Linux的防火墙:允许我们建立spectrum的黑客攻击这个设置是有效的,但我们不喜欢额外的防火墙规则。我们正在努力正确地解决这个问题——实际上是扩展了套接字调度逻辑。你猜对了-我们想利用eBPF扩展套接字调度逻辑。期待一些补丁我们。然后呢有一种方法可以使用eBPF来改进应用程序。最近,我们对使用SOCKMAP:SOCKMAP-未来技术的TCP拼接技术在改善软件堆栈的许多部分的尾部延迟方面有很大的潜力。目前的SOCKMAP实现还没有完全准备好进入黄金时期,但是潜在的可能性是巨大的。类似的,新的TCP-BPF又名BPF_SOCK_OPS钩子为检查TCP流的性能参数提供了一种很好的方法。这个功能对我们的性能非常有用团队。一些Linux的特性并不是很成熟,我们需要解决它们。例如,我们正在触及网络指标的局限性。别误会我的意思——网络指标很不错,但遗憾的是,它们不够细化。像TcpExtListenDrops和tcpextlistenverflows这样的东西被报告为全局计数器,而我们需要在每个应用程序上知道它基础。我们的解决方案是使用eBPF探测器直接从内核中提取数字。我的同事Ivan Babrou编写了一个名为"ebpf_exporter"的Prometheus metrics导出器来实现这一点。阅读:介绍ebpf_博览会rterhtps://github.com/cloudflare/ebpf_exporterWith"ebpf出口商"我们可以生成各种详细的指标。它非常强大,拯救了我们很多人场合。在本次演讲我们讨论了运行在我们边缘的6层bpf服务器:体积DoS缓解正在xdpebpfiptables xt_bpf cBPF for application layer attacksSO_ATTACH_bpf for rate limits on UDP socketsLoad balancer上运行,在运行应用程序帮助程序(如SOCKMAP for TCP)的XDPeBPFs上运行套接字拼接和TCP-BPF用于TCP测量"ebpf_exporter"用于gr