goproxy

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2018 License: Apache-2.0 Imports: 14 Imported by: 0

README

goproxy

Go HTTP(S)代理库, 支持中间人代理解密HTTPS

安装

go get github.com/ouqiang/goproxy

使用

package main

import (
	"net/http"
	"time"

	"github.com/ouqiang/goproxy"
)

func main() {
	proxy := goproxy.New()
	server := &http.Server{
		Addr:         ":8080",
		Handler:      proxy,
		ReadTimeout:  1 * time.Minute,
		WriteTimeout: 1 * time.Minute,
	}
	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}
代理测试
curl -x localhost:8080 https://www.baidu.com

中间人代理, 解密HTTPS

系统需导入根证书 mitm-proxy.crt

package main

import (
	"crypto/tls"
	"net/http"
	"sync"
	"time"

	"github.com/ouqiang/goproxy"
)
// 实现证书缓存接口
type Cache struct {
	m sync.Map
}

func (c *Cache) Set(host string, cert *tls.Certificate) {
	c.m.Store(host, cert)
}
func (c *Cache) Get(host string) *tls.Certificate {
	v, ok := c.m.Load(host)
	if !ok {
		return nil
	}

	return v.(*tls.Certificate)
}

func main() {
	proxy := goproxy.New(goproxy.WithDecryptHTTPS(&Cache{}))
	server := &http.Server{
		Addr:         ":8080",
		Handler:      proxy,
		ReadTimeout:  1 * time.Minute,
		WriteTimeout: 1 * time.Minute,
	}
	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

事件处理

实现Delegate接口

type Delegate interface {
	// Connect 收到客户端连接
	Connect(ctx *Context, rw http.ResponseWriter)
	// Auth 代理身份认证
	Auth(ctx *Context, rw http.ResponseWriter)
	// BeforeRequest HTTP请求前 设置X-Forwarded-For, 修改Header、Body
	BeforeRequest(ctx *Context)
	// BeforeResponse 响应发送到客户端前, 修改Header、Body、Status Code
	BeforeResponse(ctx *Context, resp *http.Response, err error)
	// ParentProxy 上级代理
	ParentProxy(*http.Request) (*url.URL, error)
	// Finish 本次请求结束
	Finish(ctx *Context)
	// 记录错误信息
	ErrorLog(err error)
}
type EventHandler struct{}

func (e *EventHandler) Connect(ctx *goproxy.Context, rw http.ResponseWriter) {
	// 保存的数据可以在后面的回调方法中获取
	ctx.Data["req_id"] = "uuid"

	// 禁止访问某个域名
	if strings.Contains(ctx.Req.URL.Host, "example.com") {
		rw.WriteHeader(http.StatusForbidden)
		ctx.Abort()
		return
	}
}

func (e *EventHandler) Auth(ctx *goproxy.Context, rw http.ResponseWriter)  {
	// 身份验证
}

func (e *EventHandler) BeforeRequest(ctx *goproxy.Context) {
	// 修改header
	ctx.Req.Header.Add("X-Request-Id", ctx.Data["req_id"].(string))
	// 设置X-Forwarded-For
	if clientIP, _, err := net.SplitHostPort(ctx.Req.RemoteAddr); err == nil {
		if prior, ok := ctx.Req.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		ctx.Req.Header.Set("X-Forwarded-For", clientIP)
	}
	// 读取Body
	body, err := ioutil.ReadAll(ctx.Req.Body)
	if err != nil {
		// 错误处理
		return
	}
	// Request.Body只能读取一次, 读取后必须再放回去
	// Response.Body同理
	ctx.Req.Body = ioutil.NopCloser(bytes.NewReader(body))

}

func (e *EventHandler) BeforeResponse(ctx *goproxy.Context, resp *http.Response, err error) {
    if err != nil {
        return
    }
    // 修改response
}

// 设置上级代理
func (e *EventHandler) ParentProxy(req *http.Request) (*url.URL, error) {
	return url.Parse("http://localhost:1087")
}

func (e *EventHandler) Finish(ctx *goproxy.Context) {
	fmt.Printf("请求结束 URL:%s\n", ctx.Req.URL)
}

// 记录错误日志
func (e *EventHandler) ErrorLog(err error) {
	log.Println(err)
}


func main() {
	proxy := goproxy.New(goproxy.WithDelegate(&EventHandler{}))
	server := &http.Server{
		Addr:         ":8080",
		Handler:      proxy,
		ReadTimeout:  1 * time.Minute,
		WriteTimeout: 1 * time.Minute,
	}
	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

Documentation

Overview

Package goproxy HTTP(S)代理, 支持中间人代理解密HTTPS数据

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CloneBody added in v1.0.1

func CloneBody(b io.ReadCloser) (r io.ReadCloser, body []byte, err error)

CloneBody 拷贝Body

func CloneHeader added in v1.0.1

func CloneHeader(h http.Header) http.Header

CloneHeader 深拷贝Header

func CopyHeader added in v1.0.1

func CopyHeader(dst, src http.Header)

CopyHeader 浅拷贝Header

Types

type Context

type Context struct {
	Req  *http.Request
	Data map[interface{}]interface{}
	// contains filtered or unexported fields
}

Context 代理上下文

func (*Context) Abort

func (c *Context) Abort()

Abort 中断执行

func (*Context) IsAborted added in v1.0.2

func (c *Context) IsAborted() bool

IsAborted 是否已中断执行

type DefaultDelegate

type DefaultDelegate struct {
	Delegate
}

DefaultDelegate 默认Handler什么也不做

func (*DefaultDelegate) Auth

func (h *DefaultDelegate) Auth(ctx *Context, rw http.ResponseWriter)

func (*DefaultDelegate) BeforeRequest

func (h *DefaultDelegate) BeforeRequest(ctx *Context)

func (*DefaultDelegate) BeforeResponse

func (h *DefaultDelegate) BeforeResponse(ctx *Context, resp *http.Response, err error)

func (*DefaultDelegate) Connect

func (h *DefaultDelegate) Connect(ctx *Context, rw http.ResponseWriter)

func (*DefaultDelegate) ErrorLog

func (h *DefaultDelegate) ErrorLog(err error)

func (*DefaultDelegate) Finish

func (h *DefaultDelegate) Finish(ctx *Context)

func (*DefaultDelegate) ParentProxy

func (h *DefaultDelegate) ParentProxy(req *http.Request) (*url.URL, error)

type Delegate

type Delegate interface {
	// Connect 收到客户端连接
	Connect(ctx *Context, rw http.ResponseWriter)
	// Auth 代理身份认证
	Auth(ctx *Context, rw http.ResponseWriter)
	// BeforeRequest HTTP请求前 设置X-Forwarded-For, 修改Header、Body
	BeforeRequest(ctx *Context)
	// BeforeResponse 响应发送到客户端前, 修改Header、Body、Status Code
	BeforeResponse(ctx *Context, resp *http.Response, err error)
	// ParentProxy 上级代理
	ParentProxy(*http.Request) (*url.URL, error)
	// Finish 本次请求结束
	Finish(ctx *Context)
	// 记录错误信息
	ErrorLog(err error)
}

type Option

type Option func(*options)

func WithDecryptHTTPS

func WithDecryptHTTPS(c cert.Cache) Option

WithDecryptHTTPS 中间人代理, 解密HTTPS, 需实现证书缓存接口

func WithDelegate

func WithDelegate(delegate Delegate) Option

WithDelegate 设置委托类

func WithDisableKeepAlive

func WithDisableKeepAlive(disableKeepAlive bool) Option

WithDisableKeepAlive 连接是否重用

func WithTransport

func WithTransport(t *http.Transport) Option

WithTransport 自定义http transport

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy 实现了http.Handler接口

func New

func New(opt ...Option) *Proxy

New 创建proxy实例

func (*Proxy) ClientConnNum

func (p *Proxy) ClientConnNum() int32

ClientConnNum 获取客户端连接数

func (*Proxy) DoRequest

func (p *Proxy) DoRequest(ctx *Context, responseFunc func(*http.Response, error))

DoRequest 执行HTTP请求,并调用responseFunc处理response

func (*Proxy) ServeHTTP

func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP 实现了http.Handler接口

Directories

Path Synopsis
Package cert HTTPS证书 Package cert 证书管理
Package cert HTTPS证书 Package cert 证书管理

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL