@@ -9,24 +9,28 @@ import (
9
9
"time"
10
10
11
11
"github.com/golang/glog"
12
- net_proxy "golang.org/x/net/proxy"
12
+ netProxy "golang.org/x/net/proxy"
13
13
)
14
14
15
- // Using a socks5 proxy to tunnel the HTTP requests, e.g., 127.0.0.1:7890
16
- var Socks5 = ""
17
-
18
15
func NewProxyHandler (timeoutSeconds int ) * ProxyHandler {
19
16
return & ProxyHandler {
20
17
Timeout : time .Duration (timeoutSeconds ) * time .Second ,
21
18
}
22
19
}
23
20
24
21
type 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
30
34
}
31
35
32
36
func (p * ProxyHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
@@ -52,52 +56,65 @@ func (p *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
52
56
}
53
57
}
54
58
if r .Method == http .MethodConnect {
55
- handleTunneling (w , r , p .Timeout )
59
+ handleTunneling (w , r , p .Timeout , p . Socks5Forward )
56
60
} else {
57
61
handleHTTP (w , r )
58
62
}
59
63
}
60
64
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
63
67
var err error
64
68
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 )
69
71
} 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 {
72
82
Timeout : timeout ,
73
83
KeepAlive : 30 * time .Second ,
74
84
})
85
+
75
86
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 ())
77
88
http .Error (w , err .Error (), http .StatusServiceUnavailable )
78
89
return
79
90
}
80
- dest_conn , err = socks5_dailer .Dial ("tcp" , r .Host )
91
+
92
+ destConn , err = socks5Dialer .Dial ("tcp" , r .Host )
81
93
}
94
+
82
95
if err != nil {
83
96
glog .Errorf ("Failed to dial host, %s\n " , err .Error ())
84
97
http .Error (w , err .Error (), http .StatusServiceUnavailable )
85
98
return
86
99
}
100
+
87
101
w .WriteHeader (http .StatusOK )
102
+
88
103
hijacker , ok := w .(http.Hijacker )
89
104
if ! ok {
90
105
glog .Errorln ("Attempted to hijack connection that does not support it" )
91
106
http .Error (w , "Hijacking not supported" , http .StatusInternalServerError )
92
107
return
93
108
}
94
- client_conn , _ , err := hijacker .Hijack ()
109
+
110
+ clientConn , _ , err := hijacker .Hijack ()
95
111
if err != nil {
96
112
glog .Errorf ("Failed to hijack connection, %s\n " , err .Error ())
97
113
http .Error (w , err .Error (), http .StatusServiceUnavailable )
98
114
}
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 )
101
118
}
102
119
103
120
func transfer (destination io.WriteCloser , source io.ReadCloser ) {
@@ -139,7 +156,6 @@ func proxyBasicAuth(r *http.Request) (username, password string, ok bool) {
139
156
// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
140
157
func parseBasicAuth (auth string ) (username , password string , ok bool ) {
141
158
const prefix = "Basic "
142
- // Case insensitive prefix match. See Issue 22736.
143
159
if len (auth ) < len (prefix ) || ! equalFold (auth [:len (prefix )], prefix ) {
144
160
return
145
161
}
0 commit comments