mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-11-05 10:45:27 +00:00
**核心架构重构** - 重构目录结构:Common/ -> common/, Core/ -> core/, Plugins/ -> plugins/, WebScan/ -> webscan/ - 模块化设计:拆分common/为parsers/, logging/, i18n/, output/, proxy/等子模块 - 统一插件系统:消除Plugin/Scanner/LocalPlugin等重复接口 - 配置解析器重写:新增parsers包处理所有配置解析逻辑 - 国际化支持:完整的中英文i18n系统 **服务插件重构** (59个插件) - 所有服务插件采用统一接口设计 - 新增服务插件:ActiveMQ, Cassandra, Kafka, Neo4j, RabbitMQ, Rsync等 - 增强现有插件:SSH, MySQL, Redis, SMB, FTP, PostgreSQL等 - 本地功能插件:AVDetect, Cleaner, CronTask, KeyLogger, SystemInfo等26个 - 智能错误分类和重试机制 - 并发暴力破解优化 **核心扫描引擎** - 端口扫描重构:支持SYN/Connect/ICMP多种模式 - 服务识别增强:集成nmap-service-probes指纹库 - Web扫描优化:title抓取、POC检测、指纹识别 - 进度条系统:实时显示扫描进度、发包统计、内存使用 - 发包频率控制:支持-rate和-maxpkts限制 **新增功能** - user:pass格式字典支持 (-upf参数) #179 - fscan-lite C语言版本:轻量级无依赖版本 - 本地扫描模式:26个本地安全检测插件 - API模式:支持远程调用 - Docker测试环境:13个服务的docker-compose配置 **Bug修复** - 修复并发输出混乱问题 - 修复包计数双重统计 - 修复进度条显示不准确 - 修复-no参数被忽略 - 修复SMB/SSH认证问题 - 修复Oracle TNS服务识别错误 - 修复SafeDialTimeout缺失TCP计数 **性能优化** - 删除大量死代码和冗余函数 - 简化过度工程设计 - 优化端口扫描性能 - 减少内存占用 - 清理重复代码 **测试和CI/CD** - 新增核心模块单元测试 (2000+ loc) - GitHub Actions优化:统一构建发布流程 - 支持fscan和fscan-lite统一发布 - 中文化工作流配置 **文档** - 更新README文档 - 新增插件开发文档 - 完善国际化文档 **依赖更新** - 更新go.mod依赖 - 清理无用依赖 - 升级核心库版本 统计: - 删除文件:61个旧架构文件 - 新增文件:500+个模块化文件 - 代码行数:~50000 lines - Commits压缩:289 -> 1
6.7 KiB
6.7 KiB
FScan 插件开发规范
概述
FScan 采用简化的单文件插件架构,每个插件一个 .go 文件,消除了过度设计的多文件结构。
设计原则 (Linus Torvalds "好品味" 原则)
- 简洁至上:消除所有不必要的抽象层
- 直击本质:专注于解决实际问题,不为架构而架构
- 向后兼容:不破坏用户接口和现有功能
- 消除特殊情况:统一处理逻辑,减少 if/else 分支
插件架构
核心接口
// Plugin 插件接口 - 只保留必要的方法
type Plugin interface {
GetName() string // 插件名称
GetPorts() []int // 支持的端口
Scan(ctx context.Context, info *common.HostInfo) *ScanResult // 扫描功能
}
// 可选接口:如果插件支持利用功能
type Exploiter interface {
Exploit(ctx context.Context, info *common.HostInfo, creds Credential) *ExploitResult
}
数据结构
// ScanResult 扫描结果 - 删除所有冗余字段
type ScanResult struct {
Success bool // 扫描是否成功
Service string // 服务类型
Username string // 发现的用户名(弱密码)
Password string // 发现的密码(弱密码)
Banner string // 服务版本信息
Error error // 错误信息(如果失败)
}
// ExploitResult 利用结果(仅有利用功能的插件需要)
type ExploitResult struct {
Success bool // 利用是否成功
Output string // 命令执行输出
Error error // 错误信息
}
// Credential 凭据结构
type Credential struct {
Username string
Password string
KeyData []byte // SSH私钥等
}
插件开发模板
1. 纯扫描插件(如MySQL)
package plugins
import (
"context"
"fmt"
// 其他必要导入
)
// PluginName服务扫描插件
type PluginNamePlugin struct {
name string
ports []int
}
// 构造函数
func NewPluginNamePlugin() *PluginNamePlugin {
return &PluginNamePlugin{
name: "plugin_name",
ports: []int{default_port},
}
}
// 实现Plugin接口
func (p *PluginNamePlugin) GetName() string { return p.name }
func (p *PluginNamePlugin) GetPorts() []int { return p.ports }
func (p *PluginNamePlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult {
// 如果禁用暴力破解,只做服务识别
if common.DisableBrute {
return p.identifyService(info)
}
// 生成测试凭据
credentials := GenerateCredentials("plugin_name")
// 逐个测试凭据
for _, cred := range credentials {
select {
case <-ctx.Done():
return &ScanResult{Success: false, Error: ctx.Err()}
default:
}
if p.testCredential(ctx, info, cred) {
return &ScanResult{
Success: true,
Service: "plugin_name",
Username: cred.Username,
Password: cred.Password,
}
}
}
return &ScanResult{Success: false, Service: "plugin_name"}
}
// 核心认证逻辑
func (p *PluginNamePlugin) testCredential(ctx context.Context, info *common.HostInfo, cred Credential) bool {
// 实现具体的认证测试逻辑
return false
}
// 服务识别(-nobr模式)
func (p *PluginNamePlugin) identifyService(info *common.HostInfo) *ScanResult {
// 实现服务识别逻辑
return &ScanResult{Success: false, Service: "plugin_name"}
}
// 自动注册
func init() {
RegisterPlugin("plugin_name", func() Plugin {
return NewPluginNamePlugin()
})
}
2. 带利用功能的插件(如SSH)
package plugins
// SSH插件结构
type SSHPlugin struct {
name string
ports []int
}
// 同时实现Plugin和Exploiter接口
func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult {
// 扫描逻辑(同上)
}
func (p *SSHPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential) *ExploitResult {
// 建立SSH连接
client, err := p.connectSSH(info, creds)
if err != nil {
return &ExploitResult{Success: false, Error: err}
}
defer client.Close()
// 执行命令或其他利用操作
output, err := p.executeCommand(client, "whoami")
return &ExploitResult{
Success: err == nil,
Output: output,
Error: err,
}
}
// 辅助方法
func (p *SSHPlugin) connectSSH(info *common.HostInfo, creds Credential) (*ssh.Client, error) {
// SSH连接实现
}
func (p *SSHPlugin) executeCommand(client *ssh.Client, cmd string) (string, error) {
// 命令执行实现
}
开发规范
文件组织
plugins/
├── base.go # 核心接口和注册系统
├── mysql.go # MySQL插件
├── ssh.go # SSH插件
├── redis.go # Redis插件
└── README.md # 开发文档(本文件)
命名规范
- 插件文件:
{service_name}.go - 插件结构体:
{ServiceName}Plugin - 构造函数:
New{ServiceName}Plugin() - 插件名称:小写,与文件名一致
代码规范
- 错误处理:始终使用Context进行超时控制
- 日志输出:成功时使用
common.LogSuccess,调试用common.LogDebug - 凭据生成:使用
GenerateCredentials(service_name)生成测试凭据 - 资源管理:及时关闭连接,使用 defer 确保清理
测试要求
每个插件必须支持:
- 暴力破解模式:
common.DisableBrute = false - 服务识别模式:
common.DisableBrute = true - Context超时处理:正确响应
ctx.Done() - 代理支持:如果
common.Socks5Proxy不为空
迁移指南
从三文件架构迁移
- 提取核心逻辑:从 connector.go 提取认证逻辑
- 合并实现:将 plugin.go 中的组装逻辑内联
- 删除垃圾:删除空的 exploiter.go
- 简化数据结构:只保留必要的字段
从Legacy插件迁移
- 保留核心逻辑:复制扫描和认证的核心算法
- 标准化接口:实现统一的Plugin接口
- 移除全局依赖:通过返回值而不是全局变量传递结果
- 统一日志:使用统一的日志接口
性能优化
- 连接复用:在同一次扫描中复用连接
- 内存管理:及时释放不需要的资源
- 并发控制:通过Context控制并发度
- 超时设置:合理设置各阶段超时时间
示例
参考 mysql.go 作为标准的纯扫描插件实现
参考 ssh.go 作为带利用功能的插件实现
记住:好的代码不是写出来的,是重构出来的。消除所有不必要的复杂性,直击问题本质。