@@ -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+
1752type 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
5897func (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