Skip to content

Commit 36a95dc

Browse files
Fixed tunneling, now it correctly being forwarded to SOCKS5 proxy, added deletion of hop headers, added x-forwarded-for header
1 parent 6ec6f6e commit 36a95dc

File tree

1 file changed

+49
-11
lines changed

1 file changed

+49
-11
lines changed

gohpts.go

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,60 @@ import (
1414
"golang.org/x/net/proxy"
1515
)
1616

17+
// Hop-by-hop headers
18+
// https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1
19+
var hopHeaders = []string{
20+
"Connection",
21+
"Keep-Alive",
22+
"Proxy-Authenticate",
23+
"Proxy-Authorization",
24+
"Te", // canonicalized version of "TE"
25+
"TE",
26+
"Trailer",
27+
"Transfer-Encoding",
28+
"Upgrade",
29+
}
30+
31+
func copyHeader(dst, src http.Header) {
32+
for k, vv := range src {
33+
for _, v := range vv {
34+
dst.Add(k, v)
35+
}
36+
}
37+
}
38+
39+
func delHopHeaders(header http.Header) {
40+
for _, h := range hopHeaders {
41+
header.Del(h)
42+
}
43+
}
44+
45+
func appendHostToXForwardHeader(header http.Header, host string) {
46+
if prior, ok := header["X-Forwarded-For"]; ok {
47+
host = strings.Join(prior, ", ") + ", " + host
48+
}
49+
header.Set("X-Forwarded-For", host)
50+
}
51+
1752
type app struct {
1853
hs *http.Server
1954
sc *http.Client
55+
dialer proxy.Dialer
2056
logger *zerolog.Logger
2157
}
2258

23-
func (app *app) handleSOCKS(w http.ResponseWriter, r *http.Request) {
59+
func (app *app) handleForward(w http.ResponseWriter, r *http.Request) {
60+
2461
req, err := http.NewRequest(r.Method, r.URL.String(), r.Body)
2562
if err != nil {
2663
app.logger.Error().Err(err).Msgf("Error during NewRequest() %s: %s", r.URL.String(), err)
2764
w.WriteHeader(http.StatusInternalServerError)
2865
return
2966
}
30-
31-
for key, values := range r.Header {
32-
for _, value := range values {
33-
req.Header.Add(key, value)
34-
}
67+
delHopHeaders(r.Header)
68+
copyHeader(req.Header, r.Header)
69+
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
70+
appendHostToXForwardHeader(req.Header, clientIP)
3571
}
3672
resp, err := app.sc.Do(req)
3773
if err != nil {
@@ -46,6 +82,9 @@ func (app *app) handleSOCKS(w http.ResponseWriter, r *http.Request) {
4682
}
4783
defer resp.Body.Close()
4884

85+
delHopHeaders(resp.Header)
86+
copyHeader(w.Header(), resp.Header)
87+
w.WriteHeader(resp.StatusCode)
4988
written, err := io.Copy(w, resp.Body)
5089
if err != nil {
5190
app.logger.Error().Err(err).Msgf("Error during Copy() %s: %s", r.URL.String(), err)
@@ -56,13 +95,12 @@ func (app *app) handleSOCKS(w http.ResponseWriter, r *http.Request) {
5695
}
5796

5897
func (app *app) handleTunnel(w http.ResponseWriter, r *http.Request) {
59-
dstConn, err := net.DialTimeout("tcp", r.Host, 10*time.Second)
98+
dstConn, err := app.dialer.Dial("tcp", r.Host)
6099
if err != nil {
61100
http.Error(w, err.Error(), http.StatusServiceUnavailable)
62101
return
63102
}
64103
defer dstConn.Close()
65-
66104
w.WriteHeader(http.StatusOK)
67105

68106
hj, ok := w.(http.Hijacker)
@@ -77,7 +115,7 @@ func (app *app) handleTunnel(w http.ResponseWriter, r *http.Request) {
77115
}
78116
defer srcConn.Close()
79117

80-
dstConnStr := fmt.Sprintf("%s->%s", dstConn.LocalAddr().String(), dstConn.RemoteAddr().String())
118+
dstConnStr := fmt.Sprintf("%s->%s->%s", dstConn.LocalAddr().String(), dstConn.RemoteAddr().String(), r.Host)
81119
srcConnStr := fmt.Sprintf("%s->%s", srcConn.LocalAddr().String(), srcConn.RemoteAddr().String())
82120

83121
app.logger.Debug().Msgf("%s - %s - %s", r.Proto, r.Method, r.Host)
@@ -104,7 +142,7 @@ func (app *app) handler() http.HandlerFunc {
104142
if r.Method == http.MethodConnect {
105143
app.handleTunnel(w, r)
106144
} else {
107-
app.handleSOCKS(w, r)
145+
app.handleForward(w, r)
108146
}
109147
}
110148
}
@@ -156,5 +194,5 @@ func New(conf *Config) *app {
156194
}
157195
logger.Info().Msgf("SOCKS5 Proxy: %s", conf.AddrSOCKS)
158196
logger.Info().Msgf("HTTP Proxy: %s", conf.AddrHTTP)
159-
return &app{hs: hs, sc: socks, logger: &logger}
197+
return &app{hs: hs, sc: socks, dialer: dialer, logger: &logger}
160198
}

0 commit comments

Comments
 (0)