diff --git a/Common/Proxy.go b/Common/Proxy.go index f70c198..ff473fc 100644 --- a/Common/Proxy.go +++ b/Common/Proxy.go @@ -1,13 +1,16 @@ package Common import ( + "context" + "crypto/tls" "errors" "fmt" - "golang.org/x/net/proxy" "net" "net/url" "strings" "time" + + "golang.org/x/net/proxy" ) // WrapperTcpWithTimeout 创建一个带超时的TCP连接 @@ -16,6 +19,12 @@ func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net. 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连接 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 } +// 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代理拨号器 func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) { // 解析代理URL @@ -76,3 +133,59 @@ func Socks5Dialer(forward *net.Dialer) (proxy.Dialer, error) { 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 +} diff --git a/Plugins/ActiveMQ.go b/Plugins/ActiveMQ.go index 3869b59..78879a5 100644 --- a/Plugins/ActiveMQ.go +++ b/Plugins/ActiveMQ.go @@ -3,11 +3,11 @@ package Plugins import ( "context" "fmt" - "github.com/shadow1ng/fscan/Common" - "net" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // 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) // 使用上下文创建带超时的连接 - dialer := &net.Dialer{Timeout: time.Duration(Common.Timeout) * time.Second} - conn, err := dialer.DialContext(ctx, "tcp", addr) + conn, err := Common.WrapperTcpWithTimeout("tcp", addr, time.Duration(Common.Timeout)*time.Second) if err != nil { return false, err } diff --git a/Plugins/Cassandra.go b/Plugins/Cassandra.go index a1e9298..28f85b0 100644 --- a/Plugins/Cassandra.go +++ b/Plugins/Cassandra.go @@ -3,14 +3,29 @@ package Plugins import ( "context" "fmt" - "github.com/gocql/gocql" - "github.com/shadow1ng/fscan/Common" + "net" "strconv" "strings" "sync" "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凭据 type CassandraCredential struct { Username string @@ -223,6 +238,13 @@ func CassandraConn(ctx context.Context, info *Common.HostInfo, user string, pass cluster.ProtoVersion = 4 cluster.Consistency = gocql.One + // 如果配置了代理,设置自定义Dialer + if Common.Socks5Proxy != "" { + cluster.Dialer = &CassandraProxyDialer{ + timeout: timeout, + } + } + if user != "" || pass != "" { cluster.Authenticator = gocql.PasswordAuthenticator{ Username: user, diff --git a/Plugins/IMAP.go b/Plugins/IMAP.go index db2362d..7cb1d7c 100644 --- a/Plugins/IMAP.go +++ b/Plugins/IMAP.go @@ -5,12 +5,13 @@ import ( "context" "crypto/tls" "fmt" - "github.com/shadow1ng/fscan/Common" "io" "net" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // IMAPCredential 表示一个IMAP凭据 @@ -211,8 +212,7 @@ func IMAPConn(ctx context.Context, info *Common.HostInfo, user string, pass stri // 在协程中尝试连接 go func() { // 先尝试普通连接 - dialer := &net.Dialer{Timeout: timeout} - conn, err := dialer.DialContext(ctx, "tcp", addr) + conn, err := Common.WrapperTcpWithContext(ctx, "tcp", addr) if err == nil { flag, authErr := tryIMAPAuth(conn, user, pass, timeout) conn.Close() @@ -232,14 +232,16 @@ func IMAPConn(ctx context.Context, info *Common.HostInfo, user string, pass stri tlsConfig := &tls.Config{ InsecureSkipVerify: true, } - tlsConn, tlsErr := tls.DialWithDialer(dialer, "tcp", addr, tlsConfig) + + // 使用支持代理的TLS连接 + tlsConn, tlsErr := Common.WrapperTlsWithContext(ctx, "tcp", addr, tlsConfig) if tlsErr != nil { select { case <-ctx.Done(): case resultChan <- struct { success bool err error - }{false, fmt.Errorf("连接失败: %v", tlsErr)}: + }{false, fmt.Errorf("TLS连接失败: %v", tlsErr)}: } return } diff --git a/Plugins/LDAP.go b/Plugins/LDAP.go index e798b49..876b141 100644 --- a/Plugins/LDAP.go +++ b/Plugins/LDAP.go @@ -3,12 +3,12 @@ package Plugins import ( "context" "fmt" - "github.com/go-ldap/ldap/v3" - "github.com/shadow1ng/fscan/Common" - "net" "strings" "sync" "time" + + "github.com/go-ldap/ldap/v3" + "github.com/shadow1ng/fscan/Common" ) // 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) { 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 { return false, err } diff --git a/Plugins/MSSQL.go b/Plugins/MSSQL.go index 22cc244..a3990df 100644 --- a/Plugins/MSSQL.go +++ b/Plugins/MSSQL.go @@ -4,13 +4,25 @@ import ( "context" "database/sql" "fmt" - _ "github.com/denisenkom/go-mssqldb" - "github.com/shadow1ng/fscan/Common" + "net" "strings" "sync" "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凭据 type MssqlCredential struct { Username string @@ -205,7 +217,58 @@ func MssqlConn(ctx context.Context, info *Common.HostInfo, user string, pass str 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) if err != nil { return false, err diff --git a/Plugins/Modbus.go b/Plugins/Modbus.go index 0b8af4e..6241473 100644 --- a/Plugins/Modbus.go +++ b/Plugins/Modbus.go @@ -4,9 +4,9 @@ import ( "context" "encoding/binary" "fmt" - "github.com/shadow1ng/fscan/Common" - "net" "time" + + "github.com/shadow1ng/fscan/Common" ) // ModbusScanResult 表示 Modbus 扫描结果 @@ -77,8 +77,7 @@ func tryModbusScan(ctx context.Context, info *Common.HostInfo, timeoutSeconds in // 在协程中执行扫描 go func() { // 尝试建立连接 - var d net.Dialer - conn, err := d.DialContext(connCtx, "tcp", target) + conn, err := Common.WrapperTcpWithContext(connCtx, "tcp", target) if err != nil { select { case <-connCtx.Done(): diff --git a/Plugins/Mongodb.go b/Plugins/Mongodb.go index 4066a6b..1bf4c87 100644 --- a/Plugins/Mongodb.go +++ b/Plugins/Mongodb.go @@ -3,11 +3,11 @@ package Plugins import ( "context" "fmt" - "github.com/shadow1ng/fscan/Common" "io" - "net" "strings" "time" + + "github.com/shadow1ng/fscan/Common" ) // 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) { 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 := d.DialContext(connCtx, "tcp", address) + conn, err := Common.WrapperTcpWithTimeout("tcp", address, time.Duration(Common.Timeout)*time.Second) if err != nil { return "", fmt.Errorf("连接失败: %v", err) } diff --git a/Plugins/MySQL.go b/Plugins/MySQL.go index c9a3448..6ae7401 100644 --- a/Plugins/MySQL.go +++ b/Plugins/MySQL.go @@ -4,13 +4,38 @@ import ( "context" "database/sql" "fmt" - _ "github.com/go-sql-driver/mysql" - "github.com/shadow1ng/fscan/Common" + "net" "strings" "sync" "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凭据 type MySQLCredential struct { 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 timeout := time.Duration(Common.Timeout) * time.Second - // 构造连接字符串,包含超时设置 - connStr := fmt.Sprintf( - "%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", - username, password, host, port, timeout, - ) + // 检查是否需要使用socks代理 + var connStr string + if Common.Socks5Proxy != "" { + // 注册自定义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 { diff --git a/Plugins/Neo4j.go b/Plugins/Neo4j.go index 1dcd15a..15a41f8 100644 --- a/Plugins/Neo4j.go +++ b/Plugins/Neo4j.go @@ -3,11 +3,12 @@ package Plugins import ( "context" "fmt" - "github.com/neo4j/neo4j-go-driver/v4/neo4j" - "github.com/shadow1ng/fscan/Common" "strings" "sync" "time" + + "github.com/neo4j/neo4j-go-driver/v4/neo4j" + "github.com/shadow1ng/fscan/Common" ) // Neo4jCredential 表示一个Neo4j凭据 @@ -268,6 +269,9 @@ func Neo4jConn(info *Common.HostInfo, user string, pass string) (bool, error) { config := func(c *neo4j.Config) { c.SocketConnectTimeout = timeout c.ConnectionAcquisitionTimeout = timeout + + // 注意:Neo4j驱动可能不支持代理配置 + // 如果需要代理支持,可能需要使用更底层的连接方式 } var driver neo4j.Driver diff --git a/Plugins/POP3.go b/Plugins/POP3.go index 622c50b..4f1b08e 100644 --- a/Plugins/POP3.go +++ b/Plugins/POP3.go @@ -5,11 +5,12 @@ import ( "context" "crypto/tls" "fmt" - "github.com/shadow1ng/fscan/Common" "net" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // POP3Credential 表示一个POP3凭据 @@ -255,12 +256,7 @@ func POP3Conn(ctx context.Context, info *Common.HostInfo, user string, pass stri // 在协程中尝试连接,支持取消 go func() { // 首先尝试普通连接 - dialer := &net.Dialer{ - Timeout: timeout, - // 增加KeepAlive设置,可能有助于处理一些服务器的限制 - KeepAlive: 30 * time.Second, - } - conn, err := dialer.DialContext(ctx, "tcp", addr) + conn, err := Common.WrapperTcpWithTimeout("tcp", addr, timeout) if err == nil { flag, authErr := tryPOP3Auth(conn, user, pass, timeout) conn.Close() @@ -287,7 +283,10 @@ func POP3Conn(ctx context.Context, info *Common.HostInfo, user string, pass stri tlsConfig := &tls.Config{ 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 { select { case <-ctx.Done(): diff --git a/Plugins/Rsync.go b/Plugins/Rsync.go index 8917769..366c1d9 100644 --- a/Plugins/Rsync.go +++ b/Plugins/Rsync.go @@ -3,11 +3,11 @@ package Plugins import ( "context" "fmt" - "github.com/shadow1ng/fscan/Common" - "net" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // RsyncCredential 表示一个Rsync凭据 @@ -212,13 +212,8 @@ func RsyncConn(ctx context.Context, info *Common.HostInfo, user string, pass str host, port := info.Host, info.Ports 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 { return false, "", err } @@ -335,13 +330,11 @@ func RsyncConn(ctx context.Context, info *Common.HostInfo, user string, pass str } // 5. 为每个模块创建新连接尝试认证 - authConn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", host, port)) + authConn, err := Common.WrapperTcpWithTimeout(host, port, timeout) if err != nil { continue } - defer authConn.Close() - - // 重复初始握手 + defer authConn.Close() // 重复初始握手 authConn.SetReadDeadline(time.Now().Add(timeout)) _, err = authConn.Read(buffer) if err != nil { diff --git a/Plugins/SMB2.go b/Plugins/SMB2.go index 0fa6601..3ec987f 100644 --- a/Plugins/SMB2.go +++ b/Plugins/SMB2.go @@ -3,13 +3,13 @@ package Plugins import ( "context" "fmt" - "github.com/shadow1ng/fscan/Common" - "net" "os" "strings" "sync" "time" + "github.com/shadow1ng/fscan/Common" + "github.com/hirochachacha/go-smb2" ) @@ -316,9 +316,8 @@ func trySmb2Credential(ctx context.Context, info *Common.HostInfo, credential Sm // Smb2Con 尝试SMB2连接并进行认证,检查共享访问权限 func Smb2Con(ctx context.Context, info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, shares []string) { - // 建立TCP连接,使用上下文提供的超时控制 - var d net.Dialer - conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:445", info.Host)) + // 建立TCP连接,使用socks代理支持 + conn, err := Common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:445", info.Host), time.Duration(Common.Timeout)*time.Second) if err != nil { return false, fmt.Errorf("连接失败: %v", err), nil } diff --git a/Plugins/SMTP.go b/Plugins/SMTP.go index a03a27c..63f3388 100644 --- a/Plugins/SMTP.go +++ b/Plugins/SMTP.go @@ -3,12 +3,12 @@ package Plugins import ( "context" "fmt" - "github.com/shadow1ng/fscan/Common" - "net" "net/smtp" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // SmtpCredential 表示一个SMTP凭据 @@ -253,11 +253,7 @@ func SmtpConn(info *Common.HostInfo, user string, pass string, timeoutSeconds in addr := fmt.Sprintf("%s:%s", host, port) // 设置连接超时 - dialer := &net.Dialer{ - Timeout: timeout, - } - - conn, err := dialer.Dial("tcp", addr) + conn, err := Common.WrapperTcpWithTimeout("tcp", addr, timeout) if err != nil { return false, err } diff --git a/Plugins/Telnet.go b/Plugins/Telnet.go index e043b60..e917ad7 100644 --- a/Plugins/Telnet.go +++ b/Plugins/Telnet.go @@ -5,12 +5,13 @@ import ( "context" "errors" "fmt" - "github.com/shadow1ng/fscan/Common" "net" "regexp" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/Common" ) // TelnetCredential 表示一个Telnet凭据 @@ -248,9 +249,8 @@ func tryTelnetCredential(ctx context.Context, info *Common.HostInfo, credential // telnetConnWithContext 带上下文的Telnet连接尝试 func telnetConnWithContext(ctx context.Context, info *Common.HostInfo, user, pass string) (bool, error) { - // 创建TCP连接(使用上下文控制) - var d net.Dialer - conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", info.Host, info.Ports)) + // 创建TCP连接(使用支持context的socks代理) + conn, err := Common.WrapperTcpWithContext(ctx, "tcp", fmt.Sprintf("%s:%s", info.Host, info.Ports)) if err != nil { return false, err } diff --git a/Plugins/VNC.go b/Plugins/VNC.go index 8f94d20..8b28d6c 100644 --- a/Plugins/VNC.go +++ b/Plugins/VNC.go @@ -3,11 +3,11 @@ package Plugins import ( "context" "fmt" - "github.com/mitchellh/go-vnc" - "github.com/shadow1ng/fscan/Common" - "net" "sync" "time" + + "github.com/mitchellh/go-vnc" + "github.com/shadow1ng/fscan/Common" ) // 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 // 使用带上下文的TCP连接 - var d net.Dialer - conn, err := d.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", Host, Port)) + conn, err := Common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%s", Host, Port), timeout) if err != nil { return false, err }