goproxy Documentation

repository·master·Indexed 27 days ago

https://github.com/elazarl/goproxy

A customizable and programmable HTTP/HTTPS proxy server library for Go. It enables developers to intercept, manipulate, and redirect web traffic using custom request and response handlers, including support for HTTPS Man-in-the-Middle (MITM) interception via CA certificates.

Tokens
5.6K
Snippets
16
Records
40
Agent score
92%

What's inside goproxy

  1. Quickstart: Create a basic HTTP/HTTPS proxy

    master

    To start with a basic proxy that forwards data to the destination, use goproxy.NewProxyHttpServer(). By default, this example runs on localhost:8080. Note that for HTTPS MITM functionality, you must trust the proxy CA certificate in your client (browser) to avoid certificate errors.

    package main
    
    import (
        "log"
        "net/http"
    
        "github.com/elazarl/goproxy"
    )
    
    func main() {
        proxy := goproxy.NewProxyHttpServer()
        proxy.Verbose = true
        log.Fatal(http.ListenAndServe(":8080", proxy))
    }
  2. Replace the default proxy CA certificate

    master
    By default, goproxy uses the built-in GoproxyCa. To use your own custom CA certificate for interception, you must generate a tls.Certificate and assign it to the ConnectAction.TLSConfig field of your proxy instance.
  3. Apply conditional request handlers

    master

    Use OnRequest(condition) to apply logic only to specific requests. Conditions like goproxy.DstHostIs(host) return a ReqCondition that evaluates whether a request matches the criteria (e.g., a specific hostname). Host checks are case-insensitive.

    Example: Refuse connections to a specific host during certain hours.

    proxy.OnRequest(goproxy.DstHostIs("www.reddit.com")).DoFunc(
        func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
            if h, _, _ := time.Now().Clock(); h >= 8 && h <= 17 {
                resp := goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusForbidden, "Don't waste your time!")
                return req, resp
            }
            return req, nil
        })
  4. Handle connection errors with ConnectionErrHandler

    master

    When an error occurs while sending data to the target remote server or the proxy client, the proxy.ConnectionErrHandler is triggered.

    Key details:

    • The error is passed directly as a function parameter (it is not located in the ctx.Error field).
    • You have access to the raw connection with the proxy client as an io.Writer, allowing you to write custom error data directly to the connection.
    • Note that Write() may return an error if the connection has already been closed.
    • The connection is automatically closed by the library after the handler is called; you do not need to close it manually.
  5. Handle generic request errors with RespHandler

    master

    By default, GoProxy returns an HTTP 500 (Internal Server Error) with the error message as the body when a request fails. To customize this behavior, define a RespHandler using proxy.OnResponse().DoFunc. Inside the handler, you can inspect ctx.Error to identify the specific error and return a custom response using goproxy.NewResponse.

    proxy.OnResponse().DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
    	var dnsError *net.DNSError
    	if errors.As(ctx.Error, &dnsError) {
    		// Do not leak our DNS server's address
    		dnsError.Server = "<server-redacted>"
    		return goproxy.NewResponse(ctx.Req, goproxy.ContentTypeText, http.StatusBadGateway, dnsError.Error())
    	}
    	return resp
    })
  6. Manipulate HTTP requests with OnRequest().DoFunc()

    master

    You can intercept and modify all incoming requests by calling OnRequest() without arguments. The DoFunc method accepts a function that receives the *http.Request and a *goproxy.ProxyCtx.

    Important: If your handler returns a non-nil *http.Response, the proxy will discard the original request and send that response directly to the client instead of forwarding the request to the destination.

  7. Configure ProxyHttpServer options

    master

    The ProxyHttpServer struct provides several configuration fields to control proxy behavior:

    • KeepDestinationHeaders (bool): If true, retains headers present in the http.Response before proxying.
    • Verbose (bool): If true, logs information for each request sent to the proxy.
    • Logger (Logger): Custom logger. Must implement the Logger interface. Defaults to log.New(os.Stderr, "", log.LstdFlags).
    • NonproxyHandler (http.Handler): Invoked for requests that are not proxy requests (e.g., GET /ping).
    • Tr (*http.Transport): The transport used to send requests to destination servers.
    • ConnectionErrHandler (func): Custom handler invoked when the proxy fails to connect to a target proxy. Signature: func(conn io.Writer, ctx *ProxyCtx, err error).
    • ConnectDial (func): Custom dialer for CONNECT requests. Signature: func(network string, addr string) (net.Conn, error).
    • ConnectDialWithReq (func): Custom dialer for CONNECT requests that also receives the original *http.Request. Takes precedence over ConnectDial.
    • CertStore (CertStorage): Optional cache for MITM certificates to avoid repeated CPU-intensive signing. Recommended for production.
    • KeepHeader (bool): If true, preserves the Proxy-Authorization header when forwarding to an upstream proxy.
    • AllowHTTP2 (bool): Enables HTTP/2 support. Disabled by default.
    • PreventCanonicalization (bool): If true, passes request header names directly to the destination without following HTTP RFC canonicalization.
    • KeepAcceptEncoding (bool): If true, prevents the proxy from dropping Accept-Encoding headers.
  8. Configure H2Transport fields

    master

    To use H2Transport, you must provide the following fields:

    • ClientReader (io.Reader): The source of data from the client.
    • ClientWriter (io.Writer): The destination for data being sent to the client.
    • TLSConfig (*tls.Config): The TLS configuration used for the connection to the server. Note that H2Transport will automatically set NextProtos to http2.NextProtoTLS to ensure HTTP/2 is used.
    • Host (string): The target server address (e.g., example.com or example.com:443). If the port is omitted, it defaults to :443.
  9. Handle HTTPS CONNECT phase restrictions

    master
    When using HandleConnect to intercept HTTPS traffic, remember that during the CONNECT phase, the proxy only sees the URL.Hostname() and URL.Port(). You cannot use goproxy.UrlMatches with regex patterns targeting paths (like .*gif$) during the CONNECT phase because the path is not yet available. To inspect paths, you must use a Request Handler (.Do()) instead.
  10. Understand Proxy Handler Types

    master

    GoProxy provides three distinct types of handlers depending on when you need to intercept the traffic:

    1. HTTPS Handlers (HandleConnect): Called after receiving an HTTP CONNECT from the client, but before the proxy establishes the connection to the destination. Useful for rejecting HTTPS connections based on hostname.
    2. Request Handlers (Do): Called before the proxy sends the HTTP request to the destination host.
    3. Response Handlers (Do): Called after the proxy receives an HTTP response from the destination, but before forwarding it to the client.
    // Add handlers to httpsHandlers 
    proxy.OnRequest(some ReqConditions).HandleConnect(YourHandlerFunc())
    
    // Add handlers to reqHandlers
    proxy.OnRequest(some ReqConditions).Do(YourReqHandlerFunc())
    
    // Add handlers to respHandlers
    proxy.OnResponse(some RespConditions).Do(YourRespHandlerFunc())
  11. Modify Response Body with HandleBytes

    master

    Use HandleBytes to create a RespHandler that reads the entire response body into memory, allows you to modify it via a function, and replaces the original body with the new content.

    proxy.OnResponse(cond).Do(HandleBytes(func(b []byte, ctx *ProxyCtx) []byte {
        // Modify bytes here
        return b
    }))
    HandleBytes(f func(b []byte, ctx *ProxyCtx) []byte)
  12. Implement a Response Handler with RespHandler

    master

    Use the RespHandler interface to filter or modify HTTP responses after the proxy has received them from the destination server. The proxy will send the response returned by the Handle method to the client.

    If an error occurs during processing, return nil for the response and populate ctx.RoundTrip.Error with the error details.

    type RespHandler interface {
    	Handle(resp *http.Response, ctx *ProxyCtx) *http.Response
    }