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:
ZacharyZcR
2026-04-27 21:45:16 +08:00
parent 653f11295a
commit 3d7cdcbe5f
5 changed files with 42 additions and 8 deletions
+9 -3
View File
@@ -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))
}
}
+10
View File
@@ -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)
}
+14 -4
View File
@@ -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() }()