长亭百川云 - 文章详情

牧云插件系统技术选型之插件开发用什么?

huraway

34

2023-04-28

本文将探讨在基于WASM的牧云插件系统开发中插件开发语言的选择。我们将对比不同语言在性能、安全性、易用性等方面的优缺点,并解释我们为什么以及最终选择了哪种语言作为插件开发语言。

这是系列文章“主机Agent插件引擎开发故事”的第五篇,后续将会持续更新。该系列文章将带领您深入探究长亭牧云团队主机Agent插件引擎的开发历程,内容涵盖技术选型、插件接口设计、组件通信框架等多个方面,并详细讲解背后的原理和实现方式,无论您是网络安全专业人员还是对技术开发感兴趣的读者,都可以从中得到收获。我们希望通过分享在开发过程中面临的挑战、解决方案以及实践经验,提供深入见解和有价值的技术参考,帮助读者了解如何构建高效可靠的安全产品,共同推动安全技术社区的发展。

牧云插件系统背景

牧云插件系统是一个基于 WebAssembly 的高性能、跨平台、强隔离的主机安全系统。在设计和开发过程中,选择合适的插件开发语言对于确保插件的性能、安全性和易用性至关重要。选对编程语言能有效提高开发效率,降低维护成本,同时实现对多种语言的支持以适应未来发展。因此,在开发牧云插件系统时,我们需要深入探讨和权衡各种编程语言的优缺点,以找到最适合我们需求的解决方案。

总结一下,主机安全插件需要做到高性能、跨平台、强隔离、强类型、多语言、战未来。而这些正是 WebAssembly 的优点。

WebAssembly

WebAssembly 顾名思义是一种 Web 的汇编语言,是一种可移植的编译格式。WebAssembly 的设计旨在提供更小的文件尺寸、更快的加载速度,在提供接近原生的执行的速度的同时提供高度的隔离性和安全性,旨在成为高级语言的编译目标。目前 WebAssembly 已经广泛应用于云函数、Serverless、客户端跨平台、容器技术等多种领域。我们则正在将其带到网络安全领域中。

类似于多种语言都可以编译为 JVM 的字节码,目前 CC++RustGoJavaC# 等许多语言都可以编译到 WebAssembly 字节码。

WebAssembly 数据类型

WebAssembly 本身只支持四个数据类型 s32, s64, u32, u64(即 32 位整数,64 位整数,32 位浮点和 64 位浮点)在模块(Guest)和主机(Host)之间通信。传统解决办法主要是手动传递指针并通过反射等手段指定指针指向的主机内存的使用方式,以此实现对复杂类型的支持。

(甚至字符串也算得上是复杂类型,只能通过这种方式间接使用。可见 WebAssembly 是一个多么 Low-Level 的计算模型。)

WebAssembly 插件引擎怎么办

现在有两个困难的选择题摆在我们面前:

第一个是,有这么多语言可以选,选哪个。

第二个是,通信如此不便捷,用哪种方式通信。

插件开发语言的选择

关于第一个问题,Awesome WebAssembly Languages给出了一个选择的方向。正如所有其他 Awesome 类的 Repo 一样,其中包含了一个比较完备的可以编译到 WebAssembly 或者在WebAssembly 上有自己的 VM 的语言列表。

其中列出的达到 Stable 级别的语言包括以下这些(去掉虽然稳定但是不实用的,比如 Brainfuck):

除了上面提到的 Stable 语言列表,值得考虑的语言还包括:

作为一个主机安全系统的插件引擎,我们不想要的东西包括:

  • 较大的 Overhead,包括虚拟机嵌套等
    • 例如 C#/F#/QuickJS/Lua/Python
  • 较高的迁移成本
  • 不熟悉或难上手的语言
    • 例如 C#/F#/Zig/Rust
  • 不成熟的 WASI 支持(不可接受
    • 例如 C#/F#
  • 缺乏现代特性(例如模块化,包管理,模式匹配等)
    • 例如 C/C++/Lua
  • 缺乏良好异步支持
    • 例如 C/Lua/Python
  • 弱类型或动态类型或渐进式类型(不可接受
    • 例如 AssemblyScript/QuickJS/Lua/Python
  • 很大的可执行文件体积(数百 MB)
    • 例如 C#/F#/Python
  • 很大的内存消耗(数百MB)
    • 例如 C#/F#/Python
  • 较慢的启动时间(数秒)
    • 例如 C#/F#/Python

所以我们值得考虑的选择还剩下:

  • C/C++
  • Go/TinyGo
  • Rust
  • Zig

关于 C/C++,在这种使用场景下没有得到其主要的好处却不得不承受其固有的缺点,所以排除。

关于 Go/TinyGo,是我们熟悉的语言,语法简单,具备一定的模块化和包管理特性,具备良好异步支持,没有虚拟机,是编写插件比较好的选择。考虑到 TinyGo 的编译产物文件大小具有显著优势,而缺失的特性可以主要由 binding 提供,倾向于使用 TinyGo 而非 Google 官方的 Go。(虽然 Google 也开始逐渐提供 WASI 的支持,但还处于一个非常早期的阶段)

关于 Rust,是探针组熟悉的语言,编译产物文件小,高性能,无 GC,适合作为相对变化不频繁的部分的实现,例如公共库和探针功能辅助插件。由于学习/编写/调试/阅读相对效率较低,插件的主要部分不适合使用 Rust 编写。考虑到 Rust 写些简单的逻辑也很爽,某几个辅助功能插件用 Rust 来写也无不可。

关于 Zig,考虑到尚未到达 1.0 版本,不适合生产环境使用。

由于 WASM 的模型限制,异步特性略微受到限制,可能产生额外开销。例如在 TinyGo 文档中关于并行有以下描述:

Support for other platforms (such as WebAssembly) is a bit more limited: calling a blocking function may for example allocate heap memory.

虽然这些语言都可以称得上对 WebAssembly 支持的好,但实际的选择还需要考虑许多其他因素,例如 runtime 的支持,WASI 的支持程度,binding 的编写便捷性,以及我们的第二个问题。

解决通信问题的现有方案

关于第二个问题,现有的方案有四种可选,即手动使用 runtime 提供的 API 维护、使用waPC进行跨模块的过程调用、使用Extism封装好的插件调用逻辑、使用wit-bindgen提供的对 WIT 格式的支持。其中第一种手动维护的支持是最稳定的,第二种和第三种是基于第一种提供的不同表现形式的封装,第四种 WIT 是 WASI 的 preview2 的一部分,即将成为正式标准。

WITWasm Interface Type,是字节码联盟继第一阶段实验后确定的第二阶段接口标准格式,为 WebAssembly 组件模型的导入导出提供了统一的高阶数据类型表示标准。如果不出意外的话,第二阶段确定的内容在第三阶段也不会更改(按照官方的说法,第三阶段只是为了提供一个最后解决问题的机会),而是修复一些问题以后直接成为最终的正式标准。

有一部分厂商已经开始在自己的商业化产品中使用 WIT 支持,例如著名的无服务器厂商 Fermyon 的产品Spin

除了常见的整型、浮点、字符串之外,WIT 还提供了包括 tupleoptionresultinterfacerecordvariantenumunionflags 等高级类型,着实吸引人。与 wit-bindgenRust 一起食用十分舒适。

虽然前面三种有更长的发展时间(因此可能更稳定),但我们打算跟随未来标准,参与到标准的生态共建中来。

最终选择及原因

在对比了多种编程语言在性能、安全性、易用性等方面的优缺点之后,我们最终选择了 TinyGo 作为主推的插件开发语言,同时辅以 Rust

TinyGo 在编译产物文件大小、性能表现和易用性方面具有明显优势,适合用于插件的主要部分。而 Rust 则在高性能和安全性方面表现出色,适合作为相对变化不频繁的部分的实现,例如公共库和探针功能辅助插件。

除此之外,我们对 zignim 也很感兴趣,会持续关注其是否能够达到生产要求。

通过为牧云插件系统选择合适的开发语言,我们可以更好地满足主机安全系统的需求,提高插件的性能和安全性,同时降低开发和维护成本。在未来,我们将持续关注 WASM 生态的发展,优化和改进插件系统,以满足不断变化的安全需求。

相关博文推荐

上一篇: 【牧云插件系统技术选型之探针开发用什么?】

系列文章目录:【预告】主机Agent插件引擎开发故事汇总

  1. 【揭秘牧云插件开发者的创新之路:从无法解决的问题到“妙趣横生”】
  2. 【牧云插件系统面向未来的设计原则】
  3. 【牧云插件系统选型斗争】
  4. 【牧云插件系统技术选型之探针开发用什么?】
  5. 【牧云插件系统技术选型之插件开发用什么?】
  6. 【牧云插件系统技术选型之插件通信框架大PK】
  7. 【牧云插件系统技术选型之自己人都会吐槽的序列化方法选择之争】
  8. 【牧云插件系统技术选型之WASM运行时选哪个?不选这个竟然出大问题!】
相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2