Skip to content

Commit caa657b

Browse files
committed
Add a mitmMutateRequest hook and add ConnectAction to ProxyCtx
1 parent 75b93c0 commit caa657b

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

ctx.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ type ProxyCtx struct {
2525
// call of RespHandler
2626
UserData interface{}
2727
// Will connect a request to a response
28-
Session int64
29-
proxy *ProxyHttpServer
28+
Session int64
29+
proxy *ProxyHttpServer
30+
ConnectAction ConnectActionLiteral
3031
}
3132

3233
type RoundTripper interface {

https.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ var (
4343
)
4444

4545
type ConnectAction struct {
46-
Action ConnectActionLiteral
47-
Hijack func(req *http.Request, client net.Conn, ctx *ProxyCtx)
48-
TLSConfig func(host string, ctx *ProxyCtx) (*tls.Config, error)
46+
Action ConnectActionLiteral
47+
Hijack func(req *http.Request, client net.Conn, ctx *ProxyCtx)
48+
TLSConfig func(host string, ctx *ProxyCtx) (*tls.Config, error)
49+
MitmMutateRequest func(req *http.Request, ctx *ProxyCtx)
4950
}
5051

5152
func stripPort(s string) string {
@@ -114,6 +115,7 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
114115
break
115116
}
116117
}
118+
ctx.ConnectAction = todo.Action
117119
switch todo.Action {
118120
case ConnectAccept:
119121
if !hasPort.MatchString(host) {
@@ -264,7 +266,7 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
264266
req, err := http.ReadRequest(clientTlsReader)
265267
// Set the RoundTripper on the ProxyCtx within the `HandleConnect` action of goproxy, then
266268
// inject the roundtripper here in order to use a custom round tripper while mitm.
267-
var ctx = &ProxyCtx{Req: req, Session: atomic.AddInt64(&proxy.sess, 1), proxy: proxy, UserData: ctx.UserData, RoundTripper: ctx.RoundTripper}
269+
var ctx = &ProxyCtx{Req: req, Session: atomic.AddInt64(&proxy.sess, 1), proxy: proxy, UserData: ctx.UserData, RoundTripper: ctx.RoundTripper, ConnectAction: ctx.ConnectAction}
268270
if err != nil && err != io.EOF {
269271
return
270272
}
@@ -273,6 +275,9 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
273275
return
274276
}
275277
req.RemoteAddr = r.RemoteAddr // since we're converting the request, need to carry over the original connecting IP as well
278+
if todo.MitmMutateRequest != nil {
279+
todo.MitmMutateRequest(req, ctx)
280+
}
276281
ctx.Logf("req %v", r.Host)
277282

278283
if !httpsRegexp.MatchString(req.URL.String()) {

proxy_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,26 @@ func (QueryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
4141
io.WriteString(w, req.Form.Get("result"))
4242
}
4343

44+
type HeadersHandler struct{}
45+
46+
// This handlers returns a body with a string containing all the request headers it received.
47+
func (HeadersHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
48+
var sb strings.Builder
49+
for name, values := range req.Header {
50+
for _, value := range values {
51+
sb.WriteString(name)
52+
sb.WriteString(": ")
53+
sb.WriteString(value)
54+
sb.WriteString(";")
55+
}
56+
}
57+
io.WriteString(w, sb.String())
58+
}
59+
4460
func init() {
4561
http.DefaultServeMux.Handle("/bobo", ConstantHanlder("bobo"))
4662
http.DefaultServeMux.Handle("/query", QueryHandler{})
63+
http.DefaultServeMux.Handle("/headers", HeadersHandler{})
4764
}
4865

4966
type ConstantHanlder string
@@ -436,6 +453,33 @@ func TestSimpleMitm(t *testing.T) {
436453
}
437454
}
438455

456+
func TestMitmMutateRequest(t *testing.T) {
457+
mitmMutateRequest := func(req *http.Request, ctx *goproxy.ProxyCtx) {
458+
// We inject a header in the request
459+
req.Header.Set("Mitm-Header-Inject", "true")
460+
}
461+
mitmConnect := &goproxy.ConnectAction{
462+
Action: goproxy.ConnectMitm,
463+
TLSConfig: goproxy.TLSConfigFromCA(&goproxy.GoproxyCa),
464+
MitmMutateRequest: mitmMutateRequest,
465+
}
466+
var mitm goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
467+
return mitmConnect, host
468+
}
469+
470+
proxy := goproxy.NewProxyHttpServer()
471+
proxy.OnRequest().HandleConnect(mitm)
472+
473+
client, l := oneShotProxy(proxy, t)
474+
defer l.Close()
475+
476+
r := string(getOrFail(https.URL+"/headers", client, t))
477+
if !strings.Contains(r, "Mitm-Header-Inject: true") {
478+
t.Error("Wrong response when mitm", r, "expected MITM injected header to be returned")
479+
}
480+
481+
}
482+
439483
func TestConnectHandler(t *testing.T) {
440484
proxy := goproxy.NewProxyHttpServer()
441485
althttps := httptest.NewTLSServer(ConstantHanlder("althttps"))

0 commit comments

Comments
 (0)