译文 | 让基于 Linux 的 eBPF 程序与 eBPF for Windows 一起运行
2022-2-26 09:0:0 Author: mp.weixin.qq.com(查看原文) 阅读量:28 收藏

开卷有益 · 不求甚解


前言

在我们之前的博客中,我们谈到了我们为eBPF for Windows 项目取得的进展。我们的一个关键目标是与开发人员会面。因此,使为 Linux 编写的 eBPF 程序能够在 eBPF for Windows 平台上运行对我们来说非常重要。在本次更新中,我们想谈谈使用基本上为 Linux 编写的应用程序的学习和观察。

有什么比一个非常相关的现实世界用例更好的方法来证明这一点。在 Cilium 开发人员的帮助下,我们一直在努力让Cilium 第 4 层负载均衡器(L4LB) eBPF 程序在 Windows 的 eBPF 上运行。

在此之前,我们专注于为各种地图类型、助手和钩子构建基本的基础设施。

识别跨平台功能

Cilium 负载均衡器的功能非常丰富,我们为这项工作确定了提供 L4 负载均衡的功能子集。

感谢 Cilium 项目的开发人员,L4LB 代码是开源的。我们首先深入研究了应用程序的结构、用户模式应用程序和加载到内核中的 eBPF 程序之间的功能划分、使用了哪些 eBPF 钩子和帮助程序以及用于什么目的。

用户模式应用程序

自然地,该应用程序是在 Linux 上开发的,我们很快发现用户模式应用程序使用特定于 Linux 的诸如 netlink 之类的库。因此,我们决定编写一个受 Cilium 代理启发的用户模式应用程序,该应用程序将 Windows SDK 用于一些网络 API,并使用适用于 Windows 平台的 eBPF 来驱动 eBPF 程序。

该应用程序创建与 Cilium 代理相同类型的映射,并加载实现负载平衡功能的 eBPF 程序。

Hooks and helpers

接下来,我们列出了 L4LB 功能使用的钩子和助手。我们发现,在高层次上,Cilium 有一个独立的负载均衡器,它使用 eXpress 数据路径 (XDP) 和套接字/流量控制子系统 (TC) 挂钩。对于 L4LB,XDP 钩子特别有趣,因为它允许尽早直接在网络驱动程序的接收路径内执行 BPF 程序,以便处理大量入站数据包。Socket/TC 钩子用于后端的可选健康探测。出于演示的目的,我们决定专注于数据路径并开始为此构建钩子、助手和映射。

我们已经实现了一个基于Windows 过滤平台 (WFP)的 XDP 挂钩,用于处理第 2 层流量,并针对这项工作进行了增强。

下表显示了为此目的我们需要添加的钩子和助手,其中带有星号 (*) 的条目被发现是可选的或我们解决的问题。例如,bpf_fib_lookup() 是一个帮助器,我们知道它会提供基于下一跳的信息来发送数据包。对于演示,我们使用来自 Windows SDK 的现有 API 来获取第 2 层数据并将其填充到地图中以供 eBPF 程序使用。

类别Linux API
通用助手bpf_map_lookup/update/delete_elem

bpf_tail_call

bpf_get_prandom_u32

bpf_get_smp_processor_id

bpf_csum_diff

bpf_fib_lookup*

bpf_ktime_get_ns
XDP 助手bpf_xdp_adjust_meta*

bpf_xdp_adjust_tail*
XDP 动作XDP_TX(发夹)

Map

我们增强了对以下列表中其他类型地图的支持:

类别Linux API
Map typesbpf_map_type_hash

bpf_map_type_percpu_array

bpf_map_type_percpu_hash

bpf_map_type_prog_array

bpf_map_type_hash_of_maps

bpf_map_type_lru_hash

bpf_map_type_lpm_trie

bpf_map_type_perf_event_array*

验证器功能增强

正如我们取得进展一样,我们开始在 Cilium L4LB 代码上运行 PREVAIL 验证程序时遇到验证失败。深入挖掘,我们注意到 Cilium L4LB 程序嵌入了 Linux 特定的程序集,而不是从 C 编译,并且该程序集显然是由于需要 Linux 内核验证器工件的变通方法。该程序集未能通过 PREVAIL 验证程序验证,但原始 C 代码很好,因此我们回到使用 C 而不是程序集来处理此类代码路径。

然后,我们发现了两种常见情况,其中 PREVAIL 验证程序需要附加功能来处理此类实际程序。我们为 PREVAIL 创建了补丁并将它们贡献给上游。

让这一切一起工作

最后,我们将所有部分放在一起运行负载均衡器的直接服务器返回 (DSR) 和源 NAT (SNAT) 功能。

在注释掉我们认为是可选的功能(就演示而言)并处理上述汇编指令案例后,我们能够获得大约 96% 的为 Linux 编写的 eBPF 代码,以便在 eBPF 之上运行适用于 Windows 平台。这包括为 Maglev 散列、NAT 引擎、连接跟踪器、数据包处理代码等编写的 eBPF 代码。我们认为这是非常令人鼓舞和令人兴奋的,因为它展示了 eBPF 的跨平台价值。

软件架构

图 1:演示代码的软件架构

图 1 说明了演示负载均衡器的软件架构。该代码由受 Cilium L4LB 代理启发的用户模式代理组成。这会读取几个输入属性,例如接口详细信息并接受所需的服务详细信息。对于负载均衡器部分,我们最终同时支持 DSR 和 SNAT,并且代理接受它作为服务模式。除此之外,代理还接收虚拟 IP (VIP) 和后端直接 IP (DIP) 地址。代理计算后端的 Maglev 哈希,然后设置 BPF 程序所需的许多映射,例如 Maglev 映射、后端映射、服务映射等。代理调用 eBPF API,通过这些 API 验证 BPF L4LB 程序,然后在 XDP 挂钩处加载。

图 2:用户模式代理 CLI

演示拓扑包含五个虚拟机 (VM) — 一个负载平衡器 VM 和四个后端 DIP VM,以及一个代表客户端的浏览器会话。为了简单起见,我们将这些虚拟机托管在同一台服务器上,尽管这无关紧要。VM 使用服务器上的内部 VMSwitch 互连。图 3 显示了设置的拓扑结构和在 DSR 模式下采用的数据包路径。

演示拓扑 DSR

图 3:使用 DSR 模式的拓扑图

客户端向VIP地址40.1.1.1发起源地址为20.1.1.100的web请求。在 SNAT 模式下,负载均衡器在入站和出站方向都转换 IP 标头。使用连接跟踪器映射跟踪连接状态。

图 4:DSR 模式截图

在 DSR 模式下,负载均衡器将传入请求封装在外部 IP 标头中,并将其发送到选定的后端 VM。因此,后端 VM 必须解封装外部 IP 标头并将其提供给 Web 服务器。我们选择了两个后端虚拟机来运行 Windows 和两个虚拟机来运行 Linux。对于 Windows 后端,我们使用 XDP 程序来处理解封装,而 Linux VM 使用基于 TC 的程序。

上面描述的所有演示代码都是开源的,可以在 GitHub 上找到,任何人都可以根据需要使用或扩展。

接下来是什么?

我们将打开的工作项列表保存在我们的公共 GitHub 存储库中。我们将继续以应用程序为中心,专注于钩子和助手,以提高网络可观察性。最大化 eBPF 源代码兼容性将继续是我们的一个重要目标,因为我们构建了平台以帮助在 Windows 的 eBPF 之上部署更多应用程序。除此之外,我们正在与社区积极讨论如何接受已签署的 eBPF 程序。

对于我们所有的工作,我们邀请社区的合作者为这项工作做出贡献,无论是代码、设计还是错误报告。

如何合作

我们欢迎所有的贡献和建议,并期待与 eBPF 开发者社区的其他成员在这个激动人心的旅程中继续合作。您可以通过我们的 Slack 频道,通过我们的 GitHub 讨论与我们联系,或者 在太平洋时间周一上午 8:30参加我们的 每周公开 Zoom 会议。

译文申明

  • 文章来源为近期阅读文章,质量尚可的,大部分较新,但也可能有老文章。
  • 开卷有益,不求甚解,不需面面俱到,能学到一个小技巧就赚了。
  • 译文仅供参考,具体内容表达以及含义, 以原文为准 (译文来自自动翻译)
  • 如英文不错的,尽量阅读原文。(点击原文跳转)
  • 每日早读基本自动化发布(不定期删除),这是一项测试

最新动态: Follow Me

微信/微博:red4blue

公众号/知乎:blueteams



文章来源: http://mp.weixin.qq.com/s?__biz=MzU0MDcyMTMxOQ==&mid=2247485765&idx=3&sn=e16794507c08523e447bdd1e6eed1eed&chksm=fb35a08dcc42299b7101b639f2922d6b6052c11b4fc7b1e0186c098bbcd9df4ce0f496c0de4c#rd
如有侵权请联系:admin#unsafe.sh