Skip to content

Commit c650e5d

Browse files
initialized doConnect
1 parent 43d408e commit c650e5d

File tree

3 files changed

+93
-13
lines changed

3 files changed

+93
-13
lines changed

context.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package httpproxy
22

33
type Context struct {
4-
Prx *Proxy
5-
SessionNo int64
6-
UserData interface{}
4+
Prx *Proxy
5+
SessionNo int64
6+
ConnectAction ConnectAction
7+
UserData interface{}
78
}

demo/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@ func OnAuth(ctx *httpproxy.Context, user string, pass string) bool {
2020
}
2121

2222
func OnConnect(ctx *httpproxy.Context, host string) (httpproxy.ConnectAction, string) {
23-
return httpproxy.ConnectAccept, host
23+
return httpproxy.ConnectOk, host
2424
}
2525

2626
func OnRequest(ctx *httpproxy.Context, req *http.Request) *http.Response {
2727
return nil
2828
}
2929

3030
func OnResponse(ctx *httpproxy.Context, req *http.Request, resp *http.Response) {
31-
31+
resp.Header.Add("Via", "test")
3232
}
3333

3434
func main() {
3535
prx, _ := httpproxy.NewProxy()
3636
prx.OnError = OnError
37+
prx.OnResponse = OnResponse
3738
http.ListenAndServe(":8080", prx)
3839
}

httpproxy.go

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,26 @@ package httpproxy
33
import (
44
"crypto/tls"
55
"encoding/base64"
6+
"fmt"
7+
"io"
8+
"net"
69
"net/http"
10+
"regexp"
711
"strings"
12+
"sync"
813
"sync/atomic"
914
)
1015

1116
type ConnectAction int
1217

1318
const (
14-
ConnectAccept = ConnectAction(iota)
15-
ConnectReject
19+
ConnectNone = ConnectAction(iota)
20+
ConnectOk
1621
ConnectMitm
1722
)
1823

24+
var hasPort = regexp.MustCompile(`:\d+$`)
25+
1926
type Proxy struct {
2027
SessionNo int64
2128
Rt http.RoundTripper
@@ -80,6 +87,77 @@ func doAuth(ctx *Context, w http.ResponseWriter, r *http.Request) bool {
8087
return true
8188
}
8289

90+
func doConnect(ctx *Context, w http.ResponseWriter, r *http.Request) (w2 http.ResponseWriter, r2 *http.Request) {
91+
if r.Method != "CONNECT" {
92+
w2, r2 = w, r
93+
return
94+
}
95+
hij, ok := w.(http.Hijacker)
96+
if !ok {
97+
if r.Close {
98+
defer r.Body.Close()
99+
}
100+
err := fmt.Errorf("httpserver does not support hijacking")
101+
doError(ctx, err)
102+
return
103+
}
104+
hijConn, _, err := hij.Hijack()
105+
if err != nil {
106+
if r.Close {
107+
defer r.Body.Close()
108+
}
109+
doError(ctx, err)
110+
return
111+
}
112+
ctx.ConnectAction = ConnectOk
113+
host := r.URL.Host
114+
if ctx.Prx.OnConnect != nil {
115+
ctx.ConnectAction, host = ctx.Prx.OnConnect(ctx, host)
116+
if ctx.ConnectAction == ConnectNone {
117+
ctx.ConnectAction = ConnectOk
118+
}
119+
}
120+
if !hasPort.MatchString(host) {
121+
host += ":80"
122+
}
123+
switch ctx.ConnectAction {
124+
case ConnectOk:
125+
targetConn, err := net.Dial("tcp", host)
126+
if err != nil {
127+
hijConn.Close()
128+
doError(ctx, err)
129+
return
130+
}
131+
_, err = hijConn.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
132+
if err != nil {
133+
hijConn.Close()
134+
targetConn.Close()
135+
doError(ctx, err)
136+
return
137+
}
138+
var wg sync.WaitGroup
139+
wg.Add(2)
140+
go func() {
141+
_, err := io.Copy(targetConn, hijConn)
142+
if err != nil {
143+
doError(ctx, err)
144+
}
145+
wg.Done()
146+
}()
147+
go func() {
148+
_, err := io.Copy(hijConn, targetConn)
149+
if err != nil {
150+
doError(ctx, err)
151+
}
152+
wg.Done()
153+
}()
154+
hijConn.Close()
155+
targetConn.Close()
156+
}
157+
158+
return
159+
}
160+
83161
func doRequest(ctx *Context, w http.ResponseWriter, r *http.Request) bool {
84162
r.RequestURI = ""
85163
if !r.URL.IsAbs() {
@@ -148,15 +226,15 @@ func (prx *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
148226
}
149227
removeProxyHeaders(r)
150228

151-
// doConnect
152-
153-
req := r
154-
155-
if doRequest(ctx, w, req) {
229+
if w2, r2 := doConnect(ctx, w, r); r2 != nil {
230+
w, r = w2, r2
231+
} else {
156232
return
157233
}
158234

159-
if doResponse(ctx, w, req) {
235+
if doRequest(ctx, w, r) {
160236
return
161237
}
238+
239+
doResponse(ctx, w, r)
162240
}

0 commit comments

Comments
 (0)