An HTTP proxy library for Go

Elazar Leibovich 2ce16c963a Merge pull request #303 from jgiannuzzi/add_status_text 2 months ago
certs c4fc26588b fixes #208, fixes #188, new CA for goproxy, with file that generates new ones 1 year ago
examples 9614ae7e72 Merge pull request #285 from liudanking/master 7 months ago
ext 63b166f257 all: gofmt 7 months ago
regretable 63b166f257 all: gofmt 7 months ago
test_data d40a3910ce move test data to its own dir 6 years ago
transport 29672965d1 Removed unreacheble code, renamed receiver 3 months ago
.gitignore 04f99139e9 .gitignore, ./all.bash more organized 6 years ago
LICENSE 6b09cc8b07 by @ancientlore email request, adding LICENSE file 5 years ago
README.md c42c8c09ee Fixed some typos in the README.md 3 months ago
actions.go 33be580eb8 fix minor typo in docs 4 years ago
all.bash ceca68a249 move regret buffer to package, improve 6 years ago
ca.pem e18c7b8430 Update the certificate files to match the contents of certs.go. 1 year ago
certs.go c4fc26588b fixes #208, fixes #188, new CA for goproxy, with file that generates new ones 1 year ago
chunked.go 623bafc29d gofmt 5 years ago
counterecryptor.go 623bafc29d gofmt 5 years ago
counterecryptor_test.go bbda9955e9 Fix issue 297: TestCounterEncStreamHistogram broken in go1.11. 6 months ago
ctx.go b55838031a Fix spelling error in ctx.go. 1 year ago
dispatcher.go b2f0a315f3 Allow SrcIpIs to accept multiple parameters. 3 years ago
doc.go 7875f0f4ac Unify examples naming 3 years ago
https.go 23fb7b333a Merge pull request #266 from orkunkaraduman/needing-ctx-userdata-in-mitm 7 months ago
key.pem e18c7b8430 Update the certificate files to match the contents of certs.go. 1 year ago
proxy.go 077c1cc6f9 Keep Response Headers 9 months ago
proxy_test.go 63b166f257 all: gofmt 7 months ago
responses.go 9b700f7984 Add status text based on status code on new HTTP responses 5 months ago
signer.go 9614ae7e72 Merge pull request #285 from liudanking/master 7 months ago
signer_test.go 623bafc29d gofmt 5 years ago

README.md

Introduction

GoDoc

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.

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.