diff --git a/pkg/relay/http_client.go b/pkg/relay/http_client.go index 057a5df..f505a5e 100644 --- a/pkg/relay/http_client.go +++ b/pkg/relay/http_client.go @@ -15,6 +15,7 @@ package relay import ( + "context" "crypto/tls" "encoding/base64" "fmt" @@ -24,8 +25,10 @@ import ( "net/http" "regexp" "strings" + "time" "gopacket/internal/build" + "gopacket/pkg/transport" ) // HTTPRelayClient implements ProtocolClient for relaying NTLM auth to HTTP/HTTPS targets. @@ -73,20 +76,22 @@ func (c *HTTPRelayClient) SetPath(path string) { func (c *HTTPRelayClient) InitConnection() error { // Use a custom transport that keeps connections alive for the NTLM handshake. // The entire 3-leg NTLM exchange must happen on the same TCP connection. - transport := &http.Transport{ + tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, DisableKeepAlives: false, // Force single connection reuse for NTLM auth MaxIdleConnsPerHost: 1, - DialContext: (&net.Dialer{ - Timeout: 10 * 1e9, // 10 seconds - }).DialContext, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + return transport.DialContext(ctx, network, addr) + }, } c.httpClient = &http.Client{ - Transport: transport, + Transport: tr, // Don't follow redirects — we need to see the raw 401/302 responses CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse diff --git a/pkg/relay/socks.go b/pkg/relay/socks.go index 38d7ee4..4c425f9 100644 --- a/pkg/relay/socks.go +++ b/pkg/relay/socks.go @@ -447,6 +447,9 @@ func (s *SOCKSServer) handleConnection(conn net.Conn) { func (s *SOCKSServer) handleDNSPassthrough(clientConn net.Conn, host string, port int) { target := fmt.Sprintf("%s:%d", host, port) + // Intentionally uses net.DialTimeout, not transport.DialTimeout: this is + // the outbound leg of our own SOCKS5 server, so routing it through the + // operator's -proxy would double-tunnel. remotConn, err := net.DialTimeout("tcp", target, 10*time.Second) if err != nil { if build.Debug { diff --git a/pkg/relay/winrm_client.go b/pkg/relay/winrm_client.go index 88a0afe..59ad560 100644 --- a/pkg/relay/winrm_client.go +++ b/pkg/relay/winrm_client.go @@ -15,6 +15,7 @@ package relay import ( + "context" "crypto/tls" "encoding/base64" "fmt" @@ -24,8 +25,10 @@ import ( "net/http" "regexp" "strings" + "time" "gopacket/internal/build" + "gopacket/pkg/transport" ) // WinRMRelayClient implements ProtocolClient for relaying NTLM auth to WinRM targets. @@ -50,20 +53,22 @@ func NewWinRMRelayClient(addr string, useTLS bool) *WinRMRelayClient { // InitConnection creates the HTTP client with connection reuse for NTLM handshake. // Implements ProtocolClient. func (c *WinRMRelayClient) InitConnection() error { - transport := &http.Transport{ + tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, DisableKeepAlives: false, // Force single connection reuse for NTLM auth MaxIdleConnsPerHost: 1, - DialContext: (&net.Dialer{ - Timeout: 10 * 1e9, // 10 seconds - }).DialContext, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + return transport.DialContext(ctx, network, addr) + }, } c.httpClient = &http.Client{ - Transport: transport, + Transport: tr, CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, diff --git a/pkg/tds/sqlr.go b/pkg/tds/sqlr.go index fb46edd..c1f1baa 100644 --- a/pkg/tds/sqlr.go +++ b/pkg/tds/sqlr.go @@ -16,9 +16,10 @@ package tds import ( "fmt" - "net" "strings" "time" + + "gopacket/pkg/transport" ) // SQLRInstance represents a discovered SQL Server instance @@ -31,15 +32,10 @@ type SQLRInstance struct { NamedPipe string } -// GetInstances queries the SQL Server Browser service for instances +// GetInstances queries the SQL Server Browser service for instances. +// Fails under -proxy because SQL Browser is UDP and cannot be tunneled. func GetInstances(server string, timeout time.Duration) ([]SQLRInstance, error) { - // Create UDP connection - addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", server, SQLRPort)) - if err != nil { - return nil, err - } - - conn, err := net.DialUDP("udp", nil, addr) + conn, err := transport.DialUDP(fmt.Sprintf("%s:%d", server, SQLRPort)) if err != nil { return nil, err } @@ -66,15 +62,9 @@ func GetInstances(server string, timeout time.Duration) ([]SQLRInstance, error) return parseInstanceResponse(buf[:n]) } -// GetInstancePort queries for a specific instance's port +// GetInstancePort queries for a specific instance's port. Fails under -proxy (UDP). func GetInstancePort(server, instance string, timeout time.Duration) (int, error) { - // Create UDP connection - addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", server, SQLRPort)) - if err != nil { - return 0, err - } - - conn, err := net.DialUDP("udp", nil, addr) + conn, err := transport.DialUDP(fmt.Sprintf("%s:%d", server, SQLRPort)) if err != nil { return 0, err }