@@ -9,24 +9,28 @@ import (
99 "time"
1010
1111 "github.com/golang/glog"
12- net_proxy "golang.org/x/net/proxy"
12+ netProxy "golang.org/x/net/proxy"
1313)
1414
15- // Using a socks5 proxy to tunnel the HTTP requests, e.g., 127.0.0.1:7890
16- var Socks5 = ""
17-
1815func NewProxyHandler (timeoutSeconds int ) * ProxyHandler {
1916 return & ProxyHandler {
2017 Timeout : time .Duration (timeoutSeconds ) * time .Second ,
2118 }
2219}
2320
2421type ProxyHandler struct {
25- Timeout time.Duration
26- Username * string
27- Password * string
28- LogAuth bool
29- LogHeaders bool
22+ Timeout time.Duration
23+ Username * string
24+ Password * string
25+ LogAuth bool
26+ LogHeaders bool
27+ Socks5Forward * Socks5Forward
28+ }
29+
30+ type Socks5Forward struct {
31+ Address string
32+ Username * string
33+ Password * string
3034}
3135
3236func (p * ProxyHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
@@ -52,52 +56,65 @@ func (p *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5256 }
5357 }
5458 if r .Method == http .MethodConnect {
55- handleTunneling (w , r , p .Timeout )
59+ handleTunneling (w , r , p .Timeout , p . Socks5Forward )
5660 } else {
5761 handleHTTP (w , r )
5862 }
5963}
6064
61- func handleTunneling (w http.ResponseWriter , r * http.Request , timeout time.Duration ) {
62- var dest_conn net.Conn
65+ func handleTunneling (w http.ResponseWriter , r * http.Request , timeout time.Duration , socks5Forward * Socks5Forward ) {
66+ var destConn net.Conn
6367 var err error
6468
65- // Check if the socks5 proxy is set
66- // Then tunnel to socks5 proxy
67- if Socks5 == "" {
68- dest_conn , err = net .DialTimeout ("tcp" , r .Host , timeout )
69+ if socks5Forward == nil {
70+ destConn , err = net .DialTimeout ("tcp" , r .Host , timeout )
6971 } else {
70- var socks5_dailer net_proxy.Dialer
71- socks5_dailer , err = net_proxy .SOCKS5 ("tcp" , Socks5 , nil , & net.Dialer {
72+ var socks5Auth * netProxy.Auth
73+ if socks5Forward .Username != nil && socks5Forward .Password != nil {
74+ socks5Auth = & netProxy.Auth {
75+ User : * socks5Forward .Username ,
76+ Password : * socks5Forward .Password ,
77+ }
78+ }
79+
80+ var socks5Dialer netProxy.Dialer
81+ socks5Dialer , err = netProxy .SOCKS5 ("tcp" , socks5Forward .Address , socks5Auth , & net.Dialer {
7282 Timeout : timeout ,
7383 KeepAlive : 30 * time .Second ,
7484 })
85+
7586 if err != nil {
76- glog .Errorf ("Failed to dail socks5 proxy %s, %s\n " , Socks5 , err .Error ())
87+ glog .Errorf ("Failed to dial socks5 proxy %s, %s\n " , socks5Forward . Address , err .Error ())
7788 http .Error (w , err .Error (), http .StatusServiceUnavailable )
7889 return
7990 }
80- dest_conn , err = socks5_dailer .Dial ("tcp" , r .Host )
91+
92+ destConn , err = socks5Dialer .Dial ("tcp" , r .Host )
8193 }
94+
8295 if err != nil {
8396 glog .Errorf ("Failed to dial host, %s\n " , err .Error ())
8497 http .Error (w , err .Error (), http .StatusServiceUnavailable )
8598 return
8699 }
100+
87101 w .WriteHeader (http .StatusOK )
102+
88103 hijacker , ok := w .(http.Hijacker )
89104 if ! ok {
90105 glog .Errorln ("Attempted to hijack connection that does not support it" )
91106 http .Error (w , "Hijacking not supported" , http .StatusInternalServerError )
92107 return
93108 }
94- client_conn , _ , err := hijacker .Hijack ()
109+
110+ clientConn , _ , err := hijacker .Hijack ()
95111 if err != nil {
96112 glog .Errorf ("Failed to hijack connection, %s\n " , err .Error ())
97113 http .Error (w , err .Error (), http .StatusServiceUnavailable )
98114 }
99- go transfer (dest_conn , client_conn )
100- go transfer (client_conn , dest_conn )
115+
116+ go transfer (destConn , clientConn )
117+ go transfer (clientConn , destConn )
101118}
102119
103120func transfer (destination io.WriteCloser , source io.ReadCloser ) {
@@ -139,7 +156,6 @@ func proxyBasicAuth(r *http.Request) (username, password string, ok bool) {
139156// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
140157func parseBasicAuth (auth string ) (username , password string , ok bool ) {
141158 const prefix = "Basic "
142- // Case insensitive prefix match. See Issue 22736.
143159 if len (auth ) < len (prefix ) || ! equalFold (auth [:len (prefix )], prefix ) {
144160 return
145161 }
0 commit comments