作者注:这是长期的 Linux 内核网络开发人员和 Cilium 项目的创建者 Thomas Graf 的帖子 Linux 内核社区最近宣布了 bpfilter,它将用高性能网络过滤器取代长期存在的 iptables 内核实现Linux BPF,同时保证 Linux 用户的无中断过渡。从作为 tcpdump 和 Wireshark 等流行工具底层的包过滤功能的卑微根源,BPF 已经发展成为一个丰富的框架,以高度灵活的方式扩展 Linux 的功能,而不会牺牲性能和安全等关键属性。这种强大的组合已经导致像 Google、Facebook 和 Netflix 这样的 Linux 内核技术的前瞻用户选择 BPF 用于从网络安全和负载平衡到性能监控和故障排除的用例。 Netflix 的 Brendan Gregg 首先将 BPF Superpowers 称为 Linux。这篇文章将介绍这些“超能力”如何使像 iptablesredundant 这样的长期存在的内核子系统同时启用新的内核用例,这是以前很少有人想象的。在过去的 15 年里,我在 Linux 内核社区中编写了许多子系统的代码,包括 TCP/IP 堆栈、iptables 等等,这让 meto 能够近距离观察 BPF 的发展。我很快意识到 BPF 不仅仅是另一个特性,而是代表了一种基础技术转变,随着时间的推移,它将改变 Linux 中网络和安全性的几乎所有方面。我开始做出贡献,并与 Alexei Starovoitov 和 Daniel Borkmann 一起成为其最大的支持者之一,他们现在正在维护 BPFupstream。从这个角度来看,从 iptables 到 bpfilter 的转变只是 BPF 为现代领域振兴 Linux 网络堆栈之旅的下一个合乎逻辑的步骤。要了解这种转变为何如此令人兴奋,请允许我带您了解内核中 iptables 的历史。多年来,iptables 一直是在 Linux 上实现防火墙和数据包过滤器的主要工具。 iptables 及其前身 ipchains 从一开始就是我个人 Linux 之旅的一部分。最初作为用户,后来作为内核开发者。多年来,iptables 既是福也是祸:是因为它的灵活性和快速修复。在多个系统组件正在争夺谁可以安装什么 iptables 规则的环境中调试 5K 规则 iptables 设置时的诅咒。 OH:“在任何团队中,您都需要坦克、治疗师、伤害输出者、具有人群控制能力的人以及另一个了解 iptables 的人”——Jérôme Petazzoni (@jpetazzo) 2015 年 6 月 27 日
当 20 年前 iptables 开始出现以取代其前身 ipchains 时,防火墙功能的编写范围很简单:当时,网络速度很慢。还记得拨号时调制解调器发出的声音吗?那是 iptables 最初开发和设计的时代。实现 iptables 实现的访问控制列表 (ACL) 的标准做法是使用规则的顺序列表,即每个接收或传输的数据包都与规则列表一个接一个地匹配。然而,线性处理有一个明显的巨大缺点,过滤数据包的成本会随着规则数量的增加而线性增加。一段时间过去了,网络速度提高了,iptables 设置从几十条规则增加到了数千条规则。从性能和延迟的角度来看,遍历顺序的 iptables 列表变得难以忍受。社区很快确定了最常见的瓶颈:拒绝或允许单个 IP 地址和端口组合的一长串规则列表。这导致了 ipset 的引入。 ipset 允许将匹配 IP 地址和/或端口组合的规则列表压缩到哈希表中,以减少 iptables 规则的整体数量。从那以后,这一直作为一种解决方法,而没有解决核心问题本身。不幸的是,ipset 并不能解决所有问题。一个突出的例子是 kube-proxy,它是 Kubernetes 的一个组件,它使用 iptables 和 -j DNAT 规则为服务提供负载平衡。它为服务所服务的每个后端安装多个 iptables 规则。 Foreach 服务添加到 Kubernetes,要遍历的 iptables 规则列表呈指数增长。最近的 KubeContalk 检查了 kube-proxy 性能的所有细节。演讲展示了随着服务数量的增长,不可预测的延迟和性能下降的测量结果。它还揭示了 iptables 的另一个主要弱点:缺乏增量更新。每次添加新规则时,都必须替换整个规则列表。这导致安装代表 20K Kubernetes 服务的 160K iptablesrules 的总持续时间为 5 小时。
使用基于 IP/端口的机制通常有许多其他明显的缺点,特别是在应用程序容器时代。容器经常被部署和拆除。这可能会导致单个 IP 地址的生命周期较短。一个 IP 地址可能会被一个容器使用几秒钟,然后在几秒钟后被另一个容器重新使用。这给依赖使用 IP 地址进行安全过滤目的的系统带来压力,因为集群中的所有节点必须不断了解容器映射的最新 IP。虽然这在集群内几乎不困难,但跨集群变得非常具有挑战性。深入了解细节超出了这篇博文的范围,因此我们将其保存以供以后的博文使用。近年来,BPF 以疯狂的速度发展,解锁了以前不在内核范围内的东西。这是通过 BPF 提供的令人难以置信的强大和高效的可编程性实现的。以前需要自定义内核开发和内核重新编译的任务现在可以在 BPFsandbox 的安全边界内使用高效的 BPF 程序来完成。以下是一个项目列表,展示了 BPF 如何被各种项目和公司利用: Cilium 正在将 BPF 的力量释放到容器世界,并在 L3-L7 提供强大而高效的网络、安全性和负载平衡。阅读 Cilium 简介以开始了解 Cilium。 @ciliumproject 对 eBPF 和 XPD 所做的事情是我见过的最干净的网络插件,疯狂的道具 https://t.co/oOShMvT2iY pic.twitter.com/mPV864Aia1 — jessie frazelle (@jessfraz) 2017 年 8 月 16 日 Facebook 有介绍了基于 BPF/XDP 的负载平衡的令人兴奋的工作,以取代还包括 DDoS 缓解逻辑的 IPVS。虽然与 iptables 相比 IPVS 是一个诱人的下一步,但 Facebook 在看到性能大约提高了 10 倍之后,已经从 IPVS 迁移到 BPF。
eBPF 性能让你大开眼界!我使用 XDP 编写的一个简单的入口防火墙处理 1100 万个数据包/秒。是时候进行更多优化了! — Diptanu Choudhury (@diptanu) 2017 年 8 月 21 日 Netflix,尤其是 Brendan Gregg,一直在利用 BPF 的功能进行性能分析和跟踪。 bcc 项目让用户可以使用 BPF 的强大功能,例如,生成惊人的火焰图:有关更多详细信息,包括有关如何利用 BPF 进行应用程序跟踪的许多示例,请查看 Brendan Gregg 的博客文章。正如我对许多在系统工程领域求职的人所说的那样:BPF 体验越来越热 https://t.co/bScbqE6m17 — Brendan Gregg (@brendangregg) 2017 年 5 月 20 日 Google 一直在研究 bpfd使用 eBPF 为远程目标启用强大的 Linux 跟踪。基于围绕 BPF 的上游参与,他们似乎也在考虑将各种内部项目迁移到 BPF。
Cloudflare 正在使用 BPF 来缓解 DDoS 攻击,并发布了多篇博文,并就该主题进行了多次公开演讲。 Suricata 是一个 IDS,它开始使用 BPF 和 XDP 来替换 nfqueue,后者是一个基于 iptables 的有线窃听基础设施。更多细节可以在这个内核食谱中找到。有太多的例子不胜枚举一一列举在这篇博客文章。我们aremaintaining的BPF参考指南中的项目usingBPF更完整的列表。 BPF 的最新发展是一个令人兴奋的提议,以对用户完全透明的方式用 BPF 完全替换 iptables 的内核部分,即现有的 iptables 客户端二进制文件和库将继续工作。您可以在内核邮件列表上找到上游讨论。该提案的作者是 Daniel Borkmann(Covalent)、网络维护者 David Miller(Red Hat)和 Alexei Starovoitov(Facebook)。该提案被 LWN 的一篇文章所涵盖,该文章对最初的讨论进行了很好的总结。 Quentin Monnet 在 FRnOG 30 上展示的下图显示了 bpfilter 与 iptables 和 nftables 相比的一些早期测量结果。它显示了纯软件 BPF 实现以及硬件卸载测试:这些早期的性能数字令人难以置信,并且表明了 BPF 的强大功能。需要注意的是,bpfilter和BPF本身并不能解决iptables使用顺序列表带来的性能问题。这样做将需要本地使用 BPF,如 Cilium 项目所做的那样。
一些 Linux 内核邮件列表以其火焰战争而闻名。 Haveflamewars在这种情况下爆发了?不,事实上,核心 iptables 维护者已经立即提出了所有针对 BPF 方向的建议。 Florian Westphal 提出了一个框架,该框架将在 bpfilter 之上运行,并将 nftables 转换为 BPF。这允许保留特定领域的 nftables 语言,但受益于 BPF 运行时的所有优势,包括其 JIT 编译器、硬件卸载和工具。 Pablo Neira Ayuso 似乎一直在研究类似的提案,并且已经发表了一系列将 nftables 转换为 BPF 的系列。方法上的主要区别似乎是 Pablo 打算在内核中执行翻译。此后,社区一致同意,任何 BPF 程序的注入都必须通过用户空间发生,并通过 BPFverifier 传递,以保证 BPF 的安全行为。我认为 BPF 是多年来最令人兴奋的 Linux 开发。我们几乎没有触及其潜力的表面,它仍在不断发展。用 BPF 替换 iptables 的内核部分是合乎逻辑的第一步。真正的过渡将是 BPF 原生工具,以及摆脱传统的 IP 地址/端口中心结构。