本文将探讨在基于WASM的牧云插件系统开发中探针开发语言的选择。我们将对比不同语言在性能、安全性、易用性等方面的优缺点,并解释我们为什么以及最终选择了哪种语言作为探针开发语言。
这是系列文章“主机Agent插件引擎开发故事”的第四篇,后续将会持续更新。该系列文章将带领您深入探究长亭牧云团队主机Agent插件引擎的开发历程,内容涵盖技术选型、插件接口设计、组件通信框架等多个方面,并详细讲解背后的原理和实现方式,无论您是网络安全专业人员还是对技术开发感兴趣的读者,都可以从中得到收获。我们希望通过分享在开发过程中面临的挑战、解决方案以及实践经验,提供深入见解和有价值的技术参考,帮助读者了解如何构建高效可靠的安全产品,共同推动安全技术社区的发展。
在主机安全系统的架构中,Agent
程序非常重要。其不但是实施基本功能的重要模块,而且是一个主机安全系统中具体安全能力的承载者。其运行不但要覆盖入侵检测、资产清点、应用监控、漏洞检测、帮助优化性能和快速排查问题等,还必须达到高度的稳定性、可靠性和安全性。因此,认真选择探针使用哪种语言开发是一个非常非常重要的问题。
根据主机安全系统的实际需求,对探针开发语言的选择至少要满足以下基本原则:
使用 C++
编写 Agent
程序是在主机安全领域中非常常见的一种做法。使用 C
编写相对不那么常见,但非常适合满足特定场景的特殊需求。针对主机安全场景分析如下:
C++
必然就要谈到性能,几乎可以说是蓝星上除了汇编以外最快的东西了,能生成最精简的机器码,提供理论上几乎最高的性能,因此从这个角度来看非常适合编写主机 Agent
。C++
,熟悉网络安全的人一定知道,这是内存安全问题的重灾区,几乎不能更重了。从这个角度来看,又非常不适合编写主机 Agent
使用。QT
),那么跨平台是非常完美的。可惜我们没有能直接用的框架。C++
工程中极为棘手的一个问题。C
或者 C++
。但是其他方面就不好说了。使用 Java
编写 Agent
程序在主机安全领域也是一种常见的做法,针对主机安全场景分析如下:
C++
相提并论,但也非常不错。但其存在内存占用较大的问题,是我们不太喜欢的。Java
是一个内存安全的带垃圾回收的语言,少用一些花哨的东西加上良好设计的话,安全性也不需要过于担心。JVM
帮我们提供了平台兼容性,但 JVM
如果不支持,那就是真的不支持。通常这不是个问题,但有问题的时候解决问题的难度比较大。C++
要统一些。使用 Python
编写 Agent
程序相对不那么常见,但同样存在。针对主机安全场景分析如下:
C++
或者 Rust
编写底层模块,另外新版本越来越快了。同时还有一些号称比官方 CPython
更快的版本。Python 2
。使用 Ruby
编写 Agent
并不是一种常见的做法,但有知名厂商珠玉在前,我们针对主机安全场景来分析一下:
Python
类似。Ruby
写的(比如 Metasploit
),所以在安全社区是有些影响力的。使用 Go
编写 Agent
是一种我们的做法,针对主机安全场景分析如下:
C++
的情况下是很好的选择。唯一的问题是 GC
提供的控制性比较弱,相关的问题不太好解决。CGO
和许多生态都能接轨(虽然 CGO
真的很难用)。go mod
了,所以还行。使用 Rust
编写 Agent
是一种新兴的做法,针对主机安全场景分析如下:
C++
同级别的性能,有时候更好。独特的内存管理方式使得内存占用可控。GC
的情况下作为一个编译型无虚拟机语言保证了内存安全,非常强。C
和 C++
。Rust
重写的东西终究会被 Rust
重写。常见的都有了,即将啥都有。天然能和 C
世界接轨,而且没有 CGO
的缺陷(比如不可避免的内存拷贝)。其他还有主要使用 Perl
、Bash
等实现的等等,都显然不太能用,理由不多说了。
比较各种常见的选择,可以发现,如果同时想要速度快、内存占用小、没有太多安全担忧、社区支持强、能适应各种复杂场景,基本上主要就是从 Go
和 Rust
里面选。Go
成熟相对更早一些,所以早期牧云的探针语言选型就是 Go
。
随着数年的深度使用,以及 Go
越来越向云原生方向走,对社区有强烈呼声的增强内存控制能力、提供好用的动态加载机制等的持续忽视,以及积极抛弃旧操作系统支持的政策,对主机安全系统的拓展性和兼容性都带来了许多困难。在之前的文章中提到过,为了满足牧云自身的兼容性需求、性能要求和可拓展需求,我们做了许多努力,提出了不少技术创新方案。截至目前,因为修修补补,我们的 Go
版本停止在了 Go 1.17.2-patch
。后缀的这个 patch
代表我们做的各种定制。
等到最近的版本终于加上了堆内存限制、手动管理内存等特性,诞生了WAZERO这样的纯 Go
写的 WASM
引擎解决拓展性问题的时候,我们已经积重难返了。
解决积重难返最好的办法是什么,当然是推倒重写(开玩笑的)。
但是如果要再次升级 Go
版本就意味着所有兼容性适配和微调都要重做,而且即使升级到最新版本也并不能解决所有问题(比如低版本系统兼容适配等)。这个时候我们看到 Rust
语言逐渐兴起,是一个非常好的选择。在 Rust
之前,我们唯一的选择就是 C++
;但是现在有了 Rust
,我们就不必为了获得足够的灵活性承受 C++
的维护之痛了。
Rust官网首页有一句话是这么说的:Hundreds of companies around the world are using Rust in production today for fast, low-resource, cross-platform solutions.
不得不承认,“fast, low-resource, cross-platform solutions”的说法真的抓住了我们这群做主机安全产品的开发者的心。
上一篇:【牧云插件系统选型斗争】
系列文章目录:【预告】主机Agent插件引擎开发故事汇总