feat: v2.1.0 核心重构与功能增强

## 架构重构
- 全局变量消除,迁移至 Config/State 对象
- SMB 插件融合(smb/smb2/smbghost/smbinfo)
- 服务探测重构,实现 Nmap 风格 fallback 机制
- 输出系统重构,TXT 实时刷盘 + 双写机制
- i18n 框架升级至 go-i18n

## 性能优化
- 正则表达式预编译
- 内存优化 map[string]struct{}
- 并发指纹匹配
- SOCKS5 连接复用
- 滑动窗口调度 + 自适应线程池

## 新功能
- Web 管理界面
- 多格式 POC 适配(xray/afrog)
- 增强指纹库(3139条)
- Favicon hash 指纹识别
- 插件选择性编译(Build Tags)
- fscan-lab 靶场环境
- 默认端口扩展(62→133)

## 构建系统
- 添加 no_local tag 支持排除本地插件
- 多版本构建:fscan/fscan-nolocal/fscan-web
- CI 添加 snapshot 模式支持仅测试构建

## Bug 修复
- 修复 120+ 个问题,包括 RDP panic、批量扫描漏报、
  JSON 输出格式、Redis 检测、Context 超时等

## 测试增强
- 单元测试覆盖率 74-100%
- 并发安全测试
- 集成测试(Web/端口/服务/SSH/ICMP)
This commit is contained in:
ZacharyZcR
2026-01-11 20:16:23 +08:00
parent 6b13b2e84f
commit 71b92d4408
948 changed files with 92335 additions and 24630 deletions
+249
View File
@@ -0,0 +1,249 @@
# FScan 插件开发规范
## 概述
FScan 采用简化的单文件插件架构,每个插件一个 `.go` 文件,消除了过度设计的多文件结构。
1. **简洁至上**:消除所有不必要的抽象层
2. **直击本质**:专注于解决实际问题,不为架构而架构
3. **向后兼容**:不破坏用户接口和现有功能
4. **消除特殊情况**:统一处理逻辑,减少 if/else 分支
## 插件架构
### 核心接口
```go
// 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, config *common.Config) *ExploitResult
}
```
### 数据结构
```go
// 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
```go
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)
```go
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, config *common.Config) *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()`
- **插件名称**:小写,与文件名一致
### 代码规范
1. **错误处理**:始终使用Context进行超时控制
2. **日志输出**:成功时使用 `common.LogSuccess`,调试用 `common.LogDebug`
3. **凭据生成**:使用 `GenerateCredentials(service_name)` 生成测试凭据
4. **资源管理**:及时关闭连接,使用 defer 确保清理
### 测试要求
每个插件必须支持:
1. **暴力破解模式**`common.DisableBrute = false`
2. **服务识别模式**`common.DisableBrute = true`
3. **Context超时处理**:正确响应 `ctx.Done()`
4. **代理支持**:如果 `common.Socks5Proxy` 不为空
## 迁移指南
### 从三文件架构迁移
1. **提取核心逻辑**:从 connector.go 提取认证逻辑
2. **合并实现**:将 plugin.go 中的组装逻辑内联
3. **删除垃圾**:删除空的 exploiter.go
4. **简化数据结构**:只保留必要的字段
### 从Legacy插件迁移
1. **保留核心逻辑**:复制扫描和认证的核心算法
2. **标准化接口**:实现统一的Plugin接口
3. **移除全局依赖**:通过返回值而不是全局变量传递结果
4. **统一日志**:使用统一的日志接口
## 性能优化
1. **连接复用**:在同一次扫描中复用连接
2. **内存管理**:及时释放不需要的资源
3. **并发控制**:通过Context控制并发度
4. **超时设置**:合理设置各阶段超时时间
## 示例
参考 `mysql.go` 作为标准的纯扫描插件实现
参考 `ssh.go` 作为带利用功能的插件实现
---
**记住:好的代码不是写出来的,是重构出来的。消除所有不必要的复杂性,直击问题本质。**