在安全工作中,扫描器几乎是绕不开的工具。
从最初的 PoC 验证脚本,到后期需要长期维护、持续扩展的扫描工具,我逐渐意识到:语言选择本身,就是一次工程决策

这篇文章不讨论 Rust 的具体语法,也不做语言对比的“站队”,而是从一个安全工程师的实际需求出发,说明我为什么在第一个工程化扫描器上选择了 Rust 红队开发 这条相对“难走”的路。


一、为什么不用 Python

Python 是我最早、也是目前仍然使用最多的安全开发语言之一。

在实际工作中,Python 非常适合以下场景:

  • 快速编写扫描脚本
  • PoC 验证与漏洞复现
  • 临时自动化工具
  • 把重复劳动脚本化

如果目标只是“解决一个问题”,Python 几乎是最优解。

但当我开始尝试把扫描器做成一个长期存在的工程时,问题逐渐显现出来。

1.1 工程规模扩大后的维护成本

随着扫描逻辑增多,模块逐渐拆分,我明显感受到:

  • 动态类型在规模扩大后,代码可读性和可维护性迅速下降
  • 扫描状态、结果结构需要反复通过注释和约定来维持一致性
  • 一旦多人协作,隐性 Bug 很难在开发阶段暴露

1.2 并发与资源控制的局限

在高并发网络扫描场景下,Python 的并发模型并不直观:

  • 线程受 GIL 影响
  • 异步代码可读性和调试成本较高
  • 对底层资源(连接、缓冲区)的控制能力有限

Python 并不是做不到,而是需要不断“绕”语言本身。

最终我得出的结论是:

Python 非常适合脚本化安全工具,
但并不适合承载一个复杂、长期演进的扫描器工程。


二、为什么不用 Go

在放弃 Python 作为工程语言后,我认真考虑过 Go。

从客观角度看,Go 在安全工具开发中具备明显优势:

  • 编译型、强类型
  • 原生并发模型(goroutine)
  • 网络库成熟
  • 社区已有不少扫描器实现

但在具体分析自己的扫描器需求后,我最终还是没有选择 Go。

2.1 扫描器的并发模型需求

我计划中的扫描器具备以下特点:

  • 大量短生命周期的网络连接
  • 扫描任务并发度高,但生命周期差异极大
  • 需要明确控制扫描任务的创建、释放和回收时机

在这种模型下,我希望对资源生命周期有更直接的掌控。

2.2 对 GC 行为的工程取舍

Go 的 GC 在大多数业务场景下表现优秀,这一点毫无疑问。
但在我预期的扫描场景中:

  • GC 触发时机并不完全可控
  • 扫描高峰期的内存波动不够“确定”
  • 我希望扫描核心路径尽量避免运行时干预

因此,与其说是 Go 不适合,不如说是:

我期望的扫描器模型,需要比 Go 更明确的资源控制语义。

这是一种工程取舍,而不是语言优劣之分。


三、我最怕 Rust 的哪一点

在真正决定使用 Rust 之前,我对 Rust 有明显的心理抗拒,主要集中在两点:

  1. 所有权机制
  2. 异步(async / await)模型

3.1 所有权:最痛苦,但也最有价值

作为安全工程师,我一开始并不关心内存模型。
我只关心扫描能不能跑、结果准不准。

但在实际开发中,Rust 的所有权机制逼迫我思考:

  • 扫描状态到底应该由谁持有
  • 扫描结果在哪个阶段生成、在哪个阶段被消费
  • 哪些数据应该是共享的,哪些必须是独占的

虽然一开始被 borrow checker 折磨得很痛苦,但随着工程推进,我逐渐发现:

所有权机制让扫描器的状态流转变得非常清晰。

很多在 Python 或 Go 中需要靠“约定”维护的安全性,在 Rust 中被编译器提前拦截了。


3.2 异步:学习成本高,但边界清晰

Rust 的异步学习曲线确实陡峭,尤其是对初学者而言。

但在扫描器这种高度并发的场景中,异步模型带来的收益非常明显:

  • 每一个扫描任务的生命周期是清晰的
  • 并发边界由代码结构决定,而不是隐式行为
  • 扫描调度逻辑更容易模块化

我现在仍然不敢说自己“精通 Rust 异步”,但至少已经体会到:

Rust 的 async 不是让你写得更快,
而是逼你把并发逻辑想清楚。


四、Rust 红队开发视角下的语言选择

最终选择 Rust,并不是因为它“更高级”或“更流行”,而是因为它更符合我对扫描器未来形态的预期:

  • 一个长期维护的工程
  • 一个可扩展、可组合的扫描框架
  • 一个在高并发场景下行为可预测的工具

Rust 红队开发 的角度来看,Rust 更像是一种“工程约束工具”,而不是效率工具。


五、总结

回顾整个语言选择过程:

  • Python:适合脚本化工具,但工程化成本高
  • Go:并发友好,但在我预期的扫描模型下控制粒度不足
  • Rust:学习曲线陡峭,但工程边界清晰、长期收益高

我选择 Rust,并不是因为它最简单,而是因为它更符合这个扫描器“未来要走多远”的定位。

接下来,我会逐步记录这个扫描器的设计与实现过程,包括:

  • 项目目录结构设计
  • 扫描模块的 trait 抽象
  • 并发调度模型
  • 扫描结果与状态管理

如果你也是安全工程师,正在考虑是否使用 Rust 编写工具,希望这篇文章能为你提供一个真实的参考视角。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐