mirror of
https://github.com/mandiant/gopacket
synced 2026-06-21 13:57:02 +00:00
relay, tds: route outbound through transport
- pkg/relay/http_client.go, winrm_client.go: swap the http.Transport
DialContext from &net.Dialer{Timeout: 10s}.DialContext to a closure
that calls transport.DialContext. NTLM relay now respects -proxy.
- pkg/relay/socks.go: add a comment on the HTTP DNS passthrough path
explaining why it intentionally uses net.DialTimeout rather than
transport. That path is the outbound leg of our own SOCKS5 server,
so routing it through -proxy would double-tunnel the operator's
proxy through the operator's proxy.
- pkg/tds/sqlr.go: SQL Server Browser discovery (UDP 1434) now uses
transport.DialUDP, which surfaces ErrUDPUnderProxy when a proxy is
configured rather than silently bypassing it.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
+7
-17
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user