📌 关键词:#Rust 工程级扫描器实战 #Rust 红队开发 #Rust 网络扫描 #扫描器工程骨架期 #红队工具开发
📌 专栏说明:本专栏聚焦 Rust 红队扫描器(LSCAN)从脚本到工程化落地的全流程,核心探讨工程架构、模块划分、并发模型与设计取舍,不涉及基础语法教学,适合有 Rust 基础的红队工具开发者参考。
🔥 前言
上一篇我们通过统一上下文、标准化会话优化了 Stage 框架,提升了工程化程度与易用性。但随着扫描器功能迭代,原架构暴露出“组件耦合高、扩展困难、测试成本高”等问题。本次架构大升级将基于 RustMap 优秀设计理念,从“分层架构”和“设计模式”两大核心维度重构,打造可扩展、易维护、符合现代 Rust 应用最佳实践的工程化架构。
一、核心升级背景与目标
1.1 升级背景
原架构存在以下核心痛点,已无法满足长期迭代需求:
-
组件耦合紧密:扫描逻辑、配置管理、输出处理等功能交织,修改一处需联动调整多处;
-
缺乏抽象层:直接依赖具体实现,新增扫描类型(如资产探测)需大幅修改核心代码;
-
扩展能力不足:输出格式、扫描策略等扩展场景需修改原有逻辑,不符合“开闭原则”;
-
测试成本高昂:核心逻辑难以mock,单元测试覆盖率低;
-
配置管理混乱:部分配置硬编码,缺乏统一的配置加载与验证机制。
1.2 升级目标
本次升级核心目标是构建“分层清晰、抽象完备、解耦彻底、易于扩展”的工程化架构,具体实现:
-
明确架构分层,实现“职责单一”原则;
-
引入核心设计模式,降低组件耦合;
-
统一抽象接口,提升扩展灵活性;
-
完善配置与事件系统,支撑模块化协作;
-
提升代码可测试性,降低维护成本。
二、核心升级思路
本次升级围绕“分层架构+设计模式”双核心展开,核心思路:
-
按“用户交互-应用编排-业务逻辑-基础设施”划分架构分层,明确各层职责;
-
基于 Rust Trait 实现抽象接口,落地依赖倒置原则,解耦“抽象”与“实现”;
-
引入观察者、工厂、策略等设计模式,解决组件通信、实例创建、多策略扩展问题;
-
构建事件总线与统一配置中心,支撑模块化协作与灵活配置。
三、核心结构设计说明
3.1 四层架构设计
优化后的架构分为四层,每层职责单一,依赖关系自上而下(上层依赖下层抽象,不依赖具体实现):
┌─────────────────────────────────────────┐
│ CLI Layer (cli/) │ ← 用户交互层:处理命令行输入,解析用户指令
├─────────────────────────────────────────┤
│ Application Layer (core.rs) │ ← 应用编排层:协调各模块工作,通过事件总线通信
│ - Application 编排器 │
│ - EventBus 事件总线 │
├─────────────────────────────────────────┤
│ Business Logic Layer (scanner/) │ ← 业务逻辑层:实现核心扫描功能,基于Trait抽象
│ - Scanner (trait) │
│ - HostDetector (trait) │
│ - PortScanner (trait) │
│ - ServiceDetector (trait) │
│ - PocScanner (trait) │
├─────────────────────────────────────────┤
│ Infrastructure Layer │ ← 基础设施层:提供通用能力,支撑上层功能
│ - Config (配置管理) │
│ - Output (输出格式化) │
│ - Error (错误处理) │
│ - Logging (日志系统) │
└─────────────────────────────────────────┘
3.2 核心设计模式解析
本次升级落地5大核心设计模式,解决不同场景下的工程化问题:
模式1:Trait 抽象(面向接口编程)
所有核心业务功能均定义为 Trait 抽象接口,具体实现与接口分离,落地依赖倒置原则:
// 定义扫描器抽象接口
pub trait Scanner {
fn scan(&self, session: &Session) -> Result<Vec<ScanContext>>;
fn name(&self) -> &str; // 获取扫描器名称
}
// 实现具体的默认扫描器
pub struct DefaultScanner {
host_detector: Box<dyn HostDetector>,
port_scanner: Box<dyn PortScanner>,
// 组合其他检测器
}
impl Scanner for DefaultScanner {
fn scan(&self, session: &Session) -> Result<Vec<ScanContext>> {
// 实现扫描逻辑,调用组合的检测器
let alive_hosts = self.host_detector.detect(&session.targets)?;
let port_results = self.port_scanner.scan(&alive_hosts, &session.ports)?;
Ok(port_results)
}
fn name(&self) -> &str {
"default_scanner"
}
}
// 使用抽象(依赖抽象而非具体实现)
let scanner: Box<dyn Scanner> = create_scanner(&config);
let results = scanner.scan(&session)?;
优势:
① 易于测试(可通过mock实现Trait模拟依赖);
② 易于扩展(新增扫描器只需实现Trait,无需修改原有逻辑);
③ 松耦合(上层模块仅依赖Trait接口,不依赖具体实现)。
模式2:观察者模式(事件驱动)
通过 EventBus 事件总线实现组件间解耦通信,核心扫描流程中发布事件,其他模块订阅处理:
// 定义扫描事件枚举
pub enum ScanEvent {
PortDiscovered { ip: String, port: u16 }, // 端口发现事件
ServiceDetected { ip: String, service: String }, // 服务识别事件
VulnerabilityFound { ip: String, poc: String }, // 漏洞发现事件
}
// 事件处理器接口
pub trait EventHandler {
fn handle(&self, event: &ScanEvent);
}
// 事件总线实现(简化版)
pub struct EventBus {
handlers: Vec<Box<dyn EventHandler>>,
}
impl EventBus {
// 发布事件:通知所有订阅者
pub fn publish(&self, event: ScanEvent) {
for handler in &self.handlers {
handler.handle(&event);
}
}
// 订阅事件:注册处理器
pub fn subscribe(&mut self, handler: Box<dyn EventHandler>) {
self.handlers.push(handler);
}
}
// 使用示例:扫描过程中发布事件
event_bus.publish(ScanEvent::PortDiscovered { ip: "192.168.1.1".into(), port: 80 });
// 订阅事件:控制台输出处理器
struct ConsoleEventHandler;
impl EventHandler for ConsoleEventHandler {
fn handle(&self, event: &ScanEvent) {
match event {
ScanEvent::PortDiscovered { ip, port } => println!("发现开放端口:{}:{}", ip, port),
_ => {}
}
}
}
event_bus.subscribe(Box::new(ConsoleEventHandler));
优势:
① 组件解耦(发布者与订阅者无直接依赖);
② 实时反馈(扫描过程中实时推送状态);
③ 易于扩展(新增事件处理逻辑只需新增订阅者)。
模式3:工厂模式(实例创建)
通过工厂函数隐藏实例创建细节,根据配置动态生成具体实现,降低上层模块对实例创建的耦合:
// 扫描器工厂函数
pub fn create_scanner(config: &AppConfig) -> Box<dyn Scanner> {
// 根据配置创建不同的扫描器实例
Box::new(DefaultScanner::new(config.clone()))
}
// 输出格式化器工厂函数
pub fn create_formatter(format: &OutputFormat) -> Box<dyn OutputFormatter> {
match format {
OutputFormat::Json => Box::new(JsonFormatter),
OutputFormat::Text => Box::new(TextFormatter),
OutputFormat::Csv => Box::new(CsvFormatter),
}
}
模式4:策略模式(多策略扩展)
针对“输出格式化”等多策略场景,通过 Trait 定义统一接口,不同策略实现不同逻辑:
// 输出格式化器抽象接口
pub trait OutputFormatter {
fn format(&self, results: &[ScanContext]) -> Result<String>;
}
// 不同策略实现:JSON格式
pub struct JsonFormatter;
impl OutputFormatter for JsonFormatter {
fn format(&self, results: &[ScanContext]) -> Result<String> {
serde_json::to_string_pretty(results).map_err(|e| e.into())
}
}
// 文本格式
pub struct TextFormatter;
impl OutputFormatter for TextFormatter {
fn format(&self, results: &[ScanContext]) -> Result<String> {
// 文本格式化逻辑
Ok(format!("扫描结果总计:{}条", results.len()))
}
}
模式5:组合模式(功能组合)
DefaultScanner 组合多个检测器(HostDetector、PortScanner 等),将复杂扫描功能拆解为多个子功能的组合:
pub struct DefaultScanner {
host_detector: Box<dyn HostDetector>, // 主机发现检测器
port_scanner: Box<dyn PortScanner>, // 端口扫描器
service_detector: Box<dyn ServiceDetector>, // 服务识别器
poc_scanner: Box<dyn PocScanner>, // POC扫描器
}
impl DefaultScanner {
pub fn new(config: AppConfig) -> Self {
Self {
host_detector: create_host_detector(&config),
port_scanner: create_port_scanner(&config),
service_detector: create_service_detector(&config),
poc_scanner: create_poc_scanner(&config),
}
}
}
四、核心代码解析(架构核心组件)
4.1 应用编排器:Application
Application 位于应用编排层,负责协调各模块工作,是整个扫描器的“中枢”:
pub struct Application {
config: AppConfig, // 应用配置
event_bus: EventBus, // 事件总线
scanner: Box<dyn Scanner>, // 扫描器实例
formatter: Box<dyn OutputFormatter>, // 输出格式化器
}
impl Application {
pub fn new(config: AppConfig) -> Result<Self> {
// 初始化事件总线
let mut event_bus = EventBus::new();
// 订阅默认事件处理器(控制台输出)
event_bus.subscribe(Box::new(ConsoleEventHandler));
// 通过工厂函数创建实例
let scanner = create_scanner(&config);
let formatter = create_formatter(&config.output.format);
Ok(Self {
config,
event_bus,
scanner,
formatter,
})
}
// 执行扫描流程
pub fn run(&self, session: Session) -> Result<()> {
// 执行扫描
let results = self.scanner.scan(&session)?;
// 格式化输出
let formatted_result = self.formatter.format(&results)?;
// 输出结果(打印或保存文件)
if self.config.output.save_to_file {
std::fs::write(&self.config.output.output_path, formatted_result)?;
} else {
println!("{}", formatted_result);
}
Ok(())
}
// 获取事件总线(用于扩展订阅)
pub fn event_bus_mut(&mut self) -> &mut EventBus {
&mut self.event_bus
}
}
4.2 事件总线核心实现
use std::sync::Mutex;
// 线程安全的事件总线(支持多线程扫描场景)
pub struct EventBus {
handlers: Mutex<Vec<Box<dyn EventHandler + Send + Sync>>>,
}
impl EventBus {
pub fn new() -> Self {
Self {
handlers: Mutex::new(Vec::new()),
}
}
// 发布事件
pub fn publish(&self, event: ScanEvent) {
let handlers = self.handlers.lock().unwrap();
for handler in &*handlers {
handler.handle(&event);
}
}
// 订阅事件(支持动态添加)
pub fn subscribe(&self, handler: Box<dyn EventHandler + Send + Sync>) {
let mut handlers = self.handlers.lock().unwrap();
handlers.push(handler);
}
}
// 事件处理器Trait(支持线程安全)
pub trait EventHandler: Send + Sync {
fn handle(&self, event: &ScanEvent);
}
五、核心特点与知识点总结
5.1 架构核心特点
-
分层清晰:四层架构职责明确,降低跨层耦合;
-
抽象完备:基于Trait实现接口抽象,落地依赖倒置;
-
解耦彻底:通过事件总线实现组件通信解耦,无直接依赖;
-
扩展灵活:新增功能只需实现Trait或新增订阅者,符合开闭原则;
-
线程安全:事件总线支持多线程场景,适配后续并发优化。
5.2 核心知识点
-
Rust Trait 抽象:理解“接口”与“实现”的分离,掌握 dyn Trait 动态分发;
-
设计模式落地:学会在 Rust 中实现观察者、工厂、策略等经典模式;
-
线程安全设计:使用 Mutex 实现线程安全的事件总线,理解 Send/Sync Trait 约束;
-
依赖注入:通过工厂函数将实例创建与使用分离,提升可测试性。
六、下篇预告
本篇我们完成了架构分层重构与核心设计模式落地,明确了各层职责与组件协作方式。下一篇将聚焦“项目结构优化与配置管理”,详细解析优化后的项目目录组织、统一配置体系实现,以及核心模块的职责划分。
📌 温馨提示:如需要本次架构升级后的完整源码,可关注微信公众号【砺石安全】回复:【20260105】 进行领取
📌 互动交流:如果本文对你理解 Rust 红队工具的工程化架构有帮助,欢迎点赞、收藏、关注!如果有疑问或优化建议,也可以在评论区留言讨论~
📚 专栏导航:
上一篇:【Rust 工程级扫描器实战】06|工程骨架期:Stage 版框架优化
下一篇:【Rust 工程级扫描器实战】07-2|工程骨架期:项目结构优化与配置管理
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/weixin_44616217/article/details/156616498



