proxy

package
v0.0.0-...-ba13dd4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: GPL-3.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateID

func GenerateID() string

GenerateID returns a new unique hex string ID.

func MakeRequest

func MakeRequest(method, target string, timeout int64, body io.Reader, client http.Client) ([]byte, string, int, error)

MakeRequest performs an HTTP request using the provided client with a configurable timeout.

func NewHTTPClient

func NewHTTPClient(proxyURL string, tc *TransportConfig) http.Client

NewHTTPClient creates an http.Client that optionally routes through a proxy. proxyURL may be empty for no proxy. tc may be nil for sensible defaults.

func OpcodeFromName

func OpcodeFromName(name string) (byte, bool)

OpcodeFromName is the inverse of OpcodeName. Returns (0, false) if unknown.

func OpcodeName

func OpcodeName(op byte) string

OpcodeName maps a WS opcode to its wire name for JSON payloads.

func UpdateContentLength

func UpdateContentLength(raw []byte) []byte

UpdateContentLength recalculates the Content-Length header from the body size in a raw HTTP request. Used by the manipulate handler and fuzzer.

Accepts either CRLF or LF header terminators (CodeMirror normalizes edits to LF), but always emits canonical CRLF. The body is preserved byte-for-byte — line endings inside the body are never touched.

func WriteFrame

func WriteFrame(w io.Writer, f *WSFrame, masked bool) error

WriteFrame writes a WebSocket frame to w. If masked is true, a random mask is applied.

Types

type CapturedRequest

type CapturedRequest struct {
	ID           string        `json:"id"`
	Seq          int           `json:"seq"`
	Timestamp    time.Time     `json:"timestamp"`
	Method       string        `json:"method"`
	URL          string        `json:"url"`
	Host         string        `json:"host"`
	Protocol     string        `json:"protocol,omitempty"` // "HTTP/1.1" | "HTTP/2"
	StatusCode   int           `json:"statusCode"`
	ContentType  string        `json:"contentType,omitempty"`
	Duration     time.Duration `json:"duration"`
	ResponseSize int           `json:"responseSize"`
	ReqRaw       []byte        `json:"reqRaw,omitempty"`
	RespRaw      []byte        `json:"respRaw,omitempty"`
}

CapturedRequest holds all data about a proxied HTTP request/response pair.

type CapturedWSMessage

type CapturedWSMessage struct {
	ID            string    `json:"id"`
	ConnectionID  string    `json:"connectionId"`
	Timestamp     time.Time `json:"timestamp"`
	Direction     string    `json:"direction"` // "client_to_server" or "server_to_client"
	Opcode        byte      `json:"opcode"`
	PayloadLength int       `json:"payloadLength"`
	Payload       string    `json:"payload"` // base64 for binary, raw for text
	Host          string    `json:"host"`
	URL           string    `json:"url"`
	IsText        bool      `json:"isText"`
}

CapturedWSMessage holds a captured WebSocket message.

type CustomAddition

type CustomAddition struct {
	ID    string `json:"id"`
	Type  string `json:"type"` // "header", "query", "body"
	Name  string `json:"name"`
	Value string `json:"value"`
}

CustomAddition defines a single piece of data to inject into requests.

type CustomData

type CustomData struct {
	// contains filtered or unexported fields
}

CustomData manages a set of additive request modifications.

func NewCustomData

func NewCustomData() *CustomData

NewCustomData creates a disabled CustomData with no items.

func (*CustomData) AddItem

func (cd *CustomData) AddItem(typ, name, value string) CustomAddition

AddItem adds a new item with a generated ID. Returns the item.

func (*CustomData) IsEnabled

func (cd *CustomData) IsEnabled() bool

IsEnabled reports whether custom data injection is active.

func (*CustomData) Items

func (cd *CustomData) Items() []CustomAddition

Items returns a copy of the current items.

func (*CustomData) RemoveItem

func (cd *CustomData) RemoveItem(id string) bool

RemoveItem deletes an item by ID. Returns true if found.

func (*CustomData) SetEnabled

func (cd *CustomData) SetEnabled(enabled bool)

SetEnabled enables or disables custom data injection.

func (*CustomData) SetItems

func (cd *CustomData) SetItems(items []CustomAddition)

SetItems replaces all custom data items.

type H2TransportCache

type H2TransportCache struct {
	// contains filtered or unexported fields
}

H2TransportCache provides per-host h2 transport reuse for high-throughput callers (e.g., the fuzzer).

func NewH2TransportCache

func NewH2TransportCache(tc *TransportConfig) *H2TransportCache

NewH2TransportCache returns a cache parameterized over the given TransportConfig.

func (*H2TransportCache) Close

func (c *H2TransportCache) Close()

Close releases all cached transports.

func (*H2TransportCache) Get

func (c *H2TransportCache) Get(host string) *http2.Transport

Get returns a cached or freshly built h2 transport keyed by host.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler is the main http.Handler for the intercepting proxy. It routes CONNECT requests to the MITM engine and plain HTTP to the forwarder.

func NewHandler

func NewHandler(certCache *cert.Cache, store *Store, intercept *InterceptQueue, scope *Scope, noise *NoiseFilter, replace *MatchReplace, customData *CustomData, transport *TransportConfig, wsStore *WSStore, broadcast chan<- any) *Handler

NewHandler creates a proxy Handler.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*Handler) SetHookRunner

func (h *Handler) SetHookRunner(hr HookRunner)

SetHookRunner sets the plugin hook runner for proxy pipeline hooks.

type HookRunner

type HookRunner interface {
	RunRequestHook(ctx context.Context, info sdk.RequestInfo, rawReq []byte) ([]byte, error)
	RunResponseHook(ctx context.Context, info sdk.RequestInfo, rawResp []byte) ([]byte, error)
}

HookRunner is implemented by the plugin manager to run proxy pipeline hooks.

type InterceptAction

type InterceptAction int

InterceptAction describes the decision made for an intercepted request.

const (
	ActionForward InterceptAction = iota
	ActionDrop
)

type InterceptDecision

type InterceptDecision struct {
	Action  InterceptAction
	ReqData []byte // non-nil → use as replacement raw request bytes
}

InterceptDecision is sent back to the waiting handler goroutine.

type InterceptQueue

type InterceptQueue struct {
	// contains filtered or unexported fields
}

InterceptQueue manages the set of paused requests and the enabled/disabled toggle.

func NewInterceptQueue

func NewInterceptQueue(timeout time.Duration) *InterceptQueue

NewInterceptQueue creates an InterceptQueue with the given auto-forward timeout.

func (*InterceptQueue) IsEnabled

func (q *InterceptQueue) IsEnabled() bool

IsEnabled reports whether interception is currently active.

func (*InterceptQueue) List

func (q *InterceptQueue) List() []*PendingRequest

List returns a snapshot of all currently pending requests.

func (*InterceptQueue) Pause

func (q *InterceptQueue) Pause(id, method, rawURL, host, protocol string, rawReq []byte) (InterceptDecision, bool)

Pause blocks the calling goroutine until a decision is made or the timeout fires. Returns (decision, true) on explicit decision, or (forward, false) on timeout.

func (*InterceptQueue) Resolve

func (q *InterceptQueue) Resolve(id string, d InterceptDecision) bool

Resolve sends a decision to the goroutine waiting on id. Returns false if id is unknown.

func (*InterceptQueue) SetEnabled

func (q *InterceptQueue) SetEnabled(enabled bool)

SetEnabled enables or disables interception.

func (*InterceptQueue) SetTimeout

func (q *InterceptQueue) SetTimeout(d time.Duration)

SetTimeout changes the auto-forward timeout.

type ManipulateWSCloseCallback

type ManipulateWSCloseCallback func(reason string)

ManipulateWSCloseCallback is invoked exactly once when the session closes, either due to remote close, read error, or a call to Close.

type ManipulateWSFrameCallback

type ManipulateWSFrameCallback func(direction string, opcode byte, payload []byte, ts time.Time)

ManipulateWSFrameCallback is invoked once per complete incoming message. Sent frames are reported via the same callback so the UI can render a unified transcript.

type ManipulateWSManager

type ManipulateWSManager struct {
	// contains filtered or unexported fields
}

ManipulateWSManager tracks active user-driven WS sessions.

func NewManipulateWSManager

func NewManipulateWSManager(transport *TransportConfig) *ManipulateWSManager

NewManipulateWSManager returns a manager. transport may be nil, in which case plain net.Dial / tls.Dial are used.

func (*ManipulateWSManager) Close

func (m *ManipulateWSManager) Close(id, reason string) error

Close sends a close frame (if still open) and tears down the session. Repeated calls are safe.

func (*ManipulateWSManager) Dial

func (m *ManipulateWSManager) Dial(
	rawUpgrade []byte,
	scheme, host string,
	onFrame ManipulateWSFrameCallback,
	onClose ManipulateWSCloseCallback,
) (*ManipulateWSSession, []byte, error)

Dial opens a WebSocket connection to host using the exact rawUpgrade bytes supplied by the user (with a best-effort Sec-WebSocket-Key fill-in if the header is missing). It returns the session (open and reading in the background), the raw upgrade response bytes, and an error.

On non-101 response, the error is non-nil but rawResp is still populated so the caller can show the server's rejection in the UI.

func (*ManipulateWSManager) Get

Get returns a session by ID or nil.

func (*ManipulateWSManager) Send

func (m *ManipulateWSManager) Send(id string, opcode byte, payload []byte) error

Send writes a single FIN data/control frame with the given opcode and payload. The client side always masks outgoing frames. The sent frame is also dispatched to the session's onFrame callback so the UI transcript is updated consistently.

type ManipulateWSSession

type ManipulateWSSession struct {
	ID  string
	URL string
	// contains filtered or unexported fields
}

ManipulateWSSession is a client-initiated WebSocket connection whose raw upgrade handshake was authored by the user. Frames are sent on demand via Send; incoming frames are reassembled across continuations and delivered via the session's onFrame callback.

func (*ManipulateWSSession) State

State returns the current lifecycle state.

type ManipulateWSState

type ManipulateWSState int32

ManipulateWSState is the lifecycle state of a ManipulateWSSession.

const (
	ManipulateWSConnecting ManipulateWSState = iota
	ManipulateWSOpen
	ManipulateWSClosed
)

type MatchReplace

type MatchReplace struct {
	// contains filtered or unexported fields
}

MatchReplace manages a set of match-and-replace rules applied to proxy traffic.

func NewMatchReplace

func NewMatchReplace() *MatchReplace

NewMatchReplace creates a disabled MatchReplace with no rules.

func (*MatchReplace) AddRule

func (mr *MatchReplace) AddRule(target, matchType, match, replace string) MatchReplaceRule

AddRule adds a new rule with a generated ID. Returns the rule.

func (*MatchReplace) Apply

func (mr *MatchReplace) Apply(target string, data []byte) []byte

Apply runs all enabled rules matching the given target against data, returning the modified result.

func (*MatchReplace) HasResponseRules

func (mr *MatchReplace) HasResponseRules() bool

HasResponseRules reports whether any rules target response_header or response_body.

func (*MatchReplace) IsEnabled

func (mr *MatchReplace) IsEnabled() bool

IsEnabled reports whether match-and-replace is active.

func (*MatchReplace) RemoveRule

func (mr *MatchReplace) RemoveRule(id string) bool

RemoveRule deletes a rule by ID. Returns true if found.

func (*MatchReplace) Rules

func (mr *MatchReplace) Rules() []MatchReplaceRule

Rules returns a copy of the current rules.

func (*MatchReplace) SetEnabled

func (mr *MatchReplace) SetEnabled(enabled bool)

SetEnabled enables or disables match-and-replace.

func (*MatchReplace) SetRules

func (mr *MatchReplace) SetRules(rules []MatchReplaceRule)

SetRules replaces all match-and-replace rules, compiling regex patterns.

type MatchReplaceRule

type MatchReplaceRule struct {
	ID        string `json:"id"`
	Target    string `json:"target"`    // "request_header", "request_body", "response_header", "response_body", "ws_message"
	MatchType string `json:"matchType"` // "string" or "regex"
	Match     string `json:"match"`
	Replace   string `json:"replace"`
	// contains filtered or unexported fields
}

MatchReplaceRule defines a single match-and-replace transformation.

type NoiseFilter

type NoiseFilter struct {
	// contains filtered or unexported fields
}

NoiseFilter silently tunnels/forwards traffic matching known browser noise patterns (captive portal, telemetry, OCSP, etc.) without capture.

func NewNoiseFilter

func NewNoiseFilter() *NoiseFilter

NewNoiseFilter creates a NoiseFilter that is enabled by default with curated browser noise patterns.

func (*NoiseFilter) AddPattern

func (nf *NoiseFilter) AddPattern(pattern string) NoisePattern

AddPattern adds a new noise pattern and returns it with a generated ID.

func (*NoiseFilter) IsEnabled

func (nf *NoiseFilter) IsEnabled() bool

IsEnabled reports whether noise filtering is active.

func (*NoiseFilter) IsNoisy

func (nf *NoiseFilter) IsNoisy(host string) bool

IsNoisy checks if a host matches any enabled noise pattern.

func (*NoiseFilter) Patterns

func (nf *NoiseFilter) Patterns() []NoisePattern

Patterns returns a copy of the current noise patterns.

func (*NoiseFilter) RemovePattern

func (nf *NoiseFilter) RemovePattern(id string) bool

RemovePattern deletes a pattern by ID. Returns true if found.

func (*NoiseFilter) SetEnabled

func (nf *NoiseFilter) SetEnabled(enabled bool)

SetEnabled enables or disables noise filtering.

func (*NoiseFilter) SetPatterns

func (nf *NoiseFilter) SetPatterns(patterns []NoisePattern)

SetPatterns replaces all noise patterns.

type NoisePattern

type NoisePattern struct {
	ID      string `json:"id"`
	Pattern string `json:"pattern"`
}

NoisePattern defines a host pattern to filter as noise.

type PendingRequest

type PendingRequest struct {
	ID       string `json:"id"`
	Method   string `json:"method"`
	URL      string `json:"url"`
	Host     string `json:"host"`
	Protocol string `json:"protocol,omitempty"`
	ReqRaw   []byte `json:"reqRaw"`
	// contains filtered or unexported fields
}

PendingRequest is an intercepted request waiting for a forward/drop decision.

type RequestFilter

type RequestFilter struct {
	Host        string
	Method      string
	Status      int
	Search      string
	Exclude     string    // comma-separated file extensions, e.g. ".css,.png,.jpg"
	ExtMode     string    // "exclude" (default) or "include"
	ContentType string    // simplified content type keyword, e.g. "html", "json", "image"
	InScopeFunc ScopeFunc // optional: if set, only include requests passing this check
	Offset      int
	Limit       int
}

RequestFilter holds optional filter criteria for listing requests.

type Scope

type Scope struct {
	// contains filtered or unexported fields
}

Scope manages host and request-level scope filtering.

func NewScope

func NewScope() *Scope

NewScope creates a Scope that is disabled by default with no rules.

func (*Scope) AddRule

func (s *Scope) AddRule(rule ScopeRule) ScopeRule

AddRule appends a rule, assigning it a generated ID.

func (*Scope) HostInScope

func (s *Scope) HostInScope(host string) bool

HostInScope checks if a hostname passes scope at the CONNECT level (host only).

func (*Scope) InScope

func (s *Scope) InScope(host, method, path string) bool

InScope checks if a request passes scope (host + method + path).

func (*Scope) IsEnabled

func (s *Scope) IsEnabled() bool

IsEnabled reports whether scope filtering is active.

func (*Scope) RemoveRule

func (s *Scope) RemoveRule(id string) bool

RemoveRule deletes a rule by ID. Returns true if found.

func (*Scope) Rules

func (s *Scope) Rules() []ScopeRule

Rules returns a copy of the current scope rules.

func (*Scope) SetEnabled

func (s *Scope) SetEnabled(enabled bool)

SetEnabled enables or disables scope filtering.

func (*Scope) SetRules

func (s *Scope) SetRules(rules []ScopeRule)

SetRules replaces all scope rules.

type ScopeFunc

type ScopeFunc func(host, method, path string) bool

ScopeFunc checks whether a request with the given host, method, and path is in scope.

type ScopeRule

type ScopeRule struct {
	ID      string   `json:"id"`
	Pattern string   `json:"pattern"` // host glob: "*.target.com"
	Methods []string `json:"methods"` // e.g. ["POST","PUT"], empty = all
	Path    string   `json:"path"`    // path glob: "/api/*", empty = all
	Include bool     `json:"include"` // true=include, false=exclude
}

ScopeRule defines a single include or exclude scope rule.

type SendOptions

type SendOptions struct {
	FollowRedirects bool
	Decompress      bool
	H2Transport     *http2.Transport
}

SendOptions controls behavior of SendRawRequest.

type SendResult

type SendResult struct {
	Response       *http.Response
	RawResp        []byte
	Duration       time.Duration
	Hops           int
	ResponseSource string // "wire" | "synthetic" | "fallback-h1"
}

SendResult holds the outcome of a raw send.

func SendRawRequest

func SendRawRequest(ctx context.Context, raw []byte, scheme, host string, opts SendOptions, tc *TransportConfig) (*SendResult, error)

SendRawRequest sends raw HTTP request bytes, choosing the wire protocol from the version token in the request line. HTTP/1.0 and HTTP/1.1 go on the wire byte-for-byte over a raw TCP/TLS socket with ALPN forced to http/1.1. HTTP/2 is re-encoded by golang.org/x/net/http2 with ALPN forced to h2 (h2 has no textual request line on the wire).

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps an HTTP proxy listener.

func NewServer

func NewServer(bindAddr string, port int, handler *Handler) *Server

NewServer creates a proxy Server on the given address and port.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start begins listening and blocks until ctx is cancelled.

type SitemapEndpoint

type SitemapEndpoint struct {
	Path     string           `json:"path"`
	Methods  []string         `json:"methods"`
	Params   []string         `json:"params"`
	Variants []SitemapVariant `json:"variants"`
	Count    int              `json:"count"`
}

SitemapEndpoint represents a unique path within a host.

type SitemapHost

type SitemapHost struct {
	Origin    string            `json:"origin"`
	Endpoints []SitemapEndpoint `json:"endpoints"`
	Count     int               `json:"count"`
}

SitemapHost represents a unique origin (scheme://host:port).

type SitemapVariant

type SitemapVariant struct {
	Params    []string `json:"params"`
	RequestID string   `json:"requestId"`
	Count     int      `json:"count"`
}

SitemapVariant represents a unique query-parameter-name combination observed for an endpoint, along with the ID of the latest matching request.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is a thread-safe in-memory ring buffer of captured requests.

func NewStore

func NewStore(maxSize int) *Store

NewStore creates a Store with the given max capacity (default 5,000).

func (*Store) Add

func (s *Store) Add(r *CapturedRequest)

Add appends a request, evicting the oldest if at capacity.

func (*Store) All

func (s *Store) All() []*CapturedRequest

All returns a copy of all stored requests.

func (*Store) Clear

func (s *Store) Clear()

Clear removes all stored requests.

func (*Store) Get

func (s *Store) Get(id string) *CapturedRequest

Get returns the request with the given ID, or nil.

func (*Store) Hosts

func (s *Store) Hosts() []string

Hosts returns a sorted, deduplicated list of hosts from the ring buffer.

func (*Store) List

func (s *Store) List(f RequestFilter) ([]*CapturedRequest, int)

List returns a filtered, paginated slice along with the total matching count.

func (*Store) LoadItems

func (s *Store) LoadItems(items []*CapturedRequest)

LoadItems replaces all stored requests with the given items. If more items are provided than maxSize, only the last maxSize are kept.

func (*Store) MaxSize

func (s *Store) MaxSize() int

MaxSize returns the current ring buffer capacity.

func (*Store) SetMaxSize

func (s *Store) SetMaxSize(n int)

SetMaxSize updates the ring buffer capacity. If the current number of items exceeds the new capacity, the oldest items are trimmed.

func (*Store) Sitemap

func (s *Store) Sitemap() []SitemapHost

Sitemap builds an aggregated site map from all captured requests. Hosts are keyed by origin (scheme://host:port). Within each host, endpoints are grouped by path with observed methods and query param names.

type TransportConfig

type TransportConfig struct {
	// contains filtered or unexported fields
}

TransportConfig manages HTTP transport settings (HTTP/2, keep-alive, SOCKS) and rebuilds the shared transport when settings change.

func NewTransportConfig

func NewTransportConfig() *TransportConfig

NewTransportConfig creates a TransportConfig with defaults: HTTP/2 enabled, keep-alive disabled.

func (*TransportConfig) HTTP2

func (tc *TransportConfig) HTTP2() bool

HTTP2 returns whether HTTP/2 upstream is enabled.

func (*TransportConfig) KeepAlive

func (tc *TransportConfig) KeepAlive() bool

KeepAlive returns whether keep-alive is enabled.

func (*TransportConfig) SOCKS

func (tc *TransportConfig) SOCKS() (host string, port int, username, password string, dns bool)

SOCKS returns the current SOCKS proxy settings.

func (*TransportConfig) SOCKSDialContext

func (tc *TransportConfig) SOCKSDialContext() func(ctx context.Context, network, addr string) (net.Conn, error)

SOCKSDialContext returns a DialContext function that routes through the SOCKS proxy, or nil if no SOCKS proxy is configured. Used by tunnel() and NewHTTPClient().

func (*TransportConfig) SetHTTP2

func (tc *TransportConfig) SetHTTP2(enabled bool)

SetHTTP2 enables or disables HTTP/2 upstream negotiation.

func (*TransportConfig) SetKeepAlive

func (tc *TransportConfig) SetKeepAlive(enabled bool)

SetKeepAlive enables or disables TCP connection reuse.

func (*TransportConfig) SetSOCKS

func (tc *TransportConfig) SetSOCKS(host string, port int, username, password string, dns bool)

SetSOCKS configures an upstream SOCKS5 proxy. Pass empty host to disable.

func (*TransportConfig) Transport

func (tc *TransportConfig) Transport() *http.Transport

Transport returns the current cached transport.

type WSFrame

type WSFrame struct {
	FIN     bool
	Opcode  byte
	Masked  bool
	Payload []byte
}

WSFrame represents a single WebSocket frame.

func ReadFrame

func ReadFrame(r io.Reader) (*WSFrame, error)

ReadFrame reads a single WebSocket frame from r.

func (*WSFrame) IsControl

func (f *WSFrame) IsControl() bool

IsControl returns true for close/ping/pong frames.

type WSMessageFilter

type WSMessageFilter struct {
	Host   string
	Offset int
	Limit  int
}

WSMessageFilter holds optional filter criteria.

type WSStore

type WSStore struct {
	// contains filtered or unexported fields
}

WSStore is a thread-safe in-memory ring buffer of captured WebSocket messages.

func NewWSStore

func NewWSStore(maxSize int) *WSStore

NewWSStore creates a WSStore with the given max capacity.

func (*WSStore) Add

func (s *WSStore) Add(m *CapturedWSMessage)

Add appends a message, evicting the oldest if at capacity.

func (*WSStore) Clear

func (s *WSStore) Clear()

Clear removes all stored messages.

func (*WSStore) List

func (s *WSStore) List(f WSMessageFilter) ([]*CapturedWSMessage, int)

List returns a filtered, paginated slice along with total count.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL