mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 03:10:42 +08:00
fix: Web 全局状态同步、字典文件错误提示、长驻插件连接可取消
- scan.go: Web API 构建 config/state 后同步到全局实例 - config_builder.go: 用户名/密码/URL 文件读取失败时输出错误日志 - reverseshell.go: 读命令设 1s 超时,超时后检查 ctx 实现可取消 - forwardshell.go: handleClient 接受 ctx,取消时关闭连接解除阻塞 - socks5proxy.go: handleClient 接受 ctx,取消时关闭连接解除 IO 阻塞
This commit is contained in:
@@ -100,6 +100,8 @@ func parseUsernames(fv *FlagVars) []string {
|
||||
if fv.UsersFile != "" {
|
||||
if lines, err := parsers.ReadLinesFromFile(fv.UsersFile); err == nil {
|
||||
usernames = append(usernames, lines...)
|
||||
} else {
|
||||
LogError(fmt.Sprintf("读取用户名文件 %s 失败: %v", fv.UsersFile, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +130,8 @@ func parsePasswords(fv *FlagVars) []string {
|
||||
if fv.PasswordsFile != "" {
|
||||
if lines, err := parsers.ReadLinesFromFile(fv.PasswordsFile); err == nil {
|
||||
passwords = append(passwords, lines...)
|
||||
} else {
|
||||
LogError(fmt.Sprintf("读取密码文件 %s 失败: %v", fv.PasswordsFile, err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +250,8 @@ func parseURLs(fv *FlagVars) []string {
|
||||
for _, line := range lines {
|
||||
urls = append(urls, normalizeURL(line))
|
||||
}
|
||||
} else {
|
||||
LogError(fmt.Sprintf("读取URL文件 %s 失败: %v", fv.URLsFile, err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,14 +114,20 @@ func (p *ForwardShellPlugin) startForwardShellServer(ctx context.Context, port i
|
||||
}
|
||||
|
||||
common.LogSuccess(i18n.Tr("forwardshell_client_connected", conn.RemoteAddr().String()))
|
||||
go p.handleClient(conn)
|
||||
go p.handleClient(ctx, conn)
|
||||
}
|
||||
}
|
||||
|
||||
// handleClient 处理客户端连接
|
||||
func (p *ForwardShellPlugin) handleClient(clientConn net.Conn) {
|
||||
func (p *ForwardShellPlugin) handleClient(ctx context.Context, clientConn net.Conn) {
|
||||
defer func() { _ = clientConn.Close() }()
|
||||
|
||||
// ctx 取消时关闭连接,解除阻塞的读操作
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = clientConn.Close()
|
||||
}()
|
||||
|
||||
// 发送欢迎信息
|
||||
welcome := fmt.Sprintf("FScan Forward Shell - %s\nType 'exit' to disconnect\n\n", runtime.GOOS)
|
||||
_, _ = clientConn.Write([]byte(welcome))
|
||||
@@ -145,7 +151,7 @@ func (p *ForwardShellPlugin) handleClient(clientConn net.Conn) {
|
||||
p.executeCommand(clientConn, command)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
if err := scanner.Err(); err != nil && ctx.Err() == nil {
|
||||
common.LogError(i18n.Tr("forwardshell_read_failed", err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package local
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"github.com/shadow1ng/fscan/common/i18n"
|
||||
@@ -123,12 +125,20 @@ func (p *ReverseShellPlugin) startNativeReverseShell(ctx context.Context, host s
|
||||
prompt := fmt.Sprintf("%s> ", getCurrentDir())
|
||||
_, _ = conn.Write([]byte(prompt))
|
||||
|
||||
// 设置读取超时,以便能响应 ctx 取消
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
|
||||
// 读取命令
|
||||
cmdLine, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
// 超时继续循环检查 ctx
|
||||
var netErr net.Error
|
||||
if errors.As(err, &netErr) && netErr.Timeout() {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("读取命令错误: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,24 +118,34 @@ func (p *Socks5ProxyPlugin) startSocks5Server(ctx context.Context, port int, sta
|
||||
}
|
||||
|
||||
// 并发处理客户端连接
|
||||
go p.handleClient(conn)
|
||||
go p.handleClient(ctx, conn)
|
||||
}
|
||||
}
|
||||
|
||||
// handleClient 处理客户端连接
|
||||
func (p *Socks5ProxyPlugin) handleClient(clientConn net.Conn) {
|
||||
func (p *Socks5ProxyPlugin) handleClient(ctx context.Context, clientConn net.Conn) {
|
||||
defer func() { _ = clientConn.Close() }()
|
||||
|
||||
// ctx 取消时关闭连接,解除阻塞的 IO
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = clientConn.Close()
|
||||
}()
|
||||
|
||||
// SOCKS5握手阶段
|
||||
if err := p.handleSocks5Handshake(clientConn); err != nil {
|
||||
common.LogError(i18n.Tr("socks5_handshake_failed", err))
|
||||
if ctx.Err() == nil {
|
||||
common.LogError(i18n.Tr("socks5_handshake_failed", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SOCKS5请求阶段
|
||||
targetConn, _, err := p.handleSocks5Request(clientConn)
|
||||
if err != nil {
|
||||
common.LogError(i18n.Tr("socks5_request_failed", err))
|
||||
if ctx.Err() == nil {
|
||||
common.LogError(i18n.Tr("socks5_request_failed", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
defer func() { _ = targetConn.Close() }()
|
||||
|
||||
+3
-1
@@ -206,9 +206,11 @@ func (h *ScanHandler) runScan(req ScanRequest) {
|
||||
fv.DisableSave = true // Web模式不保存到文件
|
||||
fv.Silent = true // 静默模式
|
||||
|
||||
// 构建Config
|
||||
// 构建Config,同步到全局实例供 network/限速等模块使用
|
||||
config := common.BuildConfigFromFlags(fv)
|
||||
state := common.NewState()
|
||||
common.SetGlobalConfig(config)
|
||||
common.SetGlobalState(state)
|
||||
|
||||
// 设置WebSocket结果回调
|
||||
common.SetResultCallback(func(result interface{}) {
|
||||
|
||||
Reference in New Issue
Block a user