Documentation ¶
Overview ¶
Taken from $GOROOT/src/pkg/net/http/chunked needed to write https responses to client.
Package goproxy provides a customizable HTTP proxy, supporting hijacking HTTPS connection.
The intent of the proxy, is to be usable with reasonable amount of traffic yet, customizable and programable.
The proxy itself is simply an `net/http` handler.
Typical usage is
proxy := goproxy.NewProxyHttpServer() proxy.Verbose = true proxy.HandleRequestFunc(func(ctx *goproxy.ProxyCtx) goproxy.Next { if ctx.Host() == "example.com:80" { ctx.SetDestinationHost("127.0.0.1:8080") return goproxy.FORWARD } return goproxy.NEXT }) proxy.ListenAndServe(":8080")
Adding a header to each request:
proxy.HandleRequestFunc(func(ctx *goproxy.ProxyCtx) goproxy.Next { ctx.Req.Header.Set("X-GoProxy","1") return goproxy.NEXT })
For printing the content type of all incoming responses
proxy.HandleResponseFunc(func(ctx *goproxy.ProxyCtx) goproxy.Next { fmt.Println(ctx.Req.Host, "->", ctx.Req.Header.Get("Content-Type")) return goproxy.NEXT })
Note the use of `ctx.Req` here. The `ctx` holds `Req` and `Resp`. `Resp` can be nil if not available.
To print the content type of all responses from a certain url, we'll add a "middleware" before:
golangOrgOnly := goproxy.UrlHasPrefix("golang.org/pkg") logInYourFace := func(ctx *goproxy.ProxyCtx) goproxy.Next { fmt.Println(ctx.Req.Host, "->", ctx.Req.Header.Get("Content-Type")) return goproxy.NEXT } proxy.HandleResponseFunc(golangOrgOnly(logInYourFace))
To invalide responses based on headers for example, you can:
proxy.HandleResponseFunc(func(ctx *goproxy.ProxyCtx) goproxy.Next { if ctx.Resp.Header.Get("X-GoProxy") == "" { ctx.Resp.Close() http.Error(ctx.ResponseWriter, "Denied.. didn't find an X-GoProxy header!", 403) return goproxy.DONE } return goproxy.NEXT })
We close the body of the original repsonse, and return a new 403 response with a short message.
You can catch traffic going through the proxy selectively, and write it to a HAR formatted file with this code:
proxy.HandleRequestFunc(func(ctx *goproxy.ProxyCtx) goproxy.Next { if ctx.Host() == "example.com:80" { ctx.LogToHARFile(true) } return goproxy.NEXT }) proxy.NonProxyHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/har" { proxy.FlushHARToDisk("/tmp/file.har") w.WriteHeader(201) w.Write([]byte("hello world!\n")) } })
You then "curl http://localhost:8888/har" to provoke a file flush to "/tmp/file.har".
Example use cases:
1. https://github.com/stoplightio/goproxy/tree/master/examples/goproxy-avgsize
To measure the average size of an Html served in your site. One can ask all the QA team to access the website by a proxy, and the proxy will measure the average size of all text/html responses from your host.
2. [not yet implemented]
All requests to your web servers should be directed through the proxy, when the proxy will detect html pieces sent as a response to AJAX request, it'll send a warning email.
3. https://github.com/stoplightio/goproxy/blob/master/examples/goproxy-httpdump/
Generate a real traffic to your website by real users using through proxy. Record the traffic, and try it again for more real load testing.
4. https://github.com/stoplightio/goproxy/tree/master/examples/goproxy-no-reddit-at-worktime
Will allow browsing to reddit.com between 8:00am and 17:00pm
5. https://github.com/stoplightio/goproxy/tree/master/examples/goproxy-jquery-version
Will warn if multiple versions of jquery are used in the same domain.
6. https://github.com/stoplightio/goproxy/blob/master/examples/goproxy-upside-down-ternet/
Modifies image files in an HTTP response via goproxy's image extension found in ext/.
Index ¶
- Constants
- Variables
- func CondRemoteAddrIs(ctx *ProxyCtx, ip string) bool
- func HostsToMap(hosts ...string) map[string]bool
- func MatchIsLocalhost(req *http.Request) bool
- func MatchRequestHostMap(req *http.Request, hosts map[string]bool) bool
- func NewResponse(r *http.Request, status int, contentType, body string) *http.Response
- type ChainedHandler
- func RemoteAddrIs(ip string) ChainedHandler
- func RemoteAddrIsNot(ip string) ChainedHandler
- func ReqHostMatches(regexps ...*regexp.Regexp) ChainedHandler
- func RequestHostContains(hosts ...string) ChainedHandler
- func RequestHostIsIn(hosts ...string) ChainedHandler
- func RequestHostIsNotIn(hosts ...string) ChainedHandler
- func RespContentTypeIs(types ...string) ChainedHandler
- func UrlHasPrefix(prefix string) ChainedHandler
- func UrlIsIn(urls ...string) ChainedHandler
- func UrlMatches(re *regexp.Regexp) ChainedHandler
- type CounterEncryptorRand
- type GoproxyConfig
- type Handler
- type HandlerFunc
- type Next
- type ProxyCtx
- func (ctx *ProxyCtx) BufferResponse() ([]byte, error)
- func (ctx *ProxyCtx) Charset() string
- func (ctx *ProxyCtx) DispatchDoneHandlers() error
- func (ctx *ProxyCtx) DispatchResponseHandlers() error
- func (ctx *ProxyCtx) FakeDestinationDNS(host string)
- func (ctx *ProxyCtx) FlushHARToDisk(filename string)
- func (ctx *ProxyCtx) ForwardConnect() error
- func (ctx *ProxyCtx) ForwardRequest(host string) error
- func (ctx *ProxyCtx) ForwardResponse(resp *http.Response) error
- func (ctx *ProxyCtx) HijackConnect() net.Conn
- func (ctx *ProxyCtx) Host() string
- func (ctx *ProxyCtx) LogToHARFile(captureContent bool) Next
- func (ctx *ProxyCtx) Logf(msg string, argv ...interface{})
- func (ctx *ProxyCtx) ManInTheMiddle() error
- func (ctx *ProxyCtx) ManInTheMiddleHTTPS() error
- func (ctx *ProxyCtx) NewHTMLResponse(body string)
- func (ctx *ProxyCtx) NewResponse(status int, contentType, body string)
- func (ctx *ProxyCtx) NewTextResponse(body string)
- func (ctx *ProxyCtx) RejectConnect()
- func (ctx *ProxyCtx) RoundTrip(req *http.Request) (*http.Response, error)
- func (ctx *ProxyCtx) SNIHost() string
- func (ctx *ProxyCtx) SetConnectScheme(scheme string)
- func (ctx *ProxyCtx) SetDestinationHost(host string)
- func (ctx *ProxyCtx) SetResponseBody(content []byte)
- func (ctx *ProxyCtx) TunnelHTTP() error
- func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{})
- type ProxyHttpServer
- func (proxy *ProxyHttpServer) FlushHARToDisk(filename string)
- func (proxy *ProxyHttpServer) HandleConnect(f Handler)
- func (proxy *ProxyHttpServer) HandleConnectFunc(f func(ctx *ProxyCtx) Next)
- func (proxy *ProxyHttpServer) HandleDone(f Handler)
- func (proxy *ProxyHttpServer) HandleDoneFunc(f func(ctx *ProxyCtx) Next)
- func (proxy *ProxyHttpServer) HandleRequest(f Handler)
- func (proxy *ProxyHttpServer) HandleRequestFunc(f func(ctx *ProxyCtx) Next)
- func (proxy *ProxyHttpServer) HandleResponse(f Handler)
- func (proxy *ProxyHttpServer) HandleResponseFunc(f func(ctx *ProxyCtx) Next)
- func (proxy *ProxyHttpServer) ListenAndServe(addr string) error
- func (proxy *ProxyHttpServer) Logf(msg string, v ...interface{})
- func (proxy *ProxyHttpServer) NewConnectDialToProxy(https_proxy string) func(network, addr string) (net.Conn, error)
- func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (proxy *ProxyHttpServer) SetMITMCertConfig(config *GoproxyConfig)
- type RoundTripper
- type RoundTripperFunc
Constants ¶
const ( NEXT = Next(iota) // Continue to the next Handler MOCK DONE // Implies that no further processing is required. The request has been fulfilled completely. FORWARD // Continue directly with forwarding, going through Response Handlers MITM // Continue with Man-in-the-middle attempt, either through HTTP or HTTPS. REJECT // Reject the CONNECT attempt outright )
Variables ¶
var AlwaysForward = HandlerFunc(func(ctx *ProxyCtx) Next { return FORWARD })
var AlwaysMitm = HandlerFunc(func(ctx *ProxyCtx) Next { ctx.SNIHost() return MITM })
var AlwaysReject = HandlerFunc(func(ctx *ProxyCtx) Next { return REJECT })
var CA_CERT = []byte(`-----BEGIN CERTIFICATE-----
MIIC/TCCAeWgAwIBAgIRALVzNa8DPRRGV0QBro07S7UwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzAyMTYxNTA0MDVaFw0yNzAyMTQxNTA0
MDVaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCf5PWDdpWwMSSogQ0EcvR58pkU5tncQ9ektJ0GSrfLd/hR17M5+xKq
cFDlWGB7uKUU+6uM4UQnrbYzx97MUCnh5Ie58Hgb9jdx+A3eYCzneJWoBtJcsiMd
TFbjVEuqyFWVcy/dzfrmwEiyH2xHmMhJ/SnVpZa1MG9bjxJwuUECQMjbShePW5bK
XCMpIGyqHENRQg6wXRf1NykaSD+2yu4v+sljiCDy/VbmJDkoiyRtBsdxTncITKa3
LPbZnZtJS26SpYkDpNpAzt2bWkkrxh9isV2S4MNqrO7CjNNawEmkSs7yv+LhCvYN
i+9x3QTuJJ3QEoxIjJ2qv02tzlj5RidXAgMBAAGjTjBMMA4GA1UdDwEB/wQEAwIC
pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBQGA1UdEQQN
MAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAZq4a3eBSmC3PCD8Pte4h
zdgTNK22Zh1YCD+rVaDC8v9igJ69s+ggQl1VwzgIUd90mXAElBHmqjPffT5Ao1E5
ph+7Kdt4H04ugpLDZGfeOB6k5OMRbiEvgz5XRVPQVBcLTAvEit23ifVSbqkfMRh5
dO3dhRG0sxdKN+eFzxnXp4mGpcIniPYTsRE0Zee5ESMsw72S6iFFR9pokhUw9ESN
EQ+bJpd63nxMEkahFHBBrC/74obmg58pYbGyVlE1UuqN49WYgqL83Id+EQSwHzrn
hNqXKv3sGnFl4uUCRCc/PNRUdCkhPp5v9W6k5rMYwGxBb4QBrU12PpUWoqwV8dFi
8A==
-----END CERTIFICATE-----`)
var CA_KEY = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAn+T1g3aVsDEkqIENBHL0efKZFObZ3EPXpLSdBkq3y3f4Udez
OfsSqnBQ5Vhge7ilFPurjOFEJ622M8fezFAp4eSHufB4G/Y3cfgN3mAs53iVqAbS
XLIjHUxW41RLqshVlXMv3c365sBIsh9sR5jISf0p1aWWtTBvW48ScLlBAkDI20oX
j1uWylwjKSBsqhxDUUIOsF0X9TcpGkg/tsruL/rJY4gg8v1W5iQ5KIskbQbHcU53
CEymtyz22Z2bSUtukqWJA6TaQM7dm1pJK8YfYrFdkuDDaqzuwozTWsBJpErO8r/i
4Qr2DYvvcd0E7iSd0BKMSIydqr9Nrc5Y+UYnVwIDAQABAoIBAHkVzI832HfLX3Vz
9UWvQFCxVRgtEkLp5X5HgLppDvK48YYZERMRfbswvzJPURGgbPOM+wb++LwLovVn
oOOcuXrls5st7edO+AII1YfX0WmhOcQ7Fkc4Z7siOpKBHaRBff5lcpRIDn98khDC
Fx/JJbRSUcIHWi/wdAQkPtS6le57qqBl2wGRIbV3/6Hjq15X2UJCtzrGjY3IcYKp
lwL2C7boEEppQLXodVdXewfoM+6v76g/Vtx4qaLapCaVnv8GthtcejQhHIgZO5ZR
j1ANuaVWPDi0CoLWDCQAOlrDiQbTQtdgyV0uG+3JGxW2SW2uv15N9Fn1eELf8S29
CwmW6yECgYEAzqDwjRR+sOMdUKHCPHYHa+7V1t/dvmaEJaSsORo9gMLauqLbQGy5
2zTIHoIzIzrW6IjFtVkThKmof+6JdBbINKShLtkNsl3Pr9fuhRsE7qxTnWen4BmM
p4fx83xhQrEcSya+9Uj19spfKTxM/+sfhGhKavWjJ+0Fumqd8IMuvskCgYEAxhlg
UmSZeWSXJ9CGUpu+eZkZdoUQxGwzka9iuGE/qM1eFWd7idx4owexaHLOqf9rxACb
fuMbREOn+n8zsTynsvNLw6CPtDlV4QB08wcFX14hk+WGDujDWppOyiXKsytHzUmG
Q1KycHwa/qVNVtSy2hlRtJxYNwwDupRl73+6JR8CgYAqLprNAkkWzVaXtl4Tv7im
JRzMf+khzIXftW1fPucdWSoT/dkqnseWY4ETEVtlLsbes8VAz013wLbgXw76fwgi
DxXEnZT5O8OBT2CnFav9GXr8YEPaMP0Q2mTfYx3r4oI3KVLEej+UQR4KKgBCInrN
qgi/KyRCq1WHB+r0RaOOWQKBgETibBkafDe3H8yreRneqGRWNYF+Ee+LhH8jUpu0
zVMgXpfozQ+KR7TBJxKf4XdBpzKX13pO9JtPP2ketFXsNpBGg9D50x6jVVaRNxmP
FnIsJFbuWCh1DgFCaSVn8M1OvoAHEhX0+rGcpjJoPrVz7uFiLoQ0XYR+vAk0MyIN
8yeXAoGAEYDoNb8fcOnUOac9ziIqP2cZkl3jY9bom2Pm4xgsxrvdT29WTdKUXDnv
McrO0jsnBcEeA2jQjCZ5ZZ6zsKRvPtYHjHzcUCYhc1HI5QIK49ObuHGGzYIPhcIv
irIev81IwGZcLkKJ1U1P7sDpT07gXpdKMAfur6OgSd3oq25NH8E=
-----END RSA PRIVATE KEY-----`)
MaxSerialNumber is the upper boundary that is used to create unique serial numbers for the certificate. This can be any unsigned integer up to 20 bytes (2^(8*20)-1).
Functions ¶
func CondRemoteAddrIs ¶
func HostsToMap ¶
func MatchIsLocalhost ¶
func NewResponse ¶
Will generate a valid http response to the given request the response will have the given contentType, and http status. Typical usage, refuse to process requests to local addresses:
proxy.HandleRequest(IsLocalhost(HandlerFunc(func(ctx *ProxyCtx) Next { ctx.NewResponse(http.StatusUnauthorized, "text/html", "<html><body>Can't use proxy for local addresses</body></html>") return FORWARD })))
Types ¶
type ChainedHandler ¶
func RemoteAddrIs ¶
func RemoteAddrIs(ip string) ChainedHandler
MatchRemoteAddr returns a ReqCondtion testing wether the source IP of the request is the given string, Was renamed from `SrcIpIs`.
func RemoteAddrIsNot ¶
func RemoteAddrIsNot(ip string) ChainedHandler
func ReqHostMatches ¶
func ReqHostMatches(regexps ...*regexp.Regexp) ChainedHandler
ReqHostMatches is a middleware that tests whether the host to which the request was directed to matches any of the given regular expressions.
func RequestHostContains ¶
func RequestHostContains(hosts ...string) ChainedHandler
RequestHostContains is a middleware that tests whether the host to which the request is directed to contains one of the given strings.
func RequestHostIsIn ¶
func RequestHostIsIn(hosts ...string) ChainedHandler
RequestHostIsIn is a middleware that tests whether the host to which the request is directed to equal to one of the given strings.
This matcher supersedes and combines DstHostIs and ReqHostIs.
func RequestHostIsNotIn ¶
func RequestHostIsNotIn(hosts ...string) ChainedHandler
func RespContentTypeIs ¶
func RespContentTypeIs(types ...string) ChainedHandler
RespContentTypeIs is a middleware to filter apply a handler only to those requests matching a given content-type.
imageHandler := HandlerFunc(func(ctx *ProxyCtx) Next { ... convert ctx.Resp.Body, reinject a new Body with a png, and change the Content-Type return FORWARD // side-steps further modifications // or return NEXT // to continue on with other Handlers } proxy.HandleRequest(RespContentTypeIs("image/jpeg", "image/gif")(imageHandler))
func UrlHasPrefix ¶
func UrlHasPrefix(prefix string) ChainedHandler
UrlHasPrefix is a middleware matching when the destination URL the proxy client has requested has the given prefix, with or without the host.
For example UrlHasPrefix("host/x") will match requests of the form 'GET host/x', and will match requests to url 'http://host/x'
func UrlIsIn ¶
func UrlIsIn(urls ...string) ChainedHandler
UrlIsIn is a middleware that tests if the URL matches `urls`, testing whether or not the request URL is one of the given strings with or without the host prefix.
UrlIsIn("google.com/","foo") will match these three cases: * 'GET /' with 'Host: google.com' * 'GET google.com/' * 'GET /foo' for any host
func UrlMatches ¶
func UrlMatches(re *regexp.Regexp) ChainedHandler
UrlMatches returns a ReqCondition testing whether the destination URL of the request matches the given regexp, with or without prefix
type CounterEncryptorRand ¶
type CounterEncryptorRand struct {
// contains filtered or unexported fields
}
func NewCounterEncryptorRandFromKey ¶
func NewCounterEncryptorRandFromKey(key interface{}, seed []byte) (r CounterEncryptorRand, err error)
func (*CounterEncryptorRand) Read ¶
func (c *CounterEncryptorRand) Read(b []byte) (n int, err error)
func (*CounterEncryptorRand) Seed ¶
func (c *CounterEncryptorRand) Seed(b []byte)
type GoproxyConfig ¶
type GoproxyConfig struct { Root *x509.Certificate *tls.Config // contains filtered or unexported fields }
Config is a set of configuration values that are used to build TLS configs capable of MITM.
var GoproxyCaConfig *GoproxyConfig
func LoadCAConfig ¶
func LoadCAConfig(caCert, caKey []byte) (*GoproxyConfig, error)
Load a CAConfig bundle from by arrays. You can then load them into the proxy with `proxy.SetMITMCertConfig`
func NewConfig ¶
func NewConfig(ca *x509.Certificate, privateKey interface{}) (*GoproxyConfig, error)
NewConfig creates a MITM config using the CA certificate and private key to generate on-the-fly certificates.
type Handler ¶
func IsLocalhost ¶
IsLocalhost checks whether the destination host is explicitly local host (buggy, there can be IPv6 addresses it doesn't catch)
func IsNotLocalhost ¶
type HandlerFunc ¶
func (HandlerFunc) Handle ¶
func (f HandlerFunc) Handle(ctx *ProxyCtx) Next
type Next ¶
type Next int
Next indicates the return values possible for handlers.
In `request` handlers, `NEXT` means continue to the next handler. If none are left, it continues on with `FORWARD`. If you return `FORWARD`, then you skip all the other registered request handlers, and forward the request directly to the remote server, unless you've set a `ctx.Resp` before, in which case the response is sent back without touching any Response Handlers. If you return `REJECT`, the library will return a 502 error to the requester. In the `request` handlers, returning `MITM` will panic.
In Response handlers, `NEXT` means continue with the other registered handlers. If this was the last, the library will finish the forwarding of the current `ctx.Resp`. When `DONE` is returned, the library doesn't do anything else. It assumes you have properly written to `ctx.ResponseWriter` with a proper response (along with `ctx.Req`, this would resemble closely native `net/http` request handling). When `FORWARD` is returned, the lib jumps directly to the forwarding step, instead of going through the other response handlers. When `MITM` is returned, the lib will panic. When `REJECT` is returned, the lib will panic also. You can reject a request, but not a response.
In Connect handlers, `NEXT` means continue on with the next Connect handler. `FORWARD` means continue on with forwarding the raw TCP socket. `MITM` means jump in the middle and try to man-in-the-middle the connection. With the `MITM` option, all future requests to be detected from within the tunnel will trigger the Request handlers, in the order they were registered, just like a normal request arriving directly outside a tunnel. Those requests that are MITM will have the `ctx.IsThroughMITM` property set to `true`. Returning `REJECT` will reject the connection altogether. If you did sniff with `SNIHost()`, then the lib will forcefully close the connection, violating the protocol (you wanted to sniff, so it's your fault, right ? :). If you didn't sniff SNI, then a `502 Rejected` will be sent propertly to the client before closing the connection. `DONE` is not valid in that context, you need take a decision.
type ProxyCtx ¶
type ProxyCtx struct { Method string SourceIP string IsSecure bool // Whether we are handling an HTTPS request with the client IsThroughMITM bool // Whether the current request is currently being MITM'd IsThroughTunnel bool // Whether the current request is going through a CONNECT tunnel, doing HTTP calls (non-secure) MITMCertConfig *GoproxyConfig // OriginalRequest holds a copy of the request before doing some HTTP tunnelling through CONNECT, or doing a man-in-the-middle attack. OriginalRequest *http.Request // Will contain the client request from the proxy Req *http.Request ResponseWriter http.ResponseWriter // Connections, up (the requester) and downstream (the server we forward to) Conn net.Conn // Resp constains the remote sever's response (if available). This can be nil if the request wasn't sent yet, or if there was an error trying to fetch the response. In this case, refer to `ResponseError` for the latest error. Resp *http.Response // ResponseError contains the last error, if any, after running `ForwardRequest()` explicitly, or implicitly forwarding a request through other means (like returning `FORWARD` in some handlers). ResponseError error // RoundTripper is used to send a request to a remote server when // forwarding a Request. If you set your own RoundTripper, then // `FakeDestinationDNS` and `LogToHARFile` will have no effect. RoundTripper RoundTripper // will contain the recent error that occured while trying to send receive or parse traffic Error error // UserObjects and UserData allow you to keep data between // Connect, Request and Response handlers. UserObjects map[string]interface{} UserData map[string]string // Will connect a request to a response Session int64 // contains filtered or unexported fields }
ProxyCtx is the Proxy context, contains useful information about every request. It is passed to every user function. Also used as a logger.
func (*ProxyCtx) BufferResponse ¶
BufferResponse reads the whole Resp.Body and returns a byte array. It is the caller,s responsibility to set a new Body with `SetResponseBody` afterwards. Otherwise, the Resp.Body will be in a closed state and that is not fun for other parts of your program. This replaces the need for goproxy's previous `HandleBytes` implementation.
func (*ProxyCtx) Charset ¶
Will try to infer the character set of the request from the headers. Returns the empty string if we don't know which character set it used. Currently it will look for charset=<charset> in the Content-Type header of the request.
func (*ProxyCtx) DispatchDoneHandlers ¶
func (*ProxyCtx) DispatchResponseHandlers ¶
func (*ProxyCtx) FakeDestinationDNS ¶
FakeDestinationDNS will force a connection to the specified host/ip instead of the normal DNS resolution of the `SetDestinationHost()`. This will assume the destination server will answer as if it was ctx.Host().
If you specify a port, it will also serve in the redirection, otherwise the port from `ctx.Host()` will be used.
func (*ProxyCtx) FlushHARToDisk ¶
func (*ProxyCtx) ForwardConnect ¶
func (*ProxyCtx) ForwardRequest ¶
func (*ProxyCtx) HijackConnect ¶
func (*ProxyCtx) Host ¶
Host() returns the "host:port" to which your request will be forwarded. For a CONNECT request, it is preloaded with the original request's "host:port". For other methods, it is preloaded with the request's host and an added port based on the scheme (unless the port was specified).
If you sniff the SNI host with `ctx.SNIHost()`, it will alter the value returned by `Host()` to reflect what was sniffed. You need that to properly MITM secure CONNECT calls, otherwise the remote end will always fail to recognize the certificates this lib signs on-the-fly.
You can alter this value with `SetDestinationHost()`.
func (*ProxyCtx) LogToHARFile ¶
LogToHARFile collects all the content from the Request/Response roundtrip and stores it in memory until you call `FlushHARToDisk(filename)`.. at which point it will all be flushed to disk in HAR file format.
LogToHARFile alwasy returns `NEXT`.
func (*ProxyCtx) Logf ¶
Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter This message will be printed only if the Verbose field of the ProxyHttpServer is set to true
proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ nr := atomic.AddInt32(&counter,1) ctx.Printf("So far %d requests",nr) return r, nil })
func (*ProxyCtx) ManInTheMiddle ¶
ManInTheMiddle triggers either a full-fledged MITM when done through HTTPS, otherwise, simply tunnels future HTTP requests through the CONNECT stream, dispatching calls to the Request Handlers
func (*ProxyCtx) ManInTheMiddleHTTPS ¶
ManIntheMiddleHTTPS assumes we're dealing with an TLS-wrapped CONNECT tunnel. It will perform a full-blown man-in-the-middle attack, and forward any future requests received from inside the TSL tunnel to the Request Handlers.
Requests in there will be marked `IsSecure = true` (although, you and me know it's not *totally* secure, huh ?). They will also have the `ctx.IsThroughMITM` flag set to true.
The `ctx.OriginalRequest` will also hold the original CONNECT request from which the tunnel originated.
func (*ProxyCtx) NewHTMLResponse ¶
func (*ProxyCtx) NewResponse ¶
func (*ProxyCtx) NewTextResponse ¶
func (*ProxyCtx) RejectConnect ¶
func (ctx *ProxyCtx) RejectConnect()
func (*ProxyCtx) SNIHost ¶
SNIHost will try preempt the TLS handshake and try to sniff the Server Name Indication. It returns `Host()` for non CONNECT requests, so it is always safe to call. If it sniffed successfully, but didn't find anything, it is possible to return an empty string.
func (*ProxyCtx) SetConnectScheme ¶
SetConnectScheme determines how to interprete the TCP conversation following a CONNECT request. `scheme` can be "http" or "https". By default, it uses a simple heuristic: "http" if CONNECT asked for port 80, otherwise it always assumes "https" when trying to man-in-the-middle. Call this before returning `MITM` from Connect Handlers.
func (*ProxyCtx) SetDestinationHost ¶
SetDestinationHost sets the "host:port" to which you want to FORWARD or MITM a CONNECT request. Otherwise defaults to what was in the `CONNECT` request. If you call `SNIHost()` to sniff SNI, then this will override the destination host automatically.
If you want to alter the destination host of a *Request* that goes through a tunnel you can eavesdrop, modify `ctx.Req.URL.Host`, the RoundTrip will go to that address, even though the `ctx.Req.Host` is used as the `Host:` header. You can identify those requests with `ctx.IsThroughMITM` or `ctx.IsThroughTunnel`.
func (*ProxyCtx) SetResponseBody ¶
SetResponseBody overwrites the Resp.Body with the given content. It is the caller's responsibility to ensure the previous Body was read and/or closed properly. Use `BufferResponse()` for that. This call will fail if ctx.Resp is nil.
func (*ProxyCtx) TunnelHTTP ¶
TunnelHTTP assumes the current connection is a plain HTTP tunnel, with no security. It then dispatches all future requests in there through the registered Request Handlers.
Requests flowing through this tunnel will be marked `ctx.IsThroughTunnel == true`.
You can also find the original CONNECT request in `ctx.OriginalRequest`.
func (*ProxyCtx) Warnf ¶
Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter This message will always be printed.
proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ f,err := os.OpenFile(cachedContent) if err != nil { ctx.Warnf("error open file %v: %v",cachedContent,err) return r, nil } return r, nil })
type ProxyHttpServer ¶
type ProxyHttpServer struct { // setting Verbose to true will log information on each request sent to the proxy Verbose bool // SniffSNI enables sniffing Server Name Indicator when doing CONNECT calls. It will thus answer to CONNECT calls with a "200 OK" even if the remote server might not answer. The result would be the shutdown of the connection instead of an appropriate HTTP error code if the remote node doesn't answer. SniffSNI bool Logger *log.Logger // NonProxyHandler will be used to handle direct connections to the proxy. You can assign an `http.ServeMux` or some other routing libs here. The default will return a 500 error saying this is a proxy and has nothing to serve by itself. NonProxyHandler http.Handler // Custom transport to be used Transport *http.Transport // Setting MITMCertConfig allows you to override the default CA cert/key used to sign MITM'd requests. MITMCertConfig *GoproxyConfig // ConnectDial will be used to create TCP connections for CONNECT requests // if nil, .Transport.Dial will be used ConnectDial func(network string, addr string) (net.Conn, error) // contains filtered or unexported fields }
The basic proxy type. Implements http.Handler.
func NewProxyHttpServer ¶
func NewProxyHttpServer() *ProxyHttpServer
New proxy server, logs to StdErr by default
func (*ProxyHttpServer) FlushHARToDisk ¶
func (proxy *ProxyHttpServer) FlushHARToDisk(filename string)
func (*ProxyHttpServer) HandleConnect ¶
func (proxy *ProxyHttpServer) HandleConnect(f Handler)
func (*ProxyHttpServer) HandleConnectFunc ¶
func (proxy *ProxyHttpServer) HandleConnectFunc(f func(ctx *ProxyCtx) Next)
HandleConnectFunc and HandleConnect mimic the `net/http` handlers, and register handlers for CONNECT proxy calls.
See `Next` values for the return value meaning
func (*ProxyHttpServer) HandleDone ¶
func (proxy *ProxyHttpServer) HandleDone(f Handler)
func (*ProxyHttpServer) HandleDoneFunc ¶
func (proxy *ProxyHttpServer) HandleDoneFunc(f func(ctx *ProxyCtx) Next)
HandleDoneFunc and HandleDone are called at the end of every request. Use them to cleanup.
See `Next` values for the return value meaning
func (*ProxyHttpServer) HandleRequest ¶
func (proxy *ProxyHttpServer) HandleRequest(f Handler)
func (*ProxyHttpServer) HandleRequestFunc ¶
func (proxy *ProxyHttpServer) HandleRequestFunc(f func(ctx *ProxyCtx) Next)
HandleRequestFunc and HandleRequest put hooks to handle certain requests. Note that MITM'd and HTTP requests that go through a CONNECT'd connection also go through those Request Handlers.
See `Next` values for the return value meaning
func (*ProxyHttpServer) HandleResponse ¶
func (proxy *ProxyHttpServer) HandleResponse(f Handler)
func (*ProxyHttpServer) HandleResponseFunc ¶
func (proxy *ProxyHttpServer) HandleResponseFunc(f func(ctx *ProxyCtx) Next)
HandleResponseFunc and HandleResponse put hooks to handle certain requests. Note that MITM'd and HTTP requests that go through a CONNECT'd connection also go through those Response Handlers.
See `Next` values for the return value meaning
func (*ProxyHttpServer) ListenAndServe ¶
func (proxy *ProxyHttpServer) ListenAndServe(addr string) error
ListenAndServe launches all the servers required and listens. Use this method if you want to start listeners for transparent proxying.
func (*ProxyHttpServer) Logf ¶
func (proxy *ProxyHttpServer) Logf(msg string, v ...interface{})
func (*ProxyHttpServer) NewConnectDialToProxy ¶
func (*ProxyHttpServer) ServeHTTP ¶
func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request)
Standard net/http function. Shouldn't be used directly, http.Serve will use it.
func (*ProxyHttpServer) SetMITMCertConfig ¶
func (proxy *ProxyHttpServer) SetMITMCertConfig(config *GoproxyConfig)
SetMITMCertConfig sets the CA Config to be used to sign man-in-the-middle'd certificates. You can load some []byte with `LoadCAConfig()`. This bundle gets passed into the `ProxyCtx` and may be overridden in the [TODO: FIXME] `HandleConnect()` callback, before doing SNI sniffing.
type RoundTripper ¶
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
examples
|
|
goproxy-yui-minify
This example would minify standalone Javascript files (identified by their content type) using the command line utility YUI compressor http://yui.github.io/yuicompressor/ Example usage: ./yui -java /usr/local/bin/java -yuicompressor ~/Downloads/yuicompressor-2.4.8.jar $ curl -vx localhost:8080 http://golang.org/lib/godoc/godocs.js (function(){function g(){var u=$("#search");if(u.length===0){return}function t(){if(....
|
This example would minify standalone Javascript files (identified by their content type) using the command line utility YUI compressor http://yui.github.io/yuicompressor/ Example usage: ./yui -java /usr/local/bin/java -yuicompressor ~/Downloads/yuicompressor-2.4.8.jar $ curl -vx localhost:8080 http://golang.org/lib/godoc/godocs.js (function(){function g(){var u=$("#search");if(u.length===0){return}function t(){if(.... |
ext
|
|
html
extension to goproxy that will allow you to easily filter web browser related content.
|
extension to goproxy that will allow you to easily filter web browser related content. |