Documentation
¶
Overview ¶
keylog.go provides TLS key logging for traffic analysis with Wireshark.
This implements the SSLKEYLOGFILE format that allows Wireshark to decrypt TLS traffic when the key log file is configured in Wireshark's settings.
Usage:
// Automatic: reads from SSLKEYLOGFILE environment variable
// Just set SSLKEYLOGFILE=/path/to/keys.log before running
// Manual: set a specific file
transport.SetKeyLogFile("/path/to/keys.log")
// Custom writer
transport.SetKeyLogWriter(myWriter)
Index ¶
- Constants
- Variables
- func AdditionalTransportParamsForPreset(preset *fingerprint.Preset, ctx context.Context, host string, port int) map[uint64][]byte
- func ApplyLocalAddrControl(dialer *net.Dialer, localAddr string)
- func BuildChromeTransportParams() map[uint64][]byte
- func BuildDialControl(fp *fingerprint.TCPFingerprint, localAddr string) func(network, address string, c syscall.RawConn) error
- func BuildDialerControl(fp *fingerprint.TCPFingerprint) func(network, address string, conn syscall.RawConn) error
- func BuildLocalAddrListenControl(localAddr string) func(network, address string, c syscall.RawConn) error
- func CloseKeyLog() error
- func FormatECHCacheKey(preset, host, port string) string
- func FormatSessionCacheKey(preset, protocol, host, port string) string
- func FormatSessionCacheKeyWithID(sessionId, preset, protocol, host, port string) string
- func GetKeyLogWriter() io.Writer
- func IsConnectionError(err error) bool
- func IsDNSError(err error) bool
- func IsMASQUEProxy(proxyURL string) bool
- func IsProxyError(err error) bool
- func IsProxyNoSpeculative(proxyAddr string) bool
- func IsSOCKS5Proxy(proxyURL string) bool
- func IsSpeculativeTLSError(err error) bool
- func IsTLSError(err error) bool
- func IsTimeout(err error) bool
- func ListenUDPWithLocalAddr(network string, localUDPAddr *net.UDPAddr, localAddr string) (*net.UDPConn, error)
- func MarkProxyNoSpeculative(proxyAddr string)
- func MeasureAndSetInitialRTT(ctx context.Context, host string, port int)
- func MeasureInitialRTT(ctx context.Context, host string, port int) map[uint64][]byte
- func NewKeyLogFileWriter(path string) (io.WriteCloser, error)
- func ResetInitialRTT()
- func SetDialerControl(dialer *net.Dialer, fp *fingerprint.TCPFingerprint)
- func SetKeyLogFile(path string) error
- func SetKeyLogWriter(w io.Writer)
- func SupportsQUIC(proxyURL string) bool
- func WrapError(op, host, port, protocol string, cause error) error
- type ALPNMismatchError
- type ConnStats
- type ErrorCallback
- type HTTP1ConnStats
- type HTTP1Transport
- func NewHTTP1Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) *HTTP1Transport
- func NewHTTP1TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig, ...) *HTTP1Transport
- func NewHTTP1TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig) *HTTP1Transport
- func (t *HTTP1Transport) Close()
- func (t *HTTP1Transport) GetDNSCache() *dns.Cache
- func (t *HTTP1Transport) GetProxy() *ProxyConfig
- func (t *HTTP1Transport) GetSessionCache() utls.ClientSessionCache
- func (t *HTTP1Transport) Refresh()
- func (t *HTTP1Transport) RoundTrip(req *http.Request) (*http.Response, error)
- func (t *HTTP1Transport) RoundTripWithTLSConn(req *http.Request, tlsConn *utls.UConn, host, port string) (*http.Response, error)
- func (t *HTTP1Transport) SetConnectTo(requestHost, connectHost string)
- func (t *HTTP1Transport) SetInsecureSkipVerify(skip bool)
- func (t *HTTP1Transport) SetLocalAddr(addr string)
- func (t *HTTP1Transport) SetProxy(proxy *ProxyConfig)
- func (t *HTTP1Transport) SetSessionCache(cache utls.ClientSessionCache)
- func (t *HTTP1Transport) Stats() map[string]HTTP1ConnStats
- func (t *HTTP1Transport) StreamRoundTrip(req *http.Request) (*http.Response, error)
- type HTTP2Transport
- func NewHTTP2Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) *HTTP2Transport
- func NewHTTP2TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig, ...) *HTTP2Transport
- func NewHTTP2TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig) *HTTP2Transport
- func (t *HTTP2Transport) Close()
- func (t *HTTP2Transport) Connect(ctx context.Context, host, port string) error
- func (t *HTTP2Transport) GetConnectionUseCount(host, port string) int64
- func (t *HTTP2Transport) GetDNSCache() *dns.Cache
- func (t *HTTP2Transport) GetSessionCache() utls.ClientSessionCache
- func (t *HTTP2Transport) IsConnectionReused(host, port string) bool
- func (t *HTTP2Transport) Refresh()
- func (t *HTTP2Transport) RoundTrip(req *http.Request) (*http.Response, error)
- func (t *HTTP2Transport) SetConnectTo(requestHost, connectHost string)
- func (t *HTTP2Transport) SetECHConfig(echConfig []byte)
- func (t *HTTP2Transport) SetECHConfigDomain(domain string)
- func (t *HTTP2Transport) SetInsecureSkipVerify(skip bool)
- func (t *HTTP2Transport) SetLocalAddr(addr string)
- func (t *HTTP2Transport) SetSessionCache(cache utls.ClientSessionCache)
- func (t *HTTP2Transport) Stats() map[string]ConnStats
- type HTTP3Stats
- type HTTP3Transport
- func NewHTTP3Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) (*HTTP3Transport, error)
- func NewHTTP3TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig, ...) (*HTTP3Transport, error)
- func NewHTTP3TransportWithMASQUE(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig, ...) (*HTTP3Transport, error)
- func NewHTTP3TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig) (*HTTP3Transport, error)
- func NewHTTP3TransportWithTransportConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, config *TransportConfig) (*HTTP3Transport, error)
- func (t *HTTP3Transport) Close() error
- func (t *HTTP3Transport) Connect(ctx context.Context, host, port string) error
- func (t *HTTP3Transport) GetDNSCache() *dns.Cache
- func (t *HTTP3Transport) GetDialCount() int64
- func (t *HTTP3Transport) GetECHConfigCache() map[string][]byte
- func (t *HTTP3Transport) GetRequestCount() int64
- func (t *HTTP3Transport) GetSessionCache() tls.ClientSessionCache
- func (t *HTTP3Transport) IsConnectionReused(host string) bool
- func (t *HTTP3Transport) Refresh() error
- func (t *HTTP3Transport) RoundTrip(req *http.Request) (*http.Response, error)
- func (t *HTTP3Transport) SetConnectTo(requestHost, connectHost string)
- func (t *HTTP3Transport) SetDisableECH(disable bool)
- func (t *HTTP3Transport) SetECHConfig(echConfig []byte)
- func (t *HTTP3Transport) SetECHConfigCache(configs map[string][]byte)
- func (t *HTTP3Transport) SetECHConfigDomain(domain string)
- func (t *HTTP3Transport) SetInsecureSkipVerify(skip bool)
- func (t *HTTP3Transport) SetLocalAddr(addr string)
- func (t *HTTP3Transport) SetSessionCache(cache tls.ClientSessionCache)
- func (t *HTTP3Transport) Stats() HTTP3Stats
- type HTTPError
- type PersistableSessionCache
- func (c *PersistableSessionCache) Clear()
- func (c *PersistableSessionCache) Count() int
- func (c *PersistableSessionCache) Export() (map[string]TLSSessionState, error)
- func (c *PersistableSessionCache) Get(sessionKey string) (*tls.ClientSessionState, bool)
- func (c *PersistableSessionCache) GetSessionIdentifier() string
- func (c *PersistableSessionCache) Import(sessions map[string]TLSSessionState) error
- func (c *PersistableSessionCache) Put(sessionKey string, cs *tls.ClientSessionState)
- func (c *PersistableSessionCache) SetBackend(backend SessionCacheBackend, preset, protocol string, ...)
- func (c *PersistableSessionCache) SetErrorCallback(callback ErrorCallback)
- func (c *PersistableSessionCache) SetSessionIdentifier(sessionId string)
- type Protocol
- type ProxyConfig
- type RedirectInfo
- type Request
- type Response
- type SessionCacheBackend
- type SpeculativeConn
- func (c *SpeculativeConn) Close() error
- func (c *SpeculativeConn) LocalAddr() net.Addr
- func (c *SpeculativeConn) Read(b []byte) (n int, err error)
- func (c *SpeculativeConn) RemoteAddr() net.Addr
- func (c *SpeculativeConn) SetDeadline(t time.Time) error
- func (c *SpeculativeConn) SetReadDeadline(t time.Time) error
- func (c *SpeculativeConn) SetWriteDeadline(t time.Time) error
- func (c *SpeculativeConn) Write(b []byte) (n int, err error)
- type SpeculativeTLSError
- type StreamResponse
- func (r *StreamResponse) Close() error
- func (r *StreamResponse) IsSuccess() bool
- func (r *StreamResponse) Lines() <-chan string
- func (r *StreamResponse) Read(p []byte) (n int, err error)
- func (r *StreamResponse) ReadAll() ([]byte, error)
- func (r *StreamResponse) ReadChunk(size int) ([]byte, error)
- func (r *StreamResponse) Scanner() *bufio.Scanner
- type TLSSessionState
- type Transport
- func (t *Transport) ClearProtocolCache()
- func (t *Transport) Close()
- func (t *Transport) Do(ctx context.Context, req *Request) (*Response, error)
- func (t *Transport) DoStream(ctx context.Context, req *Request) (*StreamResponse, error)
- func (t *Transport) GetConfig() *TransportConfig
- func (t *Transport) GetDNSCache() *dns.Cache
- func (t *Transport) GetHTTP1Transport() *HTTP1Transport
- func (t *Transport) GetHTTP2Transport() *HTTP2Transport
- func (t *Transport) GetHTTP3Transport() *HTTP3Transport
- func (t *Transport) GetHeaderOrder() []string
- func (t *Transport) Refresh()
- func (t *Transport) RefreshWithProtocol(p Protocol)
- func (t *Transport) SetConnectTo(requestHost, connectHost string)
- func (t *Transport) SetDisableECH(disable bool)
- func (t *Transport) SetECHConfig(echConfig []byte)
- func (t *Transport) SetECHConfigDomain(domain string)
- func (t *Transport) SetHeaderOrder(order []string)
- func (t *Transport) SetInsecureSkipVerify(skip bool)
- func (t *Transport) SetPreset(presetName string)
- func (t *Transport) SetProtocol(p Protocol)
- func (t *Transport) SetProxy(proxy *ProxyConfig)
- func (t *Transport) SetSessionIdentifier(sessionId string)
- func (t *Transport) SetTimeout(timeout time.Duration)
- func (t *Transport) Stats() map[string]interface{}
- type TransportConfig
- type TransportError
- func NewConnectionError(op, host, port, protocol string, cause error) *TransportError
- func NewDNSError(host string, cause error) *TransportError
- func NewProtocolError(host, port, protocol string, cause error) *TransportError
- func NewProxyError(op, host, port string, cause error) *TransportError
- func NewRequestError(op, host, port, protocol string, cause error) *TransportError
- func NewTLSError(op, host, port, protocol string, cause error) *TransportError
- func NewTimeoutError(op, host, port, protocol string, cause error) *TransportError
Constants ¶
const ( CacheKeyPrefixSession = "httpcloak:sessions" CacheKeyPrefixECH = "httpcloak:ech" )
CacheKeyPrefix constants for distributed cache
const TLSSessionCacheMaxSize = 32
TLSSessionCacheMaxSize is the maximum number of sessions to cache Matches the size used by pool/pool.go for LRU session cache
const TLSSessionMaxAge = 24 * time.Hour
TLSSessionMaxAge is the maximum age for TLS sessions (24 hours) TLS session tickets typically expire after 24-48 hours
Variables ¶
var ( // ErrConnection represents connection-level errors ErrConnection = errors.New("connection error") // ErrTLS represents TLS/SSL related errors ErrTLS = errors.New("TLS error") // ErrDNS represents DNS resolution errors ErrDNS = errors.New("DNS error") // ErrTimeout represents timeout errors ErrTimeout = errors.New("timeout error") // ErrProxy represents proxy-related errors ErrProxy = errors.New("proxy error") // ErrProtocol represents protocol negotiation errors ErrProtocol = errors.New("protocol error") // ErrRequest represents request-level errors ErrRequest = errors.New("request error") // ErrResponse represents response-level errors ErrResponse = errors.New("response error") // ErrClosed represents errors when transport is closed ErrClosed = errors.New("transport closed") // ErrALPNMismatch represents ALPN protocol negotiation mismatch ErrALPNMismatch = errors.New("ALPN mismatch") )
Error categories for better error handling
Functions ¶
func AdditionalTransportParamsForPreset ¶ added in v1.6.5
func AdditionalTransportParamsForPreset(preset *fingerprint.Preset, ctx context.Context, host string, port int) map[uint64][]byte
AdditionalTransportParamsForPreset returns per-connection additional QUIC transport params appropriate for the given preset. For Chrome presets, returns Chrome-specific params (google_connection_options, google_version, version_information, initial_rtt). For non-Chrome presets (e.g. Firefox), returns nil so these Chrome-specific params are not sent. If ctx/host/port are provided and the preset is Chrome, includes measured RTT; otherwise uses default 100ms.
func ApplyLocalAddrControl ¶ added in v1.6.6
ApplyLocalAddrControl wires freebind onto a net.Dialer that's binding to localAddr. Composes with any pre-existing dialer.Control (e.g. TCP fingerprint) so callers don't have to think about ordering. localAddr == "" is a no-op so the same wiring is safe to call unconditionally.
Why we only freebind when localAddr is set: most users never touch LocalAddr, and silently turning freebind on for them would be surprising (it changes the failure semantics of bind() — without it you'd see EADDRNOTAVAIL early; with it the kernel happily accepts non-local addresses and you only discover the misconfig later when packets vanish). Opt-in via LocalAddr keeps the principle of least surprise.
func BuildChromeTransportParams ¶ added in v1.6.1
BuildChromeTransportParams creates Chrome-like QUIC transport parameters. Exported so pool and other packages can reference the canonical set.
func BuildDialControl ¶ added in v1.6.6
func BuildDialControl(fp *fingerprint.TCPFingerprint, localAddr string) func(network, address string, c syscall.RawConn) error
BuildDialControl returns a Dialer.Control callback that chains TCP fingerprint sockopts with freebind (when localAddr is set). Useful when the dialer is owned by another package (proxy/socks5_tcp) that cannot import this package — pass the result via that package's Control field. Returns nil if neither concern applies (no fingerprint, no localAddr).
func BuildDialerControl ¶ added in v1.6.1
func BuildDialerControl(fp *fingerprint.TCPFingerprint) func(network, address string, conn syscall.RawConn) error
BuildDialerControl returns a Dialer.Control function that applies TCP/IP fingerprint settings to the raw socket before connect(). This sets TTL, MSS, window size, and DF bit in the SYN packet to match the target OS. Returns nil if no fingerprint is configured (zero TTL = no-op).
func BuildLocalAddrListenControl ¶ added in v1.6.6
func BuildLocalAddrListenControl(localAddr string) func(network, address string, c syscall.RawConn) error
BuildLocalAddrListenControl returns a ListenConfig.Control callback that applies freebind to a UDP socket about to bind to localAddr. Returns nil when localAddr is empty so callers can plug it straight into a net.ListenConfig literal without conditional code.
func CloseKeyLog ¶ added in v1.6.0
func CloseKeyLog() error
CloseKeyLog closes the global key log writer if it was opened by this package. This should be called on application shutdown for clean resource release.
func FormatECHCacheKey ¶ added in v1.5.8
FormatECHCacheKey creates a cache key for ECH configs. Format: httpcloak:ech:{preset}:{host}:{port}
func FormatSessionCacheKey ¶ added in v1.5.8
FormatSessionCacheKey creates a cache key for TLS sessions. Format: httpcloak:sessions:{preset}:{protocol}:{host}:{port}
func FormatSessionCacheKeyWithID ¶ added in v1.5.8
FormatSessionCacheKeyWithID creates a cache key for TLS sessions that includes a session identifier. This is used when sessions need to be isolated per proxy/session (e.g., different upstream proxies). Format: httpcloak:sessions:{sessionId}:{preset}:{protocol}:{host}:{port}
func GetKeyLogWriter ¶ added in v1.6.0
GetKeyLogWriter returns the global key log writer, or nil if not configured. This is used internally by transport code to set tls.Config.KeyLogWriter.
func IsConnectionError ¶
IsConnectionError checks if an error is a connection error
func IsMASQUEProxy ¶ added in v1.5.2
IsMASQUEProxy checks if the proxy URL should use MASQUE protocol (exported version). Returns true for masque:// scheme or known MASQUE providers with https://
func IsProxyError ¶
IsProxyError checks if an error is a proxy error
func IsProxyNoSpeculative ¶ added in v1.6.0
IsProxyNoSpeculative checks if a proxy address has been recorded as not supporting speculative TLS.
func IsSOCKS5Proxy ¶ added in v1.5.2
IsSOCKS5Proxy checks if the proxy URL is a SOCKS5 proxy (exported version)
func IsSpeculativeTLSError ¶ added in v1.6.0
IsSpeculativeTLSError checks if an error is a SpeculativeTLSError. Useful for deciding whether to retry with normal flow.
func ListenUDPWithLocalAddr ¶ added in v1.6.6
func ListenUDPWithLocalAddr(network string, localUDPAddr *net.UDPAddr, localAddr string) (*net.UDPConn, error)
ListenUDPWithLocalAddr opens a UDP socket on network bound to localUDPAddr. When localAddr is non-empty, freebind is applied first so the bind succeeds for addresses that aren't configured on any local interface (the IPv6 prefix rotation case). When localAddr is empty this degrades to a plain net.ListenUDP — no behaviour change for callers that don't use the feature.
Returns *net.UDPConn (not net.PacketConn) so the H3 path can plug it straight into quic.Transport without an extra type assertion at the call site.
func MarkProxyNoSpeculative ¶ added in v1.6.0
func MarkProxyNoSpeculative(proxyAddr string)
MarkProxyNoSpeculative records that a proxy address does not support speculative TLS. Future connections to this proxy will use blocking CONNECT flow automatically.
func MeasureAndSetInitialRTT ¶ added in v1.6.1
MeasureAndSetInitialRTT measures TCP RTT and sets the global transport params. Deprecated: Use MeasureInitialRTT and pass params via quic.Config.AdditionalTransportParameters instead.
func MeasureInitialRTT ¶ added in v1.6.5
MeasureInitialRTT measures TCP RTT to host:port and returns Chrome transport params with the measured RTT. Called once per process (cached); subsequent calls return the cached params. If measurement fails, returns params with default 100ms RTT.
func NewKeyLogFileWriter ¶ added in v1.6.0
func NewKeyLogFileWriter(path string) (io.WriteCloser, error)
NewKeyLogFileWriter creates a new key log writer for a specific file. This is useful for session-level key logging that doesn't affect the global writer. The caller is responsible for closing the returned writer.
func ResetInitialRTT ¶ added in v1.6.1
func ResetInitialRTT()
ResetInitialRTT allows re-measurement for new sessions/hosts.
func SetDialerControl ¶ added in v1.6.1
func SetDialerControl(dialer *net.Dialer, fp *fingerprint.TCPFingerprint)
SetDialerControl configures a net.Dialer to apply TCP/IP fingerprint settings on every new connection. Safe to call with a nil or zero-value fingerprint (no-op in that case).
func SetKeyLogFile ¶ added in v1.6.0
SetKeyLogFile sets the global key log file path. This overrides the SSLKEYLOGFILE environment variable. Pass empty string to disable key logging.
func SetKeyLogWriter ¶ added in v1.6.0
SetKeyLogWriter sets a custom key log writer. This allows writing to any io.Writer (e.g., a buffer for testing). Pass nil to disable key logging.
func SupportsQUIC ¶ added in v1.5.2
SupportsQUIC checks if the proxy URL supports QUIC/HTTP3 tunneling. Returns true for SOCKS5 (UDP relay) or MASQUE (CONNECT-UDP) proxies.
Types ¶
type ALPNMismatchError ¶ added in v1.5.10
type ALPNMismatchError struct {
Expected string // Expected protocol (e.g., "h2")
Negotiated string // Actually negotiated protocol (e.g., "http/1.1")
TLSConn *utls.UConn // The TLS connection (caller should close if not reusing)
Host string // Target host
Port string // Target port
}
ALPNMismatchError is returned when ALPN negotiates a different protocol than expected. It carries the TLS connection so it can be reused for the negotiated protocol.
func (*ALPNMismatchError) Error ¶ added in v1.5.10
func (e *ALPNMismatchError) Error() string
func (*ALPNMismatchError) Unwrap ¶ added in v1.5.10
func (e *ALPNMismatchError) Unwrap() error
type ConnStats ¶
type ConnStats struct {
Host string
CreatedAt time.Time
LastUsedAt time.Time
UseCount int64
Age time.Duration
IdleTime time.Duration
IsReused bool
SessionResumed bool // True if TLS session was resumed
TLSVersion uint16 // TLS version (e.g., 0x0304 for TLS 1.3)
CipherSuite uint16 // Negotiated cipher suite
}
ConnStats contains connection statistics
type ErrorCallback ¶ added in v1.5.8
ErrorCallback is called when a backend operation fails. This allows users to handle errors from async backend operations.
type HTTP1ConnStats ¶
type HTTP1ConnStats struct {
IdleConns int
TotalUseCount int64
OldestCreated time.Time
NewestLastUsed time.Time
}
HTTP1ConnStats contains HTTP/1.1 connection statistics
type HTTP1Transport ¶
type HTTP1Transport struct {
// contains filtered or unexported fields
}
HTTP1Transport is a custom HTTP/1.1 transport with uTLS fingerprinting and connection pooling with keep-alive support
func NewHTTP1Transport ¶
func NewHTTP1Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) *HTTP1Transport
NewHTTP1Transport creates a new HTTP/1.1 transport with uTLS
func NewHTTP1TransportWithConfig ¶ added in v1.5.2
func NewHTTP1TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig, config *TransportConfig) *HTTP1Transport
NewHTTP1TransportWithConfig creates a new HTTP/1.1 transport with proxy and config
func NewHTTP1TransportWithProxy ¶
func NewHTTP1TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig) *HTTP1Transport
NewHTTP1TransportWithProxy creates a new HTTP/1.1 transport with optional proxy
func (*HTTP1Transport) GetDNSCache ¶
func (t *HTTP1Transport) GetDNSCache() *dns.Cache
GetDNSCache returns the DNS cache
func (*HTTP1Transport) GetProxy ¶ added in v1.5.8
func (t *HTTP1Transport) GetProxy() *ProxyConfig
GetProxy returns the current proxy configuration
func (*HTTP1Transport) GetSessionCache ¶ added in v1.5.5
func (t *HTTP1Transport) GetSessionCache() utls.ClientSessionCache
GetSessionCache returns the TLS session cache
func (*HTTP1Transport) Refresh ¶ added in v1.5.10
func (t *HTTP1Transport) Refresh()
Refresh closes all connections but keeps the TLS session cache intact. This simulates a browser page refresh - new TCP connections but TLS resumption.
func (*HTTP1Transport) RoundTripWithTLSConn ¶ added in v1.5.10
func (t *HTTP1Transport) RoundTripWithTLSConn(req *http.Request, tlsConn *utls.UConn, host, port string) (*http.Response, error)
RoundTripWithTLSConn performs an HTTP/1.1 request using an existing TLS connection. This is used when ALPN negotiation results in HTTP/1.1 instead of HTTP/2, allowing the TLS connection to be reused instead of creating a new one. The connection will be closed after the request (not pooled) since it came from H2 transport.
func (*HTTP1Transport) SetConnectTo ¶ added in v1.5.2
func (t *HTTP1Transport) SetConnectTo(requestHost, connectHost string)
SetConnectTo sets a host mapping for domain fronting
func (*HTTP1Transport) SetInsecureSkipVerify ¶
func (t *HTTP1Transport) SetInsecureSkipVerify(skip bool)
SetInsecureSkipVerify sets whether to skip TLS verification
func (*HTTP1Transport) SetLocalAddr ¶ added in v1.6.0
func (t *HTTP1Transport) SetLocalAddr(addr string)
SetLocalAddr sets the local IP address for outgoing connections
func (*HTTP1Transport) SetProxy ¶ added in v1.5.8
func (t *HTTP1Transport) SetProxy(proxy *ProxyConfig)
SetProxy changes the proxy configuration and closes all existing connections HTTP/1.1 connections are short-lived, but we close idle ones for cleanliness
func (*HTTP1Transport) SetSessionCache ¶ added in v1.5.5
func (t *HTTP1Transport) SetSessionCache(cache utls.ClientSessionCache)
SetSessionCache sets the TLS session cache
func (*HTTP1Transport) Stats ¶
func (t *HTTP1Transport) Stats() map[string]HTTP1ConnStats
Stats returns transport statistics
func (*HTTP1Transport) StreamRoundTrip ¶ added in v1.5.3
StreamRoundTrip performs an HTTP request for streaming - connection is NOT pooled The connection will be closed when the response body is closed
type HTTP2Transport ¶
type HTTP2Transport struct {
// contains filtered or unexported fields
}
HTTP2Transport is a custom HTTP/2 transport with uTLS fingerprinting and proper connection reuse
func NewHTTP2Transport ¶
func NewHTTP2Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) *HTTP2Transport
NewHTTP2Transport creates a new HTTP/2 transport with uTLS
func NewHTTP2TransportWithConfig ¶ added in v1.5.2
func NewHTTP2TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig, config *TransportConfig) *HTTP2Transport
NewHTTP2TransportWithConfig creates a new HTTP/2 transport with proxy and advanced config
func NewHTTP2TransportWithProxy ¶
func NewHTTP2TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxy *ProxyConfig) *HTTP2Transport
NewHTTP2TransportWithProxy creates a new HTTP/2 transport with optional proxy support
func (*HTTP2Transport) Connect ¶ added in v1.0.11
func (t *HTTP2Transport) Connect(ctx context.Context, host, port string) error
Connect establishes a connection to the host without making a request. This is used for protocol racing - the first protocol to connect wins.
func (*HTTP2Transport) GetConnectionUseCount ¶
func (t *HTTP2Transport) GetConnectionUseCount(host, port string) int64
GetConnectionUseCount returns how many times a connection has been used
func (*HTTP2Transport) GetDNSCache ¶
func (t *HTTP2Transport) GetDNSCache() *dns.Cache
GetDNSCache returns the DNS cache
func (*HTTP2Transport) GetSessionCache ¶ added in v1.5.5
func (t *HTTP2Transport) GetSessionCache() utls.ClientSessionCache
GetSessionCache returns the TLS session cache
func (*HTTP2Transport) IsConnectionReused ¶
func (t *HTTP2Transport) IsConnectionReused(host, port string) bool
IsConnectionReused checks if the connection for a host will be reused Returns true if a usable connection already exists in the pool
func (*HTTP2Transport) Refresh ¶ added in v1.5.10
func (t *HTTP2Transport) Refresh()
Refresh closes all connections but keeps the TLS session cache intact. This simulates a browser page refresh - new TCP connections but TLS resumption.
func (*HTTP2Transport) SetConnectTo ¶ added in v1.5.2
func (t *HTTP2Transport) SetConnectTo(requestHost, connectHost string)
SetConnectTo sets a host mapping for domain fronting
func (*HTTP2Transport) SetECHConfig ¶ added in v1.5.3
func (t *HTTP2Transport) SetECHConfig(echConfig []byte)
SetECHConfig sets a custom ECH configuration
func (*HTTP2Transport) SetECHConfigDomain ¶ added in v1.5.3
func (t *HTTP2Transport) SetECHConfigDomain(domain string)
SetECHConfigDomain sets a domain to fetch ECH config from
func (*HTTP2Transport) SetInsecureSkipVerify ¶ added in v1.5.8
func (t *HTTP2Transport) SetInsecureSkipVerify(skip bool)
SetInsecureSkipVerify sets whether to skip TLS certificate verification
func (*HTTP2Transport) SetLocalAddr ¶ added in v1.6.0
func (t *HTTP2Transport) SetLocalAddr(addr string)
SetLocalAddr sets the local IP address for outgoing connections
func (*HTTP2Transport) SetSessionCache ¶ added in v1.5.5
func (t *HTTP2Transport) SetSessionCache(cache utls.ClientSessionCache)
SetSessionCache sets the TLS session cache
func (*HTTP2Transport) Stats ¶
func (t *HTTP2Transport) Stats() map[string]ConnStats
Stats returns transport statistics
type HTTP3Stats ¶
type HTTP3Stats struct {
RequestCount int64
DialCount int64 // Number of new connections created
Reusing bool // True if connections are being reused
}
HTTP3Stats contains HTTP/3 transport statistics
type HTTP3Transport ¶
type HTTP3Transport struct {
// contains filtered or unexported fields
}
HTTP3Transport is an HTTP/3 transport with proper QUIC connection reuse http3.Transport handles connection pooling internally - we just provide DNS resolution
func NewHTTP3Transport ¶
func NewHTTP3Transport(preset *fingerprint.Preset, dnsCache *dns.Cache) (*HTTP3Transport, error)
NewHTTP3Transport creates a new HTTP/3 transport
func NewHTTP3TransportWithConfig ¶ added in v1.5.2
func NewHTTP3TransportWithConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig, config *TransportConfig) (*HTTP3Transport, error)
NewHTTP3TransportWithConfig creates a new HTTP/3 transport with SOCKS5 proxy and advanced config
func NewHTTP3TransportWithMASQUE ¶ added in v1.5.2
func NewHTTP3TransportWithMASQUE(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig, config *TransportConfig) (*HTTP3Transport, error)
NewHTTP3TransportWithMASQUE creates a new HTTP/3 transport with MASQUE proxy support. MASQUE allows HTTP/3 (QUIC) traffic to be tunneled through an HTTP/3 proxy using the CONNECT-UDP method defined in RFC 9298.
func NewHTTP3TransportWithProxy ¶ added in v1.5.2
func NewHTTP3TransportWithProxy(preset *fingerprint.Preset, dnsCache *dns.Cache, proxyConfig *ProxyConfig) (*HTTP3Transport, error)
NewHTTP3TransportWithProxy creates a new HTTP/3 transport with SOCKS5 proxy support Only SOCKS5 proxies support UDP relay needed for QUIC/HTTP3
func NewHTTP3TransportWithTransportConfig ¶ added in v1.5.2
func NewHTTP3TransportWithTransportConfig(preset *fingerprint.Preset, dnsCache *dns.Cache, config *TransportConfig) (*HTTP3Transport, error)
NewHTTP3TransportWithTransportConfig creates a new HTTP/3 transport with advanced config
func (*HTTP3Transport) Close ¶
func (t *HTTP3Transport) Close() error
Close shuts down the transport and all connections
func (*HTTP3Transport) Connect ¶ added in v1.0.11
func (t *HTTP3Transport) Connect(ctx context.Context, host, port string) error
Connect establishes a QUIC connection to the host without making a request. This is used for protocol racing - the first protocol to connect wins.
func (*HTTP3Transport) GetDNSCache ¶
func (t *HTTP3Transport) GetDNSCache() *dns.Cache
GetDNSCache returns the DNS cache
func (*HTTP3Transport) GetDialCount ¶
func (t *HTTP3Transport) GetDialCount() int64
GetDialCount returns the number of new connections created
func (*HTTP3Transport) GetECHConfigCache ¶ added in v1.5.6
func (t *HTTP3Transport) GetECHConfigCache() map[string][]byte
GetECHConfigCache returns all cached ECH configs This is used for session persistence - ECH configs must be saved alongside TLS session tickets to ensure proper session resumption
func (*HTTP3Transport) GetRequestCount ¶
func (t *HTTP3Transport) GetRequestCount() int64
GetRequestCount returns the total number of requests made
func (*HTTP3Transport) GetSessionCache ¶ added in v1.5.5
func (t *HTTP3Transport) GetSessionCache() tls.ClientSessionCache
GetSessionCache returns the TLS session cache
func (*HTTP3Transport) IsConnectionReused ¶
func (t *HTTP3Transport) IsConnectionReused(host string) bool
IsConnectionReused returns true if requests > dials (meaning reuse happened)
func (*HTTP3Transport) Refresh ¶ added in v1.5.10
func (t *HTTP3Transport) Refresh() error
Refresh closes all QUIC connections but keeps the TLS session cache intact. This simulates a browser page refresh - new QUIC connections but TLS resumption.
func (*HTTP3Transport) SetConnectTo ¶ added in v1.5.2
func (t *HTTP3Transport) SetConnectTo(requestHost, connectHost string)
SetConnectTo sets a host mapping for domain fronting
func (*HTTP3Transport) SetDisableECH ¶ added in v1.6.0
func (t *HTTP3Transport) SetDisableECH(disable bool)
SetDisableECH disables ECH (Encrypted Client Hello) lookup for faster first request ECH is an optional privacy feature - disabling it saves ~15-20ms on first connection
func (*HTTP3Transport) SetECHConfig ¶ added in v1.5.2
func (t *HTTP3Transport) SetECHConfig(echConfig []byte)
SetECHConfig sets a custom ECH configuration
func (*HTTP3Transport) SetECHConfigCache ¶ added in v1.5.6
func (t *HTTP3Transport) SetECHConfigCache(configs map[string][]byte)
SetECHConfigCache imports ECH configs from session persistence This should be called before importing TLS sessions to ensure the correct ECH config is used when resuming connections
func (*HTTP3Transport) SetECHConfigDomain ¶ added in v1.5.2
func (t *HTTP3Transport) SetECHConfigDomain(domain string)
SetECHConfigDomain sets a domain to fetch ECH config from
func (*HTTP3Transport) SetInsecureSkipVerify ¶ added in v1.5.8
func (t *HTTP3Transport) SetInsecureSkipVerify(skip bool)
SetInsecureSkipVerify sets whether to skip TLS certificate verification
func (*HTTP3Transport) SetLocalAddr ¶ added in v1.6.0
func (t *HTTP3Transport) SetLocalAddr(addr string)
SetLocalAddr sets the local IP address for outgoing connections
func (*HTTP3Transport) SetSessionCache ¶ added in v1.5.5
func (t *HTTP3Transport) SetSessionCache(cache tls.ClientSessionCache)
SetSessionCache sets the TLS session cache
func (*HTTP3Transport) Stats ¶
func (t *HTTP3Transport) Stats() HTTP3Stats
Stats returns transport statistics
type HTTPError ¶
HTTPError represents an HTTP-level error (4xx, 5xx responses)
func NewHTTPError ¶
NewHTTPError creates an HTTP error from status code
func (*HTTPError) IsClientError ¶
IsClientError returns true for 4xx errors
func (*HTTPError) IsRetryable ¶
IsRetryable returns true for errors that should be retried
func (*HTTPError) IsServerError ¶
IsServerError returns true for 5xx errors
type PersistableSessionCache ¶ added in v1.5.5
type PersistableSessionCache struct {
// contains filtered or unexported fields
}
PersistableSessionCache implements tls.ClientSessionCache with export/import capabilities for session persistence and LRU eviction. Optionally supports a distributed backend for cross-instance session sharing.
func NewPersistableSessionCache ¶ added in v1.5.5
func NewPersistableSessionCache() *PersistableSessionCache
NewPersistableSessionCache creates a new persistable session cache
func NewPersistableSessionCacheWithBackend ¶ added in v1.5.8
func NewPersistableSessionCacheWithBackend(backend SessionCacheBackend, preset, protocol string, errorCallback ErrorCallback) *PersistableSessionCache
NewPersistableSessionCacheWithBackend creates a session cache with a distributed backend. The preset and protocol are used to generate cache keys for the backend. Protocol should be one of: "h1", "h2", "h3" The errorCallback is optional and will be called when backend operations fail.
func (*PersistableSessionCache) Clear ¶ added in v1.5.5
func (c *PersistableSessionCache) Clear()
Clear removes all cached sessions
func (*PersistableSessionCache) Count ¶ added in v1.5.5
func (c *PersistableSessionCache) Count() int
Count returns the number of cached sessions
func (*PersistableSessionCache) Export ¶ added in v1.5.5
func (c *PersistableSessionCache) Export() (map[string]TLSSessionState, error)
Export serializes all TLS sessions for persistence Returns a map of session keys to serialized TLS session state
func (*PersistableSessionCache) Get ¶ added in v1.5.5
func (c *PersistableSessionCache) Get(sessionKey string) (*tls.ClientSessionState, bool)
Get implements tls.ClientSessionCache. If a backend is configured, it will also check the backend on local cache miss.
func (*PersistableSessionCache) GetSessionIdentifier ¶ added in v1.5.8
func (c *PersistableSessionCache) GetSessionIdentifier() string
GetSessionIdentifier returns the current session identifier.
func (*PersistableSessionCache) Import ¶ added in v1.5.5
func (c *PersistableSessionCache) Import(sessions map[string]TLSSessionState) error
Import loads TLS sessions from serialized state Sessions older than TLSSessionMaxAge are skipped
func (*PersistableSessionCache) Put ¶ added in v1.5.5
func (c *PersistableSessionCache) Put(sessionKey string, cs *tls.ClientSessionState)
Put implements tls.ClientSessionCache. If a backend is configured, it will also store the session in the backend.
func (*PersistableSessionCache) SetBackend ¶ added in v1.5.8
func (c *PersistableSessionCache) SetBackend(backend SessionCacheBackend, preset, protocol string, errorCallback ErrorCallback)
SetBackend configures a distributed cache backend for this session cache. This allows setting the backend after construction.
func (*PersistableSessionCache) SetErrorCallback ¶ added in v1.5.8
func (c *PersistableSessionCache) SetErrorCallback(callback ErrorCallback)
SetErrorCallback sets the callback for backend errors.
func (*PersistableSessionCache) SetSessionIdentifier ¶ added in v1.5.8
func (c *PersistableSessionCache) SetSessionIdentifier(sessionId string)
SetSessionIdentifier sets an optional session identifier for cache key isolation. When set, cache keys will include this identifier to prevent TLS session sharing across different proxy configurations (e.g., when using different upstream proxies). This is useful in distributed scenarios where different "sessions" should have isolated TLS session caches even when targeting the same host.
type ProxyConfig ¶
type ProxyConfig struct {
URL string // Proxy URL (e.g., "http://proxy:8080" or "http://user:pass@proxy:8080")
Username string // Proxy username (optional, can also be in URL)
Password string // Proxy password (optional, can also be in URL)
// TCPProxy is the proxy URL for TCP-based protocols (HTTP/1.1 and HTTP/2)
// When set, overrides URL for TCP transports
TCPProxy string
// UDPProxy is the proxy URL for UDP-based protocols (HTTP/3 via MASQUE)
// When set, overrides URL for UDP transports
UDPProxy string
}
ProxyConfig contains proxy server configuration
type RedirectInfo ¶ added in v1.5.1
type RedirectInfo struct {
StatusCode int
URL string
Headers map[string][]string // Multi-value headers
}
RedirectInfo contains information about a redirect response
type Request ¶
type Request struct {
Method string
URL string
Headers map[string][]string // Multi-value headers (matches http.Header)
Body []byte
BodyReader io.Reader // For streaming uploads - used instead of Body if set
Timeout time.Duration
// TLSOnly is a per-request override for TLS-only mode.
// When set to true, preset HTTP headers are NOT applied - only TLS fingerprinting is used.
// When nil, the transport's TLSOnly setting is used.
// This is useful for LocalProxy where each request can have different TLS-only settings
// via the X-HTTPCloak-TlsOnly header.
TLSOnly *bool
}
Request represents an HTTP request
type Response ¶
type Response struct {
StatusCode int
Headers map[string][]string // Multi-value headers (matches http.Header)
Body io.ReadCloser // Streaming body - call Close() when done
FinalURL string
Timing *protocol.Timing
Protocol string // "h1", "h2", or "h3"
History []*RedirectInfo
// contains filtered or unexported fields
}
Response represents an HTTP response
func (*Response) Bytes ¶ added in v1.5.3
Bytes returns the response body as a byte slice. If the body has already been read, returns the cached bytes. Otherwise reads the body and caches it.
func (*Response) Close ¶ added in v1.5.3
Close closes the response body. Should be called when done reading the body.
func (*Response) GetHeader ¶ added in v1.5.3
GetHeader returns the first value for the given header key (case-insensitive). Use GetHeaders() for multi-value headers like Set-Cookie.
func (*Response) GetHeaders ¶ added in v1.5.3
GetHeaders returns all values for the given header key (case-insensitive).
type SessionCacheBackend ¶ added in v1.5.8
type SessionCacheBackend interface {
// Get retrieves a TLS session for the given key.
// Returns nil, nil if not found.
// Returns nil, error if backend error (will be propagated to caller).
Get(ctx context.Context, key string) (*TLSSessionState, error)
// Put stores a TLS session with the given TTL.
// TTL should typically be ~24 hours (TLS session ticket lifetime).
// Returns error if backend error (will be propagated to caller).
Put(ctx context.Context, key string, session *TLSSessionState, ttl time.Duration) error
// Delete removes a session from the cache.
// Returns error if backend error.
Delete(ctx context.Context, key string) error
// GetECHConfig retrieves ECH config for a host (required for HTTP/3).
// Returns nil, nil if not found.
GetECHConfig(ctx context.Context, key string) ([]byte, error)
// PutECHConfig stores ECH config for a host.
PutECHConfig(ctx context.Context, key string, config []byte, ttl time.Duration) error
}
SessionCacheBackend is the interface for distributed TLS session storage. Implementations can use Redis, Memcached, or any other distributed cache. All methods should be safe for concurrent use.
type SpeculativeConn ¶ added in v1.6.0
SpeculativeConn is a connection wrapper that implements speculative TLS handshakes.
Traditional proxy flow:
- TCP connect to proxy
- Send CONNECT request
- Wait for 200 OK response (round-trip latency)
- Start TLS handshake (ClientHello)
- Wait for ServerHello (round-trip latency)
- Continue TLS handshake
Speculative flow:
- TCP connect to proxy
- On first Write (ClientHello): send CONNECT + ClientHello together
- On first Read: strip HTTP 200 OK, return TLS data (ServerHello)
- Continue TLS handshake
This saves one round-trip by overlapping the CONNECT wait with ClientHello transmission. The proxy buffers the ClientHello until the tunnel is established, then forwards it.
Performance improvement: ~25% faster proxy connections on average.
Compatibility: Works with standard HTTP CONNECT proxies. The proxy must buffer data received after the CONNECT request until the tunnel is established. This is standard TCP behavior and works with all major proxy providers tested.
func NewSpeculativeConn ¶ added in v1.6.0
func NewSpeculativeConn(conn net.Conn, connectRequest string) *SpeculativeConn
NewSpeculativeConn creates a new speculative connection wrapper. The connectRequest should be a complete HTTP CONNECT request including \r\n\r\n terminator.
func (*SpeculativeConn) Close ¶ added in v1.6.0
func (c *SpeculativeConn) Close() error
Close closes the underlying connection.
func (*SpeculativeConn) LocalAddr ¶ added in v1.6.0
func (c *SpeculativeConn) LocalAddr() net.Addr
LocalAddr returns the local network address.
func (*SpeculativeConn) Read ¶ added in v1.6.0
func (c *SpeculativeConn) Read(b []byte) (n int, err error)
Read strips the HTTP 200 OK response from the first read and returns only TLS data. The proxy sends: "HTTP/1.1 200 Connection established\r\n\r\n" + TLS ServerHello We parse and validate the HTTP response, then return only the TLS data.
func (*SpeculativeConn) RemoteAddr ¶ added in v1.6.0
func (c *SpeculativeConn) RemoteAddr() net.Addr
RemoteAddr returns the remote network address.
func (*SpeculativeConn) SetDeadline ¶ added in v1.6.0
func (c *SpeculativeConn) SetDeadline(t time.Time) error
SetDeadline sets the read and write deadlines.
func (*SpeculativeConn) SetReadDeadline ¶ added in v1.6.0
func (c *SpeculativeConn) SetReadDeadline(t time.Time) error
SetReadDeadline sets the read deadline.
func (*SpeculativeConn) SetWriteDeadline ¶ added in v1.6.0
func (c *SpeculativeConn) SetWriteDeadline(t time.Time) error
SetWriteDeadline sets the write deadline.
type SpeculativeTLSError ¶ added in v1.6.0
type SpeculativeTLSError struct {
Op string // Operation that failed: "write", "read", "parse", "status"
StatusCode int // HTTP status code (for status errors)
Err error // Underlying error
}
SpeculativeTLSError wraps errors that occur during speculative TLS handling. This allows callers to identify speculative-specific failures and potentially retry with the normal (non-speculative) flow.
func (*SpeculativeTLSError) Error ¶ added in v1.6.0
func (e *SpeculativeTLSError) Error() string
func (*SpeculativeTLSError) Unwrap ¶ added in v1.6.0
func (e *SpeculativeTLSError) Unwrap() error
type StreamResponse ¶ added in v1.5.3
type StreamResponse struct {
StatusCode int
Headers map[string][]string // Multi-value headers
FinalURL string
Timing *protocol.Timing
Protocol string // "h1", "h2", or "h3"
// ContentLength is the expected total size (-1 if unknown/chunked)
ContentLength int64
// contains filtered or unexported fields
}
StreamResponse represents a streaming HTTP response where the body is read incrementally rather than all at once.
func (*StreamResponse) Close ¶ added in v1.5.3
func (r *StreamResponse) Close() error
Close closes the response body and cancels the context
func (*StreamResponse) IsSuccess ¶ added in v1.5.3
func (r *StreamResponse) IsSuccess() bool
IsSuccess returns true if the status code is 2xx
func (*StreamResponse) Lines ¶ added in v1.5.3
func (r *StreamResponse) Lines() <-chan string
Lines returns a channel that yields lines from the response Close the response when done to stop iteration
func (*StreamResponse) Read ¶ added in v1.5.3
func (r *StreamResponse) Read(p []byte) (n int, err error)
Read reads data from the response body
func (*StreamResponse) ReadAll ¶ added in v1.5.3
func (r *StreamResponse) ReadAll() ([]byte, error)
ReadAll reads the entire response body into memory This defeats the purpose of streaming but is useful for small responses
func (*StreamResponse) ReadChunk ¶ added in v1.5.3
func (r *StreamResponse) ReadChunk(size int) ([]byte, error)
ReadChunk reads up to size bytes from the response
func (*StreamResponse) Scanner ¶ added in v1.5.3
func (r *StreamResponse) Scanner() *bufio.Scanner
Scanner returns a bufio.Scanner for line-by-line reading
type TLSSessionState ¶ added in v1.5.5
type TLSSessionState struct {
Ticket string `json:"ticket"` // base64 encoded
State string `json:"state"` // base64 encoded
CreatedAt time.Time `json:"created_at"`
}
TLSSessionState represents a serializable TLS session
func NewTLSSessionState ¶ added in v1.5.8
func NewTLSSessionState(cs *tls.ClientSessionState) (*TLSSessionState, error)
NewTLSSessionState creates a TLSSessionState from a ClientSessionState.
func (*TLSSessionState) ToClientSessionState ¶ added in v1.5.8
func (s *TLSSessionState) ToClientSessionState() (*tls.ClientSessionState, error)
ToClientSessionState converts a serialized TLS session back to a ClientSessionState.
type Transport ¶
type Transport struct {
// contains filtered or unexported fields
}
Transport is a unified HTTP transport supporting HTTP/1.1, HTTP/2, and HTTP/3
func NewTransport ¶
NewTransport creates a new unified transport
func NewTransportWithConfig ¶ added in v1.5.2
func NewTransportWithConfig(presetName string, proxy *ProxyConfig, config *TransportConfig) *Transport
NewTransportWithConfig creates a new unified transport with proxy and config
func NewTransportWithProxy ¶
func NewTransportWithProxy(presetName string, proxy *ProxyConfig) *Transport
NewTransportWithProxy creates a new unified transport with optional proxy
func (*Transport) ClearProtocolCache ¶
func (t *Transport) ClearProtocolCache()
ClearProtocolCache clears the learned protocol support cache
func (*Transport) DoStream ¶ added in v1.5.3
DoStream executes an HTTP request and returns a streaming response The caller is responsible for closing the response when done
func (*Transport) GetConfig ¶ added in v1.6.1
func (t *Transport) GetConfig() *TransportConfig
GetConfig returns the transport's configuration.
func (*Transport) GetDNSCache ¶
GetDNSCache returns the DNS cache
func (*Transport) GetHTTP1Transport ¶ added in v1.5.5
func (t *Transport) GetHTTP1Transport() *HTTP1Transport
GetHTTP1Transport returns the HTTP/1.1 transport for TLS session cache access
func (*Transport) GetHTTP2Transport ¶ added in v1.5.5
func (t *Transport) GetHTTP2Transport() *HTTP2Transport
GetHTTP2Transport returns the HTTP/2 transport for TLS session cache access
func (*Transport) GetHTTP3Transport ¶ added in v1.5.5
func (t *Transport) GetHTTP3Transport() *HTTP3Transport
GetHTTP3Transport returns the HTTP/3 transport for TLS session cache access
func (*Transport) GetHeaderOrder ¶ added in v1.5.8
GetHeaderOrder returns the current header order. Returns preset's default order if no custom order is set.
func (*Transport) Refresh ¶ added in v1.5.10
func (t *Transport) Refresh()
Refresh closes all connections but keeps TLS session caches intact. This simulates a browser page refresh - new TCP/QUIC connections but TLS resumption. Useful for resetting connection state without losing session tickets.
func (*Transport) RefreshWithProtocol ¶ added in v1.6.0
RefreshWithProtocol closes all connections and switches to a new protocol. TLS session caches are preserved for 0-RTT resumption on the new protocol. This enables warming up TLS tickets on one protocol (e.g. H3) then serving requests on another (e.g. H2) with session resumption.
func (*Transport) SetConnectTo ¶ added in v1.5.2
SetConnectTo sets a host mapping for domain fronting
func (*Transport) SetDisableECH ¶ added in v1.6.0
SetDisableECH disables ECH lookup for faster first request
func (*Transport) SetECHConfig ¶ added in v1.5.2
SetECHConfig sets a custom ECH configuration
func (*Transport) SetECHConfigDomain ¶ added in v1.5.2
SetECHConfigDomain sets a domain to fetch ECH config from
func (*Transport) SetHeaderOrder ¶ added in v1.5.8
SetHeaderOrder sets a custom header order for all requests. Pass nil or empty slice to reset to preset's default order. Order should contain lowercase header names.
func (*Transport) SetInsecureSkipVerify ¶
SetInsecureSkipVerify sets whether to skip TLS certificate verification
func (*Transport) SetProtocol ¶
SetProtocol sets the preferred protocol
func (*Transport) SetProxy ¶
func (t *Transport) SetProxy(proxy *ProxyConfig)
SetProxy sets or updates the proxy configuration Note: This recreates the underlying transports
func (*Transport) SetSessionIdentifier ¶ added in v1.5.8
SetSessionIdentifier sets a session identifier on all TLS session caches. This is used to isolate TLS sessions when the same host is accessed through different proxies or with different session configurations. The identifier is included in distributed cache keys to prevent session sharing.
func (*Transport) SetTimeout ¶
SetTimeout sets the request timeout
type TransportConfig ¶ added in v1.5.2
type TransportConfig struct {
// ConnectTo maps request hosts to connection hosts (domain fronting).
// Key: request host, Value: connection host for DNS resolution
ConnectTo map[string]string
// ECHConfig is a custom ECH configuration (overrides DNS fetch)
ECHConfig []byte
// ECHConfigDomain is a domain to fetch ECH config from instead of target
ECHConfigDomain string
// TLSOnly mode: use TLS fingerprint but skip preset HTTP headers
// User sets all headers manually
TLSOnly bool
// QuicIdleTimeout is the idle timeout for QUIC connections (default: 30s)
QuicIdleTimeout time.Duration
// LocalAddr is the local IP address to bind outgoing connections to.
// Used for IPv6 rotation with IP_FREEBIND on Linux.
LocalAddr string
// SessionCacheBackend is an optional distributed cache for TLS sessions.
// When set, TLS session tickets will be stored/retrieved from this backend,
// enabling session sharing across multiple instances.
SessionCacheBackend SessionCacheBackend
// SessionCacheErrorCallback is called when backend operations fail.
// This is optional but recommended for monitoring backend health.
SessionCacheErrorCallback ErrorCallback
// KeyLogWriter is an optional writer for TLS key logging.
// When set, TLS master secrets are written in NSS key log format
// for traffic decryption in Wireshark.
// If nil, falls back to GetKeyLogWriter() (SSLKEYLOGFILE env var).
KeyLogWriter io.Writer
// EnableSpeculativeTLS enables the speculative TLS optimization for proxy connections.
// When true, CONNECT request and TLS ClientHello are sent together, saving one
// round-trip. Disabled by default due to compatibility issues with some proxies.
EnableSpeculativeTLS bool
// CustomJA3 is a JA3 fingerprint string to use instead of the preset's TLS fingerprint.
// Format: TLSVersion,CipherSuites,Extensions,EllipticCurves,PointFormats
// When set, the preset's ClientHelloID is overridden with HelloCustom.
// Not applied to H3 (QUIC TLS uses different extensions).
CustomJA3 string
// CustomJA3Extras provides extension data that JA3 cannot capture (e.g., signature
// algorithms, ALPN). If nil, sensible Chrome-like defaults are used.
CustomJA3Extras *fingerprint.JA3Extras
// CustomH2Settings overrides the preset's HTTP/2 settings (from Akamai fingerprint).
CustomH2Settings *fingerprint.HTTP2Settings
// CustomPseudoOrder overrides the pseudo-header order (from Akamai fingerprint).
// Values: [":method", ":authority", ":scheme", ":path"]
CustomPseudoOrder []string
// CustomTCPFingerprint overrides individual TCP/IP fingerprint fields from the preset.
// Only non-zero fields are applied; zero fields keep the preset default.
CustomTCPFingerprint *fingerprint.TCPFingerprint
}
TransportConfig contains advanced transport configuration
func (*TransportConfig) GetConnectHost ¶ added in v1.5.2
func (c *TransportConfig) GetConnectHost(requestHost string) string
GetConnectHost returns the connection host for a request host. If there's a ConnectTo mapping, returns the mapped host. Otherwise returns the original host.
func (*TransportConfig) GetECHConfig ¶ added in v1.5.2
func (c *TransportConfig) GetECHConfig(ctx context.Context, targetHost string) []byte
GetECHConfig returns the ECH config to use for a host. Returns custom config if set, otherwise fetches from ECHConfigDomain or target host.
type TransportError ¶
type TransportError struct {
Op string // Operation that failed (e.g., "dial", "tls_handshake", "request")
Host string // Target host
Port string // Target port
Protocol string // Protocol (h1, h2, h3)
Cause error // Underlying error
Category error // Error category (ErrConnection, ErrTLS, etc.)
Retryable bool // Whether the operation can be retried
}
TransportError provides detailed error information
func NewConnectionError ¶
func NewConnectionError(op, host, port, protocol string, cause error) *TransportError
NewConnectionError creates a connection error
func NewDNSError ¶
func NewDNSError(host string, cause error) *TransportError
NewDNSError creates a DNS error
func NewProtocolError ¶
func NewProtocolError(host, port, protocol string, cause error) *TransportError
NewProtocolError creates a protocol negotiation error
func NewProxyError ¶
func NewProxyError(op, host, port string, cause error) *TransportError
NewProxyError creates a proxy error
func NewRequestError ¶
func NewRequestError(op, host, port, protocol string, cause error) *TransportError
NewRequestError creates a request error
func NewTLSError ¶
func NewTLSError(op, host, port, protocol string, cause error) *TransportError
NewTLSError creates a TLS error
func NewTimeoutError ¶
func NewTimeoutError(op, host, port, protocol string, cause error) *TransportError
NewTimeoutError creates a timeout error
func (*TransportError) Error ¶
func (e *TransportError) Error() string
Error implements the error interface
func (*TransportError) Is ¶
func (e *TransportError) Is(target error) bool
Is checks if the error matches the target
func (*TransportError) IsRetryable ¶
func (e *TransportError) IsRetryable() bool
IsRetryable returns whether the error is retryable
func (*TransportError) Unwrap ¶
func (e *TransportError) Unwrap() error
Unwrap returns the underlying error