feat: 完成大部分插件的socks5支持

This commit is contained in:
DullJZ 2025-07-29 06:50:43 +00:00
parent 444dd8c03c
commit ed9068569b
16 changed files with 302 additions and 86 deletions

View File

@ -1,13 +1,16 @@
package Common package Common
import ( import (
"context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"golang.org/x/net/proxy"
"net" "net"
"net/url" "net/url"
"strings" "strings"
"time" "time"
"golang.org/x/net/proxy"
) )
// WrapperTcpWithTimeout 创建一个带超时的TCP连接 // WrapperTcpWithTimeout 创建一个带超时的TCP连接
@ -16,6 +19,12 @@ func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.
return WrapperTCP(network, address, d) return WrapperTCP(network, address, d)
} }
// WrapperTcpWithContext 创建一个带上下文的TCP连接
func WrapperTcpWithContext(ctx context.Context, network, address string) (net.Conn, error) {
d := &net.Dialer{}
return WrapperTCPWithContext(ctx, network, address, d)
}
// WrapperTCP 根据配置创建TCP连接 // WrapperTCP 根据配置创建TCP连接
func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) { func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) {
// 直连模式 // 直连模式
@ -41,6 +50,54 @@ func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error)
return conn, nil return conn, nil
} }
// WrapperTCPWithContext 根据配置创建支持上下文的TCP连接
func WrapperTCPWithContext(ctx context.Context, network, address string, forward *net.Dialer) (net.Conn, error) {
// 直连模式
if Socks5Proxy == "" {
conn, err := forward.DialContext(ctx, network, address)
if err != nil {
return nil, fmt.Errorf(GetText("tcp_conn_failed"), err)
}
return conn, nil
}
// Socks5代理模式
dialer, err := Socks5Dialer(forward)
if err != nil {
return nil, fmt.Errorf(GetText("socks5_create_failed"), err)
}
// 创建一个结果通道来处理连接和取消
connChan := make(chan struct {
conn net.Conn
err error
}, 1)
go func() {
conn, err := dialer.Dial(network, address)
select {
case <-ctx.Done():
if conn != nil {
conn.Close()
}
case connChan <- struct {
conn net.Conn
err error
}{conn, err}:
}
}()
select {
case <-ctx.Done():
return nil, ctx.Err()
case result := <-connChan:
if result.err != nil {
return nil, fmt.Errorf(GetText("socks5_conn_failed"), result.err)
}
return result.conn, nil
}
}
// Socks5Dialer 创建Socks5代理拨号器 // Socks5Dialer 创建Socks5代理拨号器
func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) { func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) {
// 解析代理URL // 解析代理URL
@ -76,3 +133,59 @@ func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) {
return dialer, nil return dialer, nil
} }
// WrapperTlsWithContext 创建一个通过代理的TLS连接
func WrapperTlsWithContext(ctx context.Context, network, address string, tlsConfig *tls.Config) (net.Conn, error) {
// 直连模式
if Socks5Proxy == "" {
dialer := &net.Dialer{}
tcpConn, err := dialer.DialContext(ctx, network, address)
if err != nil {
return nil, fmt.Errorf("直连TCP连接失败: %v", err)
}
// 在TCP连接上进行TLS握手
tlsConn := tls.Client(tcpConn, tlsConfig)
// 使用ctx的deadline设置TLS握手超时
if deadline, ok := ctx.Deadline(); ok {
tlsConn.SetDeadline(deadline)
}
if err := tlsConn.Handshake(); err != nil {
tcpConn.Close()
return nil, fmt.Errorf("TLS握手失败: %v", err)
}
// 清除deadline让上层代码自己管理超时
tlsConn.SetDeadline(time.Time{})
return tlsConn, nil
}
// Socks5代理模式
// 首先通过代理建立到目标的TCP连接
tcpConn, err := WrapperTcpWithContext(ctx, network, address)
if err != nil {
return nil, fmt.Errorf("通过代理建立TCP连接失败: %v", err)
}
// 在TCP连接上进行TLS握手
tlsConn := tls.Client(tcpConn, tlsConfig)
// 使用ctx的deadline设置TLS握手超时
if deadline, ok := ctx.Deadline(); ok {
tlsConn.SetDeadline(deadline)
}
if err := tlsConn.Handshake(); err != nil {
tcpConn.Close()
return nil, fmt.Errorf("TLS握手失败: %v", err)
}
// 清除deadline让上层代码自己管理超时
tlsConn.SetDeadline(time.Time{})
return tlsConn, nil
}

View File

@ -3,11 +3,11 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// ActiveMQCredential 表示一个ActiveMQ凭据 // ActiveMQCredential 表示一个ActiveMQ凭据
@ -213,8 +213,7 @@ func ActiveMQConn(ctx context.Context, info *Common.HostInfo, user string, pass
addr := fmt.Sprintf("%s:%v", info.Host, info.Ports) addr := fmt.Sprintf("%s:%v", info.Host, info.Ports)
// 使用上下文创建带超时的连接 // 使用上下文创建带超时的连接
dialer := &net.Dialer{Timeout: time.Duration(Common.Timeout) * time.Second} conn, err := Common.WrapperTcpWithTimeout("tcp", addr, time.Duration(Common.Timeout)*time.Second)
conn, err := dialer.DialContext(ctx, "tcp", addr)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -3,14 +3,29 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/gocql/gocql" "net"
"github.com/shadow1ng/fscan/Common"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/gocql/gocql"
"github.com/shadow1ng/fscan/Common"
) )
// CassandraProxyDialer 实现gocql.Dialer接口支持代理连接
type CassandraProxyDialer struct {
timeout time.Duration
}
func (d *CassandraProxyDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
return Common.WrapperTcpWithContext(ctx, network, fmt.Sprintf("%s:%s", host, port))
}
// CassandraCredential 表示一个Cassandra凭据 // CassandraCredential 表示一个Cassandra凭据
type CassandraCredential struct { type CassandraCredential struct {
Username string Username string
@ -223,6 +238,13 @@ func CassandraConn(ctx context.Context, info *Common.HostInfo, user string, pass
cluster.ProtoVersion = 4 cluster.ProtoVersion = 4
cluster.Consistency = gocql.One cluster.Consistency = gocql.One
// 如果配置了代理设置自定义Dialer
if Common.Socks5Proxy != "" {
cluster.Dialer = &CassandraProxyDialer{
timeout: timeout,
}
}
if user != "" || pass != "" { if user != "" || pass != "" {
cluster.Authenticator = gocql.PasswordAuthenticator{ cluster.Authenticator = gocql.PasswordAuthenticator{
Username: user, Username: user,

View File

@ -5,12 +5,13 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"io" "io"
"net" "net"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// IMAPCredential 表示一个IMAP凭据 // IMAPCredential 表示一个IMAP凭据
@ -211,8 +212,7 @@ func IMAPConn(ctx context.Context, info *Common.HostInfo, user string, pass stri
// 在协程中尝试连接 // 在协程中尝试连接
go func() { go func() {
// 先尝试普通连接 // 先尝试普通连接
dialer := &net.Dialer{Timeout: timeout} conn, err := Common.WrapperTcpWithContext(ctx, "tcp", addr)
conn, err := dialer.DialContext(ctx, "tcp", addr)
if err == nil { if err == nil {
flag, authErr := tryIMAPAuth(conn, user, pass, timeout) flag, authErr := tryIMAPAuth(conn, user, pass, timeout)
conn.Close() conn.Close()
@ -232,14 +232,16 @@ func IMAPConn(ctx context.Context, info *Common.HostInfo, user string, pass stri
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
tlsConn, tlsErr := tls.DialWithDialer(dialer, "tcp", addr, tlsConfig)
// 使用支持代理的TLS连接
tlsConn, tlsErr := Common.WrapperTlsWithContext(ctx, "tcp", addr, tlsConfig)
if tlsErr != nil { if tlsErr != nil {
select { select {
case <-ctx.Done(): case <-ctx.Done():
case resultChan <- struct { case resultChan <- struct {
success bool success bool
err error err error
}{false, fmt.Errorf("连接失败: %v", tlsErr)}: }{false, fmt.Errorf("TLS连接失败: %v", tlsErr)}:
} }
return return
} }

View File

@ -3,12 +3,12 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/go-ldap/ldap/v3"
"github.com/shadow1ng/fscan/Common"
"net"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/go-ldap/ldap/v3"
"github.com/shadow1ng/fscan/Common"
) )
// LDAPCredential 表示一个LDAP凭据 // LDAPCredential 表示一个LDAP凭据
@ -210,13 +210,8 @@ func tryLDAPCredential(ctx context.Context, info *Common.HostInfo, credential LD
func LDAPConn(ctx context.Context, info *Common.HostInfo, user string, pass string) (bool, error) { func LDAPConn(ctx context.Context, info *Common.HostInfo, user string, pass string) (bool, error) {
address := fmt.Sprintf("%s:%s", info.Host, info.Ports) address := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 创建拨号器并设置超时
dialer := &net.Dialer{
Timeout: time.Duration(Common.Timeout) * time.Second,
}
// 使用上下文控制的拨号过程 // 使用上下文控制的拨号过程
conn, err := dialer.DialContext(ctx, "tcp", address) conn, err := Common.WrapperTcpWithContext(ctx, "tcp", address)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -4,13 +4,25 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
_ "github.com/denisenkom/go-mssqldb" "net"
"github.com/shadow1ng/fscan/Common"
"strings" "strings"
"sync" "sync"
"time" "time"
mssql "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/Common"
) )
// MSSQLProxyDialer 自定义dialer结构体
type MSSQLProxyDialer struct {
timeout time.Duration
}
// DialContext 实现mssql.Dialer接口支持socks代理
func (d *MSSQLProxyDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
return Common.WrapperTcpWithContext(ctx, network, addr)
}
// MssqlCredential 表示一个MSSQL凭据 // MssqlCredential 表示一个MSSQL凭据
type MssqlCredential struct { type MssqlCredential struct {
Username string Username string
@ -205,7 +217,58 @@ func MssqlConn(ctx context.Context, info *Common.HostInfo, user string, pass str
host, username, password, port, host, username, password, port,
) )
// 建立数据库连接 // 检查是否需要使用socks代理
if Common.Socks5Proxy != "" {
// 使用自定义dialer创建连接器
connector, err := mssql.NewConnector(connStr)
if err != nil {
return false, err
}
// 设置自定义dialer
connector.Dialer = &MSSQLProxyDialer{
timeout: time.Duration(Common.Timeout) * time.Millisecond,
}
// 使用连接器创建数据库连接
db := sql.OpenDB(connector)
defer db.Close()
// 设置连接参数
db.SetConnMaxLifetime(timeout)
db.SetConnMaxIdleTime(timeout)
db.SetMaxIdleConns(0)
db.SetMaxOpenConns(1)
// 通过上下文执行ping操作以支持超时控制
pingCtx, pingCancel := context.WithTimeout(ctx, timeout)
defer pingCancel()
errChan := make(chan error, 1)
go func() {
errChan <- db.PingContext(pingCtx)
}()
// 等待ping结果或者超时
select {
case err := <-errChan:
if err != nil {
return false, err
}
return true, nil
case <-ctx.Done():
// 全局超时或取消
return false, ctx.Err()
case <-pingCtx.Done():
if pingCtx.Err() == context.DeadlineExceeded {
// 单个连接超时
return false, fmt.Errorf("连接超时")
}
return false, pingCtx.Err()
}
}
// 使用标准连接方式
db, err := sql.Open("mssql", connStr) db, err := sql.Open("mssql", connStr)
if err != nil { if err != nil {
return false, err return false, err

View File

@ -4,9 +4,9 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// ModbusScanResult 表示 Modbus 扫描结果 // ModbusScanResult 表示 Modbus 扫描结果
@ -77,8 +77,7 @@ func tryModbusScan(ctx context.Context, info *Common.HostInfo, timeoutSeconds in
// 在协程中执行扫描 // 在协程中执行扫描
go func() { go func() {
// 尝试建立连接 // 尝试建立连接
var d net.Dialer conn, err := Common.WrapperTcpWithContext(connCtx, "tcp", target)
conn, err := d.DialContext(connCtx, "tcp", target)
if err != nil { if err != nil {
select { select {
case <-connCtx.Done(): case <-connCtx.Done():

View File

@ -3,11 +3,11 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"io" "io"
"net"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// MongodbScan 执行MongoDB未授权扫描 // MongodbScan 执行MongoDB未授权扫描
@ -112,13 +112,8 @@ func MongodbUnauth(ctx context.Context, info *Common.HostInfo) (bool, error) {
func checkMongoAuth(ctx context.Context, address string, packet []byte) (string, error) { func checkMongoAuth(ctx context.Context, address string, packet []byte) (string, error) {
Common.LogDebug(fmt.Sprintf("建立MongoDB连接: %s", address)) Common.LogDebug(fmt.Sprintf("建立MongoDB连接: %s", address))
// 创建连接超时上下文
connCtx, cancel := context.WithTimeout(ctx, time.Duration(Common.Timeout)*time.Second)
defer cancel()
// 使用带超时的连接 // 使用带超时的连接
var d net.Dialer conn, err := Common.WrapperTcpWithTimeout("tcp", address, time.Duration(Common.Timeout)*time.Second)
conn, err := d.DialContext(connCtx, "tcp", address)
if err != nil { if err != nil {
return "", fmt.Errorf("连接失败: %v", err) return "", fmt.Errorf("连接失败: %v", err)
} }

View File

@ -4,13 +4,38 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
_ "github.com/go-sql-driver/mysql" "net"
"github.com/shadow1ng/fscan/Common"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/Common"
) )
// MySQLProxyDialer 自定义dialer结构体
type MySQLProxyDialer struct {
timeout time.Duration
}
// Dial 实现mysql.Dialer接口支持socks代理
func (d *MySQLProxyDialer) Dial(ctx context.Context, addr string) (net.Conn, error) {
return Common.WrapperTcpWithContext(ctx, "tcp", addr)
}
// registerMySQLDialer 注册MySQL自定义dialer
func registerMySQLDialer() {
// 创建自定义dialer
dialer := &MySQLProxyDialer{
timeout: time.Duration(Common.Timeout) * time.Millisecond,
}
// 注册自定义dialer到go-sql-driver/mysql
mysql.RegisterDialContext("tcp-proxy", func(ctx context.Context, addr string) (net.Conn, error) {
return dialer.Dial(ctx, addr)
})
}
// MySQLCredential 表示一个MySQL凭据 // MySQLCredential 表示一个MySQL凭据
type MySQLCredential struct { type MySQLCredential struct {
Username string Username string
@ -204,11 +229,24 @@ func MysqlConn(ctx context.Context, info *Common.HostInfo, user string, pass str
host, port, username, password := info.Host, info.Ports, user, pass host, port, username, password := info.Host, info.Ports, user, pass
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 构造连接字符串,包含超时设置 // 检查是否需要使用socks代理
connStr := fmt.Sprintf( var connStr string
"%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", if Common.Socks5Proxy != "" {
username, password, host, port, timeout, // 注册自定义dialer
) registerMySQLDialer()
// 使用自定义网络类型的连接字符串
connStr = fmt.Sprintf(
"%v:%v@tcp-proxy(%v:%v)/mysql?charset=utf8&timeout=%v",
username, password, host, port, timeout,
)
} else {
// 标准连接字符串
connStr = fmt.Sprintf(
"%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v",
username, password, host, port, timeout,
)
}
// 创建结果通道 // 创建结果通道
resultChan := make(chan struct { resultChan := make(chan struct {

View File

@ -3,11 +3,12 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
"github.com/shadow1ng/fscan/Common"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
"github.com/shadow1ng/fscan/Common"
) )
// Neo4jCredential 表示一个Neo4j凭据 // Neo4jCredential 表示一个Neo4j凭据
@ -268,6 +269,9 @@ func Neo4jConn(info *Common.HostInfo, user string, pass string) (bool, error) {
config := func(c *neo4j.Config) { config := func(c *neo4j.Config) {
c.SocketConnectTimeout = timeout c.SocketConnectTimeout = timeout
c.ConnectionAcquisitionTimeout = timeout c.ConnectionAcquisitionTimeout = timeout
// 注意Neo4j驱动可能不支持代理配置
// 如果需要代理支持,可能需要使用更底层的连接方式
} }
var driver neo4j.Driver var driver neo4j.Driver

View File

@ -5,11 +5,12 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net" "net"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// POP3Credential 表示一个POP3凭据 // POP3Credential 表示一个POP3凭据
@ -255,12 +256,7 @@ func POP3Conn(ctx context.Context, info *Common.HostInfo, user string, pass stri
// 在协程中尝试连接,支持取消 // 在协程中尝试连接,支持取消
go func() { go func() {
// 首先尝试普通连接 // 首先尝试普通连接
dialer := &net.Dialer{ conn, err := Common.WrapperTcpWithTimeout("tcp", addr, timeout)
Timeout: timeout,
// 增加KeepAlive设置可能有助于处理一些服务器的限制
KeepAlive: 30 * time.Second,
}
conn, err := dialer.DialContext(ctx, "tcp", addr)
if err == nil { if err == nil {
flag, authErr := tryPOP3Auth(conn, user, pass, timeout) flag, authErr := tryPOP3Auth(conn, user, pass, timeout)
conn.Close() conn.Close()
@ -287,7 +283,10 @@ func POP3Conn(ctx context.Context, info *Common.HostInfo, user string, pass stri
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
tlsConn, tlsErr := tls.DialWithDialer(dialer, "tcp", addr, tlsConfig) // 对于TLS连接暂时使用标准dialer
// TODO: 实现通过socks代理的TLS连接
tempDialer := &net.Dialer{Timeout: timeout}
tlsConn, tlsErr := tls.DialWithDialer(tempDialer, "tcp", addr, tlsConfig)
if tlsErr != nil { if tlsErr != nil {
select { select {
case <-ctx.Done(): case <-ctx.Done():

View File

@ -3,11 +3,11 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// RsyncCredential 表示一个Rsync凭据 // RsyncCredential 表示一个Rsync凭据
@ -212,13 +212,8 @@ func RsyncConn(ctx context.Context, info *Common.HostInfo, user string, pass str
host, port := info.Host, info.Ports host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 设置带有上下文的拨号器
dialer := &net.Dialer{
Timeout: timeout,
}
// 建立连接 // 建立连接
conn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", host, port)) conn, err := Common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%s", host, port), timeout)
if err != nil { if err != nil {
return false, "", err return false, "", err
} }
@ -335,13 +330,11 @@ func RsyncConn(ctx context.Context, info *Common.HostInfo, user string, pass str
} }
// 5. 为每个模块创建新连接尝试认证 // 5. 为每个模块创建新连接尝试认证
authConn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", host, port)) authConn, err := Common.WrapperTcpWithTimeout(host, port, timeout)
if err != nil { if err != nil {
continue continue
} }
defer authConn.Close() defer authConn.Close() // 重复初始握手
// 重复初始握手
authConn.SetReadDeadline(time.Now().Add(timeout)) authConn.SetReadDeadline(time.Now().Add(timeout))
_, err = authConn.Read(buffer) _, err = authConn.Read(buffer)
if err != nil { if err != nil {

View File

@ -3,13 +3,13 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net"
"os" "os"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
"github.com/hirochachacha/go-smb2" "github.com/hirochachacha/go-smb2"
) )
@ -316,9 +316,8 @@ func trySmb2Credential(ctx context.Context, info *Common.HostInfo, credential Sm
// Smb2Con 尝试SMB2连接并进行认证检查共享访问权限 // Smb2Con 尝试SMB2连接并进行认证检查共享访问权限
func Smb2Con(ctx context.Context, info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, shares []string) { func Smb2Con(ctx context.Context, info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, shares []string) {
// 建立TCP连接使用上下文提供的超时控制 // 建立TCP连接使用socks代理支持
var d net.Dialer conn, err := Common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:445", info.Host), time.Duration(Common.Timeout)*time.Second)
conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:445", info.Host))
if err != nil { if err != nil {
return false, fmt.Errorf("连接失败: %v", err), nil return false, fmt.Errorf("连接失败: %v", err), nil
} }

View File

@ -3,12 +3,12 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net"
"net/smtp" "net/smtp"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// SmtpCredential 表示一个SMTP凭据 // SmtpCredential 表示一个SMTP凭据
@ -253,11 +253,7 @@ func SmtpConn(info *Common.HostInfo, user string, pass string, timeoutSeconds in
addr := fmt.Sprintf("%s:%s", host, port) addr := fmt.Sprintf("%s:%s", host, port)
// 设置连接超时 // 设置连接超时
dialer := &net.Dialer{ conn, err := Common.WrapperTcpWithTimeout("tcp", addr, timeout)
Timeout: timeout,
}
conn, err := dialer.Dial("tcp", addr)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -5,12 +5,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common"
"net" "net"
"regexp" "regexp"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/shadow1ng/fscan/Common"
) )
// TelnetCredential 表示一个Telnet凭据 // TelnetCredential 表示一个Telnet凭据
@ -248,9 +249,8 @@ func tryTelnetCredential(ctx context.Context, info *Common.HostInfo, credential
// telnetConnWithContext 带上下文的Telnet连接尝试 // telnetConnWithContext 带上下文的Telnet连接尝试
func telnetConnWithContext(ctx context.Context, info *Common.HostInfo, user, pass string) (bool, error) { func telnetConnWithContext(ctx context.Context, info *Common.HostInfo, user, pass string) (bool, error) {
// 创建TCP连接(使用上下文控制) // 创建TCP连接(使用支持context的socks代理)
var d net.Dialer conn, err := Common.WrapperTcpWithContext(ctx, "tcp", fmt.Sprintf("%s:%s", info.Host, info.Ports))
conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", info.Host, info.Ports))
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -3,11 +3,11 @@ package Plugins
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/mitchellh/go-vnc"
"github.com/shadow1ng/fscan/Common"
"net"
"sync" "sync"
"time" "time"
"github.com/mitchellh/go-vnc"
"github.com/shadow1ng/fscan/Common"
) )
// VncCredential 表示VNC凭据 // VncCredential 表示VNC凭据
@ -190,8 +190,7 @@ func VncConn(ctx context.Context, info *Common.HostInfo, pass string) (bool, err
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 使用带上下文的TCP连接 // 使用带上下文的TCP连接
var d net.Dialer conn, err := Common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%s", Host, Port), timeout)
conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", Host, Port))
if err != nil { if err != nil {
return false, err return false, err
} }