使用golang启动一个http代理
使用第三方库github.com/elazarl/goproxy
一.快速启动 可以访问http和https(不能对https的内容进行拦截)
package main
import (
"log"
"net/http"
"github.com/elazarl/goproxy"
)
func main() {
gproxy := goproxy.NewProxyHttpServer()
// 开启调试模式
gproxy.Verbose = true
log.Fatal(http.ListenAndServe(":8080", gproxy))
}
二.配置对https的拦截
package main
import (
"bytes"
"fmt"
"github.com/elazarl/goproxy"
"io"
"log"
"net/http"
)
var (
addr = "0.0.0.0:8080"
)
func responseCondition(resp *http.Response, ctx *goproxy.ProxyCtx) bool {
return resp != nil && resp.Body != nil
}
func echoResp(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
scheme := resp.Request.URL.Scheme
ctx.Proxy.Logger.Printf("Intercepted a %s request: %s", scheme, resp.Request.URL.String())
if scheme == "https" {
respBody, _ := io.ReadAll(resp.Body)
fmt.Print(string(respBody))
resp.Body.Close()
//恢复响应体供后续流程使用
resp.Body = io.NopCloser(bytes.NewBuffer(respBody))
}
return resp
}
// 下载证书
func certHandler(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment;filename=GoProxyCA.crt")
w.WriteHeader(http.StatusOK)
w.Write(goproxy.CA_CERT)
}
// 直接使用http访问时
// 如果不是访问下载证书的请求 则直接返回错误
func nonProxyHandler(w http.ResponseWriter, r *http.Request) {
log.Println(r.Method, r.URL.Path)
if r.Method == http.MethodGet && r.URL.Path == "/ssl" {
certHandler(w, r)
} else {
http.Error(w, "This server only responds to proxy requests.", http.StatusInternalServerError)
}
}
// 实例化并启动一个代理服务器
func main() {
proxy := goproxy.NewProxyHttpServer()
proxy.NonproxyHandler = http.HandlerFunc(nonProxyHandler)
// 调试模式
proxy.Verbose = true
proxy.OnResponse(goproxy.RespConditionFunc(responseCondition)).DoFunc(echoResp)
// 启用 HTTPS 的 MITM 拦截
proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
log.Fatal(http.ListenAndServe(addr, proxy))
}
运行脚本后先使用浏览器访问http://yourAddr/ssl(如: http://localhost:8080/ssl)下载并安装证书
完整代码请访问:github.com/sgs921107/gproxy