Skip to content
An HTTP proxy library for Go
Go HTML Shell
Branch: master
Clone or download

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
certs fixes #208, fixes #188, new CA for goproxy, with file that generates … Apr 5, 2017
examples WebSocket Support (#1) Oct 11, 2019
ext Add go.mod to ext/ pkg, run go mod tidy Apr 10, 2019
regretable all: gofmt Jun 16, 2018
test_data move test data to its own dir Mar 25, 2012
transport Removed unreacheble code, renamed receiver Oct 20, 2018
.gitignore .gitignore, ./all.bash more organized Mar 28, 2012
LICENSE by @ancientlore email request, adding LICENSE file Apr 6, 2013
README.md Update README.md (#337) Apr 21, 2019
actions.go fix minor typo in docs Aug 22, 2014
all.bash move regret buffer to package, improve Jan 23, 2013
ca.pem Update the certificate files to match the contents of certs.go. Apr 13, 2017
certs.go fixes #208, fixes #188, new CA for goproxy, with file that generates … Apr 5, 2017
chunked.go gofmt Nov 14, 2013
counterecryptor.go Add support for signing with ecdsa keys Jul 3, 2019
counterecryptor_test.go Add support for signing with ecdsa keys Jul 3, 2019
ctx.go Switch CertStorage interface to single function Mar 30, 2019
dispatcher.go Allow SrcIpIs to accept multiple parameters. Oct 13, 2015
doc.go Update return response example to follow current API Jun 30, 2019
go.mod Update module info (go mod tidy) Sep 11, 2019
go.sum Update module info (go mod tidy) Sep 11, 2019
https.go improvement: more general support for half-closable connections Feb 20, 2020
key.pem Update the certificate files to match the contents of certs.go. Apr 13, 2017
logger.go added logger interface to allow usage of custom loggers Jan 20, 2019
proxy.go WebSocket Support (#1) Oct 11, 2019
proxy_test.go Issue: #345 - fixes resp == nil: Jul 11, 2019
responses.go Add status text based on status code on new HTTP responses Jul 30, 2018
signer.go Use random numbers for certificate serials Sep 11, 2019
signer_test.go Add support for signing with ecdsa keys Jul 3, 2019
websocket.go WebSocket Support (#1) Oct 11, 2019

README.md

Introduction

GoDoc Join the chat at https://gitter.im/elazarl/goproxy

Package goproxy provides a customizable HTTP proxy library for Go (golang),

It supports regular HTTP proxy, HTTPS through CONNECT, and "hijacking" HTTPS connection using "Man in the Middle" style attack.

The intent of the proxy is to be usable with reasonable amount of traffic, yet customizable and programmable.

The proxy itself is simply a net/http handler.

In order to use goproxy, one should set their browser to use goproxy as an HTTP proxy. Here is how you do that in Chrome and in Firefox.

For example, the URL you should use as proxy when running ./bin/basic is localhost:8080, as this is the default binding for the basic proxy.

Mailing List

New features will be discussed on the mailing list before their development.

Latest Stable Release

Get the latest goproxy from gopkg.in/elazarl/goproxy.v1.

Why not Fiddler2?

Fiddler is an excellent software with similar intent. However, Fiddler is not as customizable as goproxy intends to be. The main difference is, Fiddler is not intended to be used as a real proxy.

A possible use case that suits goproxy but not Fiddler, is gathering statistics on page load times for a certain website over a week. With goproxy you could ask all your users to set their proxy to a dedicated machine running a goproxy server. Fiddler is a GUI app not designed to be run like a server for multiple users.

A taste of goproxy

To get a taste of goproxy, a basic HTTP/HTTPS transparent proxy

package main

import (
    "github.com/elazarl/goproxy"
    "log"
    "net/http"
)

func main() {
    proxy := goproxy.NewProxyHttpServer()
    proxy.Verbose = true
    log.Fatal(http.ListenAndServe(":8080", proxy))
}

This line will add X-GoProxy: yxorPoG-X header to all requests sent through the proxy

proxy.OnRequest().DoFunc(
    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {
        r.Header.Set("X-GoProxy","yxorPoG-X")
        return r,nil
    })

DoFunc will process all incoming requests to the proxy. It will add a header to the request and return it. The proxy will send the modified request.

Note that we returned nil value as the response. Had we returned a response, goproxy would have discarded the request and sent the new response to the client.

In order to refuse connections to reddit at work time

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

DstHostIs returns a ReqCondition, that is a function receiving a Request and returning a boolean. We will only process requests that match the condition. DstHostIs("www.reddit.com") will return a ReqCondition accepting only requests directed to "www.reddit.com".

DoFunc will receive a function that will preprocess the request. We can change the request, or return a response. If the time is between 8:00am and 17:00pm, we will reject the request, and return a precanned text response saying "do not waste your time".

See additional examples in the examples directory.

Type of handlers for manipulating connect/req/resp behavior

There are 3 kinds of useful handlers to manipulate the behavior, as follows:

// handler called after receiving HTTP CONNECT from the client, and before proxy establish connection 
// with destination host
httpsHandlers   []HttpsHandler
    
// handler called before proxy send HTTP request to destination host
reqHandlers     []ReqHandler 
    
// handler called after proxy receives HTTP Response from destination host, and before proxy forward 
// the Response to the client.
respHandlers    []RespHandler 

Depending on what you want to manipulate, the ways to add handlers to each handler list are:

// 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())

For example:

// This rejects the HTTPS request to *.reddit.com during HTTP CONNECT phase
proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("reddit.*:443$"))).HandleConnect(goproxy.RejectConnect)

// This will NOT reject the HTTPS request with URL ending with gif, due to the fact that proxy 
// only got the URL.Hostname and URL.Port during the HTTP CONNECT phase if the scheme is HTTPS, which is
// quiet common these days.
proxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).HandleConnect(goproxy.RejectConnect)

// The correct way to manipulate the HTTP request using URL.Path as condition is:
proxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).Do(YourReqHandlerFunc())

What's New

  1. Ability to Hijack CONNECT requests. See the eavesdropper example
  2. Transparent proxy support for http/https including MITM certificate generation for TLS. See the transparent example.

License

I put the software temporarily under the Go-compatible BSD license. If this prevents someone from using the software, do let me know and I'll consider changing it.

At any rate, user feedback is very important for me, so I'll be delighted to know if you're using this package.

Beta Software

I've received positive feedback from a few people who use goproxy in production settings. I believe it is good enough for usage.

I'll try to keep reasonable backwards compatibility. In case of a major API change, I'll change the import path.

You can’t perform that action at this time.