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/abourget/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/abourget/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/abourget/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/abourget/goproxy/tree/master/examples/goproxy-jquery-version
Will warn if multiple versions of jquery are used in the same domain.
6. https://github.com/abourget/goproxy/blob/master/examples/goproxy-upside-down-ternet/
Modifies image files in an HTTP response via goproxy's image extension found in ext/.
RLS 8/31/2018 A responsewriter that will pass headers back to the underlying connection. Based on dumbresponsewriter.
6-29-2017 RLS - Added Tlsfailure method so callers can subscribe to TLS handshake failures 7011-2017 RLS - Added tproxy support to capture the original destination of https requests. This enables support for non-SNI clients.
Responsible for signing certificates based on Winston root certificate. * TODO: Check validity of certificates on first load rather than simply passing them on blindly to clients.
Index ¶
- Constants
- Variables
- func CondRemoteAddrIs(ctx *ProxyCtx, ip string) bool
- func GenerateSignature(h *vhost.ClientHelloMsg, debug bool) string
- func GetSubdomains(domain string) []string
- func HijackedDNSDialer() *net.Dialer
- func HostsToMap(hosts ...string) map[string]bool
- func IsExternal(hostname string) bool
- func LoadDefaultConfig() error
- 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
- func WhitelistedDNSDialer() *net.Dialer
- 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 GoproxyConfigServer
- type Handler
- type HandlerFunc
- type HostInfo
- type IdleTimeoutConn
- func (idleconn *IdleTimeoutConn) Close() error
- func (idleconn *IdleTimeoutConn) LocalAddr() net.Addr
- func (idleconn *IdleTimeoutConn) Read(buf []byte) (int, error)
- func (idleconn *IdleTimeoutConn) RemoteAddr() net.Addr
- func (idleconn *IdleTimeoutConn) SetDeadline(t time.Time) error
- func (idleconn *IdleTimeoutConn) SetReadDeadline(t time.Time) error
- func (idleconn *IdleTimeoutConn) SetWriteDeadline(t time.Time) error
- func (idleconn *IdleTimeoutConn) Write(buf []byte) (int, error)
- type Next
- type NonHTTPRoundTripper
- 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) ForwardNonHTTPRequest(host string) 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(level uint16, msg string, argv ...interface{})
- func (ctx *ProxyCtx) ManInTheMiddle() error
- func (ctx *ProxyCtx) ManInTheMiddleHTTPS() error
- func (ctx *ProxyCtx) NewEmptyGif()
- func (ctx *ProxyCtx) NewEmptyImage(extension string)
- func (ctx *ProxyCtx) NewEmptyPng()
- func (ctx *ProxyCtx) NewEmptyScript()
- func (ctx *ProxyCtx) NewHTMLResponse(body string)
- func (ctx *ProxyCtx) NewResponse(status int, contentType, body string)
- func (ctx *ProxyCtx) NewTextResponse(body string)
- func (ctx *ProxyCtx) RecordStatus(msg 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) SetRequestBody(req *http.Request, body io.Reader) error
- func (ctx *ProxyCtx) SetResponseBody(content []byte)
- func (ctx *ProxyCtx) TunnelHTTP() error
- func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{})
- type ProxyHttpServer
- func (proxy *ProxyHttpServer) BufferLogEntry(signature, entry string)
- func (proxy *ProxyHttpServer) DispatchRequestHandlers(ctx *ProxyCtx)
- func (proxy *ProxyHttpServer) FlushHARToDisk(filename string)
- func (proxy *ProxyHttpServer) GetLogEntries(signature string) []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) LastSignature() string
- func (proxy *ProxyHttpServer) ListenAndServe(addr string) error
- func (proxy *ProxyHttpServer) ListenAndServeTLS(httpsAddr string) error
- func (proxy *ProxyHttpServer) Logf(level uint16, msg string, v ...interface{})
- func (proxy *ProxyHttpServer) NewConnectDialToProxy(https_proxy string) func(network, addr string) (net.Conn, error)
- func (proxy *ProxyHttpServer) NewConnectDialToProxyContext(https_proxy string) func(ctx context.Context, network, addr string) (net.Conn, error)
- func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (proxy *ProxyHttpServer) SetMITMCertConfig(config *GoproxyConfigServer)
- func (proxy *ProxyHttpServer) SetShadowNetwork(sn *shadownetwork.ShadowNetwork)
- func (proxy *ProxyHttpServer) SetSignature(signature string)
- func (proxy *ProxyHttpServer) TestConnectDialContext(ctx context.Context, network, addr string) (c net.Conn, err error)
- type RequestTracer
- type RoundTripper
- type RoundTripperFunc
- type SpyConnection
- type TraceInfo
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 SIGNATURE // Return the client TLS signature (RLS 3-5-2018) )
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-----
MIIChTCCAe6gAwIBAgIBADANBgkqhkiG9w0BAQsFADA2MQswCQYDVQQGEwJVUzEQ
MA4GA1UECgwHV2luc3RvbjEVMBMGA1UEAwwMd2luc3Rvbi5jb25mMB4XDTE4MDIy
MzE4NTExNVoXDTM4MDIxODE4NTExNVowNjELMAkGA1UEBhMCVVMxEDAOBgNVBAoM
B1dpbnN0b24xFTATBgNVBAMMDHdpbnN0b24uY29uZjCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAu+LAQcFv/kIbgTPdmFmIcdFVvIONOiK6yWfjObQBwJOaRuZx
FgfojIFdRmm4SvOEhQp+/FZQQwHunDXy1ICNuEGveJyxxVh+FKfhKvwa7HcejZRe
z9BCun4vtSyOBMFkBn/oXKkK3zG7hZKsAjZiftO2m2CKTpR7mRVZHzoFDXMCAwEA
AaOBojCBnzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy
YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUcDIKYDmsRzhFGibcyJ0tCX9OYZYw
HwYDVR0jBBgwFoAUV9oF/beeIssH3fAByRVyt8Mh+kIwFwYDVR0RBBAwDoIMd2lu
c3Rvbi5jb25mMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOBgQCEhewUly9a
+LGp3HN0JagOk96cD13fmCTTzCtZH6jPXVoV1li2eQqI1UOxSqAnYD9D/KWqKkPg
zngMDIDjRXBIIMlGldKcPqC6/xKQxavGDZV4dvqRByKfPAJoam66nfN0vNaGS6dF
sCs4ajBfOFjOd62D1lpyKXFyW3dt2rxacg==
-----END CERTIFICATE-----`)
var CA_KEY = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC74sBBwW/+QhuBM92YWYhx0VW8g406IrrJZ+M5tAHAk5pG5nEW
B+iMgV1GabhK84SFCn78VlBDAe6cNfLUgI24Qa94nLHFWH4Up+Eq/Brsdx6NlF7P
0EK6fi+1LI4EwWQGf+hcqQrfMbuFkqwCNmJ+07abYIpOlHuZFVkfOgUNcwIDAQAB
AoGAYoxp+VOD8aItGRTiS1HS7pg1Vz7NKcwjmxahqZeQP7lr93pRoJOfV2tXSGKV
ZsLaJIo/1w1S5gKybD8j0nBnZHGnE+5eViuAwWLmHrcQo2Zx8Wsd1ooQce/UsL27
PjimImkLdLrCDPnavD2jrInZtWKfgP0QpaC1OyW3WHlR5OkCQQD0lnF5fbCPWpLy
qCKEQrPxVugf+sccEJ5u8Zww6MWIU8a5/299WsJL8WolnyM+xsZs7+bnx66PUjMR
FO30zDbFAkEAxKcDY2HNripMpg5uG23EGUcqvtjADnTxATrFl72OIpAHaxGsEowu
iJERWNbJnKr0p6Z0JyA/PX5yixpf5ne21wJBAJXaatHNwVRDYQ8NFoDEQW1XGscl
JcK7J+a/XzvUEdpxwasJpmw+JBbVZXyBYN3Aeaga3/UYMYocCa+ojBZU3CUCQGLd
ZEKuhO0uruI9FvYLNS9QLBlOdx/NguyPU4956N9PcatOcyfP+gUGiaYUNb/h4qX2
dSbGe4S68XMli1kejnkCQFNo6CZx31jiy57J5rjJZE6LM7OtSTBtSYJ3aE1ZUPnk
6fjNzFMU+APTWib1YsZQF/mrVh9q52CkA5Nnwpxfkjc=
-----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).
var NonHTTPRequest = "nonhttprequest"
var OrganizationName = "Winston Privacy, Inc."
OrganizationName is the name your CA cert will be signed with. It will show in your different UIs. Change it globally here to show meaningful things to your users.
Functions ¶
func CondRemoteAddrIs ¶
func GenerateSignature ¶
func GetSubdomains ¶
Returns a list of more general subdomains down to the TLDPlusOne, including the original. ie: "a.b.example.com" returns "a.b.example.com", "b.example.com" and "example.com" Returns most specific to least specific
func HijackedDNSDialer ¶
Returns a DNS dialer which can bypass local DNS
func HostsToMap ¶
func IsExternal ¶
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 })))
func WhitelistedDNSDialer ¶
Returns a DNS dialer for port 54 (unfiltered DNS which allows all requests to succeed) TODO: Should we check for DNS server on port 54 and default to port 53 if not available? For now, caller is responsible for this.
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 GoproxyConfigServer ¶
type GoproxyConfigServer struct { Root *x509.Certificate RootCAs *x509.CertPool Host map[string]*HostInfo //Config map[string] IsExternal func(string) bool // contains filtered or unexported fields }
Maintains a global list of immutable TLS Configs which can be used for TLS handshakes.
var GoproxyCaConfig *GoproxyConfigServer
func LoadCAConfig ¶
func LoadCAConfig(filename string, caCert, caKey []byte) (*GoproxyConfigServer, error)
Load a CAConfig bundle from by arrays. You can then load them into the proxy with `proxy.SetMITMCertConfig. If filename is non-nil, will attempt to load from disk.
func NewConfigServer ¶
func NewConfigServer(filename string, ca *x509.Certificate, privateKey interface{}) (*GoproxyConfigServer, error)
NewConfig creates a MITM config using the CA certificate and private key to generate on-the-fly certificates.
func (*GoproxyConfigServer) Cert ¶
func (c *GoproxyConfigServer) Cert(hostname string) (*tls.Config, error)
RLS 3/19/2018 - exported for testng
func (*GoproxyConfigServer) FlushCert ¶
func (c *GoproxyConfigServer) FlushCert(hostname string)
Removes the certificate associated with the given hostname from the cache. This is necessary if we change the whitelist or blacklist settings for a domain.
func (*GoproxyConfigServer) GetTestCertificate ¶
Used for unit testing. Gets a certificate from a server and port and creates a local version suitable for MITM.
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 HostInfo ¶
type HostInfo struct { LastVerify time.Time NextAttempt time.Time // Set to future time for invalid certs to avoid frequent reloading Config *tls.Config // contains filtered or unexported fields }
Stores metadata about a particular host. Used to improve performance.
type IdleTimeoutConn ¶
Wraps net.conn to enforce idle connection timeout during io.Copy().
func (*IdleTimeoutConn) Close ¶
func (idleconn *IdleTimeoutConn) Close() error
func (*IdleTimeoutConn) LocalAddr ¶
func (idleconn *IdleTimeoutConn) LocalAddr() net.Addr
func (*IdleTimeoutConn) RemoteAddr ¶
func (idleconn *IdleTimeoutConn) RemoteAddr() net.Addr
func (*IdleTimeoutConn) SetDeadline ¶
func (idleconn *IdleTimeoutConn) SetDeadline(t time.Time) error
func (*IdleTimeoutConn) SetReadDeadline ¶
func (idleconn *IdleTimeoutConn) SetReadDeadline(t time.Time) error
func (*IdleTimeoutConn) SetWriteDeadline ¶
func (idleconn *IdleTimeoutConn) SetWriteDeadline(t time.Time) error
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 NonHTTPRoundTripper ¶
type NonHTTPRoundTripper struct { // TLSClientConfig specifies the TLS configuration to use with // tls.Client. // Must be non-nil TLSClientConfig *tls.Config // TLSHandshakeTimeout specifies the maximum amount of time waiting to // wait for a TLS handshake. Zero means no timeout. TLSHandshakeTimeout time.Duration // DialContext must be non-nil. The caller is responsible for providing this function. DialContext func(ctx context.Context, network string, addr string) (net.Conn, error) MaxResponseHeaderBytes int64 ExpectContinueTimeout time.Duration ResponseHeaderTimeout time.Duration // contains filtered or unexported fields }
func (*NonHTTPRoundTripper) CancelRequest
deprecated
func (t *NonHTTPRoundTripper) CancelRequest(req *http.Request)
CancelRequest cancels an in-flight request by closing its connection. CancelRequest should only be called after RoundTrip has returned.
Deprecated: Use Request.WithContext to create a request with a cancelable context instead. CancelRequest cannot cancel HTTP/2 requests.
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) IsNonHttpProtocol bool // Set to true if a MITM request is determined to not be a HTTP 1.0-1.2 protocol. NonHTTPRequest []byte // The original request if a non non-HTTP protocol is detected MITMCertConfig *GoproxyConfigServer // 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 // Contains the request and response streams from the proxy to the // downstream server in the case of a MITM connection Req *http.Request ResponseWriter http.ResponseWriter // Connections, up (the requester) and downstream (the server we forward to) Conn net.Conn // Resp contains 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. // RLS: In the case of MITM, this is the client's response stream 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 Proxy *ProxyHttpServer // Closure to alert listeners that a TLS handshake failed // RLS 6-29-2017 Tlsfailure func(ctx *ProxyCtx, untrustedCertificate bool) // References to persistent caches for statistics collection // RLS 7-5-2017 IgnoreCounter bool // if true, this request won't be counted (used for streaming) // Client signature // https://blog.squarelemon.com/tls-fingerprinting/ CipherSignature string NewBodyLength int VerbosityLevel uint16 // 11/2/2017 - Used for replacement macros (user agents) DeviceType int Whitelisted bool // If true, response filtering will be completely disabled and local DNS will be bypassed. TimeRemaining int // Time remaining in sec for temporary whitelisting // Keeps a list of any messages we want to pass back to the client StatusMessage []string // Request handler sets this to true if it thinks it is a first party request FirstParty bool // Set to true to use private network PrivateNetwork bool RevealTimeRemaining int // Time remaining in sec for temporary uncloaking // If a shadow transport is being used, this points to it. ShadowTransport *shadownetwork.ShadowTransport // If true, then Winston diagnostic information will be recorded about the current request Trace traceRequest TraceInfo *TraceInfo // Information about the original request/response SkipRequestHandler bool // If set to true, then response handler will be skipped SkipResponseHandler bool // If set to true, then response handler will be skipped RequestTime time.Time // Time the request was started. Useful for debugging. Referrer string // Referrer taken from HTTP request. Used for logging. CookiesModified int // # of cookies blocked or modified for the current request. Used for logging. ElementsModified int // # of page elements removed or modified for the current request. Used for logging. // 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 ¶
This is used to pipe a request directly through to the target site back to the client via MITM. Note that we have to already have a connection to the remote server before calling.
func (*ProxyCtx) ForwardNonHTTPRequest ¶
Used to forward protocols that are "http-like" (ie: websockets). This method forwards the original HTTP request before fusing the connection, allowing further communication to take place (if none, it will close). TODO: Should we add websockets protocol support so we can inspect packets? TODO: Add P2P support
func (*ProxyCtx) ForwardRequest ¶
Forwards a request to a downstream server. This is done after MITM has been established. TODO: Remove host from function parameters
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
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) NewEmptyGif ¶
func (ctx *ProxyCtx) NewEmptyGif()
func (*ProxyCtx) NewEmptyImage ¶
func (*ProxyCtx) NewEmptyPng ¶
func (ctx *ProxyCtx) NewEmptyPng()
func (*ProxyCtx) NewEmptyScript ¶
func (ctx *ProxyCtx) NewEmptyScript()
Returns an empty script. This is done to be less obvious that we blocked it.
func (*ProxyCtx) NewHTMLResponse ¶
func (*ProxyCtx) NewResponse ¶
func (*ProxyCtx) NewTextResponse ¶
func (*ProxyCtx) RecordStatus ¶
Append a message to the context. This will be sent back to the client as a "Winston-Response" header.
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) SetRequestBody ¶
Grafts the provided io.Closer to the provided Request body. Request.Body will be consumed and closed by the native Golang Client methods Do, Post, and PostForm, and Transport.RoundTrip.
If body is of type *bytes.Buffer, *bytes.Reader, or *strings.Reader, the returned request's ContentLength is set to its exact value (instead of -1), GetBody is populated (so 307 and 308 redirects can replay the body), and Body is set to NoBody if the ContentLength is 0.
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`.
type ProxyHttpServer ¶
type ProxyHttpServer struct { // setting Verbose to true will log information on each request sent to the proxy Verbose bool // 0 (default) = Startup, service messages and command output only // 1 Serious Errors // 2 HTTP/HTTPS blocked // 3 HTTP/HTTPS OK // 4 White/Blacklisting decisions // 5 Image files // 6 Warnings // 7 Partial content (status code 206) ? // 8 ElementHiding matches // 9 Allowed/Blocked Statistics logging VerbosityLevel uint16 //int // 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 // Private transports //PrivateNetwork *shadowtransport.PrivateNetwork PrivateNetwork *shadownetwork.ShadowNetwork // Setting MITMCertConfig allows you to override the default CA cert/key used to sign MITM'd requests. MITMCertConfig *GoproxyConfigServer // 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) // RLS 2/15/2018 - New context version of ConnectDial ConnectDialContext func(ctx context.Context, network string, addr string) (net.Conn, error) // Callback function to determine if request should be traced. Trace func(ctx *ProxyCtx) traceRequest // Closure to alert listeners that a TLS handshake failed // RLS 6-29-2017 Tlsfailure func(ctx *ProxyCtx, untrustedCertificate bool) // Closure to give listeners a chance to service a request directly. Return true if handled. HandleHTTP func(ctx *ProxyCtx) bool // If set to true, then the next HTTP request will flush all idle connections. Will be reset to false afterwards. FlushIdleConnections bool // RoundTripper which supports non-http protocols NonHTTPRoundTripper *NonHTTPRoundTripper UpdateAllowedCounter func(string, string, string, int, int, int) UpdateBlockedCounter func(string, string, string, int, bool) UpdateWhitelistedCounter func(string, string, string, int) // 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) BufferLogEntry ¶
func (proxy *ProxyHttpServer) BufferLogEntry(signature, entry string)
func (*ProxyHttpServer) DispatchRequestHandlers ¶
func (proxy *ProxyHttpServer) DispatchRequestHandlers(ctx *ProxyCtx)
RLS 5/22/2018 - exported so that we can use it for unit testing
func (*ProxyHttpServer) FlushHARToDisk ¶
func (proxy *ProxyHttpServer) FlushHARToDisk(filename string)
func (*ProxyHttpServer) GetLogEntries ¶
func (proxy *ProxyHttpServer) GetLogEntries(signature string) []string
Retrieves the log entries for the given signature since the prior call. If there was no prior call, it begins buffering log entries for the next 30 seconds. The client must poll this function more frequently to obtain a complete log.
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) LastSignature ¶
func (proxy *ProxyHttpServer) LastSignature() string
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) ListenAndServeTLS ¶
func (proxy *ProxyHttpServer) ListenAndServeTLS(httpsAddr string) error
func (*ProxyHttpServer) Logf ¶
func (proxy *ProxyHttpServer) Logf(level uint16, msg string, v ...interface{})
RLS 8/16/2017 Logging now supports multiple levels of verbosity
func (*ProxyHttpServer) NewConnectDialToProxy ¶
func (*ProxyHttpServer) NewConnectDialToProxyContext ¶
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 *GoproxyConfigServer)
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.
func (*ProxyHttpServer) SetShadowNetwork ¶
func (proxy *ProxyHttpServer) SetShadowNetwork(sn *shadownetwork.ShadowNetwork)
Call after the private network has been initialized to have proxy automatically redirect requests through it. The proxy will simply forward requests through the local network until this is called.
func (*ProxyHttpServer) SetSignature ¶
func (proxy *ProxyHttpServer) SetSignature(signature string)
func (*ProxyHttpServer) TestConnectDialContext ¶
func (proxy *ProxyHttpServer) TestConnectDialContext(ctx context.Context, network, addr string) (c net.Conn, err error)
Don't use - this is for unit testing purposes only.
type RequestTracer ¶
type RequestTracer struct { Requests []traceRequest // contains filtered or unexported fields }
func (*RequestTracer) RequestTrace ¶
func (tr *RequestTracer) RequestTrace(cmd []string, seconds int)
Requests a trace. By default, will be disabled after two minutes if not triggered. [Host] -> Required
Optional parameters:
modified - display modified trace for next request only unmodified - display the original trace for next request only SkipRequest - skip request handling SkipResponse - skip response handling SkipInject - skip toolbar and monitor SkipPrivate - Bypass the private network SkipMonitor - Bypass the javascript monitor injection SkipToolbar - Bypass the toolbar injection code
func (*RequestTracer) Trace ¶
func (tr *RequestTracer) Trace(ctx *ProxyCtx) traceRequest
Returns a trace request if one has been registered for the given ctx
type RoundTripper ¶
type RoundTripperFunc ¶
type SpyConnection ¶
SpyConnection embeds a net.Conn, all reads and writes are output to stderr
type TraceInfo ¶
type TraceInfo struct { Name string // Will be printed out at beginning of trace output. RequestTime time.Time RequestDuration time.Duration // Time needed to complete the request RequestHeaders []string ResponseHeaders []string PrivateNetwork bool // If true, the request was cloaked MITM bool // if true, then we were able to intercept the request. Wil be false for clients which don't trust us. RoundTripError string // Errors recorded by roundtrip CookiesSent []string // Cookies sent with the request CookiesReceived []string // Cookies received from the server StatusCode int // status code of the server response ReqBody *[]byte // This is a copy of the original request body (used in POSTs) if needed to replay. Method *string // The original request method. // contains filtered or unexported fields }
Used to store information about a roundtrip.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
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. |
Instructions: The following code reproduces a real-world test case encountered in a production * Winston unit.
|
Instructions: The following code reproduces a real-world test case encountered in a production * Winston unit. |
Reproduces WINSTON-379 - Hashmap collision panics during TLS handshake.
|
Reproduces WINSTON-379 - Hashmap collision panics during TLS handshake. |