mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

架构优化: - 删除Config.go、Log.go、Output.go、Proxy.go四个包装层文件 - 新增Bridge.go统一管理所有桥接功能,减少文件散乱 - 移除冗余测试文件和备份文件,清理项目结构 代码精简: - i18n.go从1100+行精简至63行,移除95%冗余多语言支持 - Variables.go从223行优化至71行,保留核心15个变量 - 将大部分全局变量分散到实际使用模块中 模块整合: - 四个包装层合并为单一Bridge.go文件 - 统一桥接接口,提供一致的API调用体验 - 优化config.Manager配置管理功能 性能提升: - 减少文件数量和代码冗余,提升编译速度 - 简化模块依赖关系,降低内存占用 - 保持100%向后兼容性,无破坏性变更 测试验证: - 所有核心功能测试通过 - API接口完全兼容,现有代码无需修改 - 编译无错误,运行稳定可靠
341 lines
12 KiB
Go
341 lines
12 KiB
Go
package Common
|
||
|
||
/*
|
||
Bridge.go - 统一桥接模块
|
||
|
||
将Config.go、Log.go、Output.go、Proxy.go的桥接功能合并到一个文件中,
|
||
减少文件数量,提高代码组织性。保持所有原有API的完全兼容性。
|
||
*/
|
||
|
||
import (
|
||
"context"
|
||
"crypto/tls"
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"net"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/fatih/color"
|
||
"github.com/schollz/progressbar/v3"
|
||
|
||
"github.com/shadow1ng/fscan/Common/config"
|
||
"github.com/shadow1ng/fscan/Common/logging"
|
||
"github.com/shadow1ng/fscan/Common/output"
|
||
"github.com/shadow1ng/fscan/Common/proxy"
|
||
)
|
||
|
||
// =============================================================================
|
||
// 配置桥接 (Config.go 功能)
|
||
// =============================================================================
|
||
|
||
var version = "2.0.2"
|
||
|
||
// 向后兼容的输出配置变量
|
||
var (
|
||
Outputfile string
|
||
OutputFormat string
|
||
ProgressBar *progressbar.ProgressBar
|
||
OutputMutex sync.Mutex
|
||
)
|
||
|
||
// PocInfo POC详细信息结构
|
||
type PocInfo = config.PocInfo
|
||
|
||
// 配置相关函数
|
||
func GetVersion() string { return config.GetGlobalVersion() }
|
||
func SetVersion(v string) { config.SetGlobalVersion(v) }
|
||
func GetProgressBar() *progressbar.ProgressBar { return config.GetGlobalProgressBar() }
|
||
func SetConfigProgressBar(pb *progressbar.ProgressBar) {
|
||
config.SetGlobalProgressBar(pb)
|
||
ProgressBar = pb
|
||
}
|
||
func GetOutputMutex() *sync.Mutex { return config.GetGlobalOutputMutex() }
|
||
func GetConfigManager() *config.Manager { return config.GetGlobalManager() }
|
||
func GetFullConfig() *config.Config { return config.GetGlobalConfig() }
|
||
func SetFullConfig(cfg *config.Config) { config.SetGlobalManagerConfig(cfg); syncOutputConfig() }
|
||
|
||
func syncOutputConfig() {
|
||
cfg := config.GetGlobalConfig()
|
||
if cfg != nil && cfg.Output != nil {
|
||
Outputfile = cfg.Output.Outputfile
|
||
OutputFormat = cfg.Output.OutputFormat
|
||
}
|
||
ProgressBar = config.GetGlobalProgressBar()
|
||
}
|
||
|
||
func SyncConfigOutputSettings() {
|
||
cfg := config.GetGlobalConfig()
|
||
if cfg != nil && cfg.Output != nil {
|
||
cfg.Output.Outputfile = Outputfile
|
||
cfg.Output.OutputFormat = OutputFormat
|
||
config.SetGlobalManagerConfig(cfg)
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// 日志桥接 (Log.go 功能)
|
||
// =============================================================================
|
||
|
||
// 全局日志状态和变量
|
||
var (
|
||
status = logging.NewScanStatus()
|
||
Num, End int64
|
||
StartTime = time.Now()
|
||
globalLogger *logging.Logger
|
||
loggerOnce sync.Once
|
||
)
|
||
|
||
// 日志级别常量
|
||
const (
|
||
LogLevelAll = string(logging.LevelAll)
|
||
LogLevelError = string(logging.LevelError)
|
||
LogLevelBase = string(logging.LevelBase)
|
||
LogLevelInfo = string(logging.LevelInfo)
|
||
LogLevelSuccess = string(logging.LevelSuccess)
|
||
LogLevelDebug = string(logging.LevelDebug)
|
||
LogLevelInfoSuccess = string(logging.LevelInfoSuccess)
|
||
LogLevelBaseInfoSuccess = string(logging.LevelBaseInfoSuccess)
|
||
)
|
||
|
||
// 类型别名
|
||
type LogEntry = logging.LogEntry
|
||
type ScanStatus = logging.ScanStatus
|
||
type ProgressDisplay = logging.ProgressDisplay
|
||
|
||
func getGlobalLogger() *logging.Logger {
|
||
loggerOnce.Do(func() {
|
||
config := &logging.LoggerConfig{
|
||
Level: logging.LevelBaseInfoSuccess, EnableColor: !NoColor, SlowOutput: SlowLogOutput,
|
||
ShowProgress: true, StartTime: StartTime,
|
||
LevelColors: map[logging.LogLevel]color.Attribute{
|
||
logging.LevelError: color.FgBlue, logging.LevelBase: color.FgYellow,
|
||
logging.LevelInfo: color.FgGreen, logging.LevelSuccess: color.FgRed, logging.LevelDebug: color.FgWhite,
|
||
},
|
||
}
|
||
globalLogger = logging.NewLogger(config)
|
||
if ProgressBar != nil { globalLogger.SetProgressBar(ProgressBar) }
|
||
globalLogger.SetOutputMutex(&OutputMutex)
|
||
status = globalLogger.GetScanStatus()
|
||
})
|
||
return globalLogger
|
||
}
|
||
|
||
// 日志相关函数
|
||
func InitLogger() { log.SetOutput(io.Discard); getGlobalLogger().Initialize() }
|
||
func LogDebug(msg string) { getGlobalLogger().Debug(msg) }
|
||
func LogBase(msg string) { getGlobalLogger().Base(msg) }
|
||
func LogInfo(msg string) { getGlobalLogger().Info(msg) }
|
||
func LogSuccess(result string) { getGlobalLogger().Success(result) }
|
||
func LogError(errMsg string) { getGlobalLogger().Error(errMsg) }
|
||
func CheckErrs(err error) error { return logging.CheckErrs(err) }
|
||
func GetScanStatus() *logging.ScanStatus { return status }
|
||
func UpdateScanProgress(completed, total int64) { status.SetCompleted(completed); status.SetTotal(total); End = completed; Num = total }
|
||
func SetProgressBar(progressBar ProgressDisplay) { if globalLogger != nil { globalLogger.SetProgressBar(progressBar) } }
|
||
|
||
func SetLoggerConfig(enableColor, slowOutput bool, progressBar ProgressDisplay) {
|
||
config := &logging.LoggerConfig{
|
||
Level: logging.LevelBaseInfoSuccess, EnableColor: enableColor, SlowOutput: slowOutput,
|
||
ShowProgress: true, StartTime: StartTime,
|
||
LevelColors: map[logging.LogLevel]color.Attribute{
|
||
logging.LevelError: color.FgBlue, logging.LevelBase: color.FgYellow,
|
||
logging.LevelInfo: color.FgGreen, logging.LevelSuccess: color.FgRed, logging.LevelDebug: color.FgWhite,
|
||
},
|
||
}
|
||
newLogger := logging.NewLogger(config)
|
||
if progressBar != nil { newLogger.SetProgressBar(progressBar) }
|
||
newLogger.SetOutputMutex(&OutputMutex)
|
||
globalLogger = newLogger
|
||
status = newLogger.GetScanStatus()
|
||
}
|
||
|
||
// =============================================================================
|
||
// 输出桥接 (Output.go 功能)
|
||
// =============================================================================
|
||
|
||
// 全局输出管理器
|
||
var ResultOutput *OutputManager
|
||
|
||
type OutputManager struct { manager *output.Manager }
|
||
type ResultType = output.ResultType
|
||
|
||
const (
|
||
HOST ResultType = output.TypeHost
|
||
PORT ResultType = output.TypePort
|
||
SERVICE ResultType = output.TypeService
|
||
VULN ResultType = output.TypeVuln
|
||
)
|
||
|
||
type ScanResult = output.ScanResult
|
||
|
||
func createOutputManager(outputPath, outputFormat string) (*OutputManager, error) {
|
||
var format output.OutputFormat
|
||
switch outputFormat {
|
||
case "txt": format = output.FormatTXT
|
||
case "json": format = output.FormatJSON
|
||
case "csv": format = output.FormatCSV
|
||
default: return nil, fmt.Errorf(GetText("output_format_invalid"), outputFormat)
|
||
}
|
||
|
||
config := output.DefaultManagerConfig(outputPath, format)
|
||
manager, err := output.NewManager(config)
|
||
if err != nil { return nil, err }
|
||
return &OutputManager{manager: manager}, nil
|
||
}
|
||
|
||
// 输出相关函数
|
||
func InitOutput() error {
|
||
LogDebug(GetText("output_init_start"))
|
||
switch OutputFormat {
|
||
case "txt", "json", "csv":
|
||
default: return fmt.Errorf(GetText("output_format_invalid"), OutputFormat)
|
||
}
|
||
if Outputfile == "" { return fmt.Errorf(GetText("output_path_empty")) }
|
||
|
||
manager, err := createOutputManager(Outputfile, OutputFormat)
|
||
if err != nil {
|
||
LogDebug(GetText("output_init_failed", err))
|
||
return fmt.Errorf(GetText("output_init_failed", err))
|
||
}
|
||
ResultOutput = manager
|
||
output.SetGlobalManager(manager.manager)
|
||
LogDebug(GetText("output_init_success"))
|
||
return nil
|
||
}
|
||
|
||
func (om *OutputManager) saveResult(result *ScanResult) error {
|
||
if om.manager == nil { return fmt.Errorf(GetText("output_not_init")) }
|
||
LogDebug(GetText("output_saving_result", result.Type, result.Target))
|
||
return om.manager.SaveResult(result)
|
||
}
|
||
|
||
func SaveResult(result *ScanResult) error {
|
||
if ResultOutput == nil {
|
||
LogDebug(GetText("output_not_init"))
|
||
return fmt.Errorf(GetText("output_not_init"))
|
||
}
|
||
return ResultOutput.saveResult(result)
|
||
}
|
||
|
||
func GetResults() ([]*ScanResult, error) {
|
||
if ResultOutput == nil { return nil, fmt.Errorf(GetText("output_not_init")) }
|
||
return ResultOutput.manager.GetResults()
|
||
}
|
||
|
||
func CloseOutput() error {
|
||
if ResultOutput == nil { return nil }
|
||
LogDebug(GetText("output_closing"))
|
||
err := ResultOutput.manager.Close()
|
||
if err != nil { return fmt.Errorf(GetText("output_close_failed", err)) }
|
||
LogDebug(GetText("output_closed"))
|
||
return nil
|
||
}
|
||
|
||
// 便利函数
|
||
func SaveResultWithDetails(resultType ResultType, target, status string, details map[string]interface{}) error {
|
||
result := &ScanResult{Time: time.Now(), Type: resultType, Target: target, Status: status, Details: details}
|
||
return SaveResult(result)
|
||
}
|
||
|
||
func SaveHostResult(target string, isAlive bool, details map[string]interface{}) error {
|
||
status := "离线"; if isAlive { status = "存活" }
|
||
return SaveResultWithDetails(HOST, target, status, details)
|
||
}
|
||
|
||
func SavePortResult(target string, port int, isOpen bool, service string, details map[string]interface{}) error {
|
||
status := "关闭"; if isOpen { status = "开放" }
|
||
if details == nil { details = make(map[string]interface{}) }
|
||
details["port"] = port; if service != "" { details["service"] = service }
|
||
return SaveResultWithDetails(PORT, fmt.Sprintf("%s:%d", target, port), status, details)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 代理桥接 (Proxy.go 功能)
|
||
// =============================================================================
|
||
|
||
// 代理相关函数
|
||
func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
|
||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||
defer cancel()
|
||
return proxy.DialContextWithProxy(ctx, network, address)
|
||
}
|
||
|
||
func WrapperTcpWithContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||
return proxy.DialContextWithProxy(ctx, network, address)
|
||
}
|
||
|
||
func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) {
|
||
if err := syncProxyConfig(); err != nil { LogError("proxy_config_sync_failed: " + err.Error()) }
|
||
conn, err := proxy.DialWithProxy(network, address)
|
||
if err != nil {
|
||
LogError(GetText("tcp_conn_failed") + ": " + err.Error())
|
||
return nil, fmt.Errorf(GetText("tcp_conn_failed"), err)
|
||
}
|
||
return conn, nil
|
||
}
|
||
|
||
func WrapperTCPWithContext(ctx context.Context, network, address string, forward *net.Dialer) (net.Conn, error) {
|
||
if err := syncProxyConfig(); err != nil { LogError("proxy_config_sync_failed: " + err.Error()) }
|
||
conn, err := proxy.DialContextWithProxy(ctx, network, address)
|
||
if err != nil {
|
||
LogError(GetText("tcp_conn_failed") + ": " + err.Error())
|
||
return nil, fmt.Errorf(GetText("tcp_conn_failed"), err)
|
||
}
|
||
return conn, nil
|
||
}
|
||
|
||
func Socks5Dialer(forward *net.Dialer) (interface{}, error) {
|
||
if err := syncProxyConfig(); err != nil { return nil, fmt.Errorf(GetText("socks5_create_failed"), err) }
|
||
manager := proxy.GetGlobalProxy()
|
||
dialer, err := manager.GetDialer()
|
||
if err != nil { return nil, fmt.Errorf(GetText("socks5_create_failed"), err) }
|
||
return dialer, nil
|
||
}
|
||
|
||
func WrapperTlsWithContext(ctx context.Context, network, address string, tlsConfig *tls.Config) (net.Conn, error) {
|
||
if err := syncProxyConfig(); err != nil { LogError("proxy_config_sync_failed: " + err.Error()) }
|
||
conn, err := proxy.DialTLSContextWithProxy(ctx, network, address, tlsConfig)
|
||
if err != nil {
|
||
LogError("tls_conn_failed: " + err.Error())
|
||
return nil, fmt.Errorf("tls_conn_failed: %v", err)
|
||
}
|
||
return conn, nil
|
||
}
|
||
|
||
func syncProxyConfig() error {
|
||
var proxyURL string
|
||
if Socks5Proxy != "" { proxyURL = Socks5Proxy } else if HttpProxy != "" { proxyURL = HttpProxy }
|
||
|
||
if proxy.IsProxyEnabledGlobally() {
|
||
currentAddr := proxy.GetGlobalProxyAddress()
|
||
if (proxyURL == "" && currentAddr == "") ||
|
||
(proxyURL != "" && currentAddr != "" && (Socks5Proxy == currentAddr || HttpProxy == currentAddr)) {
|
||
return nil
|
||
}
|
||
}
|
||
|
||
if err := proxy.InitGlobalProxy(proxyURL); err != nil {
|
||
return fmt.Errorf("初始化代理配置失败: %v", err)
|
||
}
|
||
|
||
if proxyURL != "" {
|
||
LogBase(fmt.Sprintf("代理已启用: %s %s", proxy.GetGlobalProxyType(), proxy.GetGlobalProxyAddress()))
|
||
} else {
|
||
LogBase("代理已禁用")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func GetProxyStats() *proxy.ProxyStats { return proxy.GetGlobalProxyStats() }
|
||
func IsProxyEnabled() bool { return proxy.IsProxyEnabledGlobally() }
|
||
func CloseProxy() error { return proxy.CloseGlobalProxy() }
|
||
|
||
// =============================================================================
|
||
// 初始化函数
|
||
// =============================================================================
|
||
|
||
func init() {
|
||
config.SetGlobalVersion(version)
|
||
syncOutputConfig()
|
||
} |