github.com/ck00004/CobaltStrikeParser-Go@v1.0.14/lib/http/httpproxy/proxy_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package httpproxy_test 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "os" 12 "strings" 13 "testing" 14 15 "github.com/ck00004/CobaltStrikeParser-Go/lib/url" 16 17 "github.com/ck00004/CobaltStrikeParser-Go/lib/http/httpproxy" 18 ) 19 20 // setHelper calls t.Helper() for Go 1.9+ (see go19_test.go) and does nothing otherwise. 21 var setHelper = func(t *testing.T) {} 22 23 type proxyForURLTest struct { 24 cfg httpproxy.Config 25 req string // URL to fetch; blank means "http://example.com" 26 want string 27 wanterr error 28 } 29 30 func (t proxyForURLTest) String() string { 31 var buf bytes.Buffer 32 space := func() { 33 if buf.Len() > 0 { 34 buf.WriteByte(' ') 35 } 36 } 37 if t.cfg.HTTPProxy != "" { 38 fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy) 39 } 40 if t.cfg.HTTPSProxy != "" { 41 space() 42 fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy) 43 } 44 if t.cfg.NoProxy != "" { 45 space() 46 fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy) 47 } 48 req := "http://example.com" 49 if t.req != "" { 50 req = t.req 51 } 52 space() 53 fmt.Fprintf(&buf, "req=%q", req) 54 return strings.TrimSpace(buf.String()) 55 } 56 57 var proxyForURLTests = []proxyForURLTest{{ 58 cfg: httpproxy.Config{ 59 HTTPProxy: "127.0.0.1:8080", 60 }, 61 want: "http://127.0.0.1:8080", 62 }, { 63 cfg: httpproxy.Config{ 64 HTTPProxy: "cache.corp.example.com:1234", 65 }, 66 want: "http://cache.corp.example.com:1234", 67 }, { 68 cfg: httpproxy.Config{ 69 HTTPProxy: "cache.corp.example.com", 70 }, 71 want: "http://cache.corp.example.com", 72 }, { 73 cfg: httpproxy.Config{ 74 HTTPProxy: "https://cache.corp.example.com", 75 }, 76 want: "https://cache.corp.example.com", 77 }, { 78 cfg: httpproxy.Config{ 79 HTTPProxy: "http://127.0.0.1:8080", 80 }, 81 want: "http://127.0.0.1:8080", 82 }, { 83 cfg: httpproxy.Config{ 84 HTTPProxy: "https://127.0.0.1:8080", 85 }, 86 want: "https://127.0.0.1:8080", 87 }, { 88 cfg: httpproxy.Config{ 89 HTTPProxy: "socks5://127.0.0.1", 90 }, 91 want: "socks5://127.0.0.1", 92 }, { 93 // Don't use secure for http 94 cfg: httpproxy.Config{ 95 HTTPProxy: "http.proxy.tld", 96 HTTPSProxy: "secure.proxy.tld", 97 }, 98 req: "http://insecure.tld/", 99 want: "http://http.proxy.tld", 100 }, { 101 // Use secure for https. 102 cfg: httpproxy.Config{ 103 HTTPProxy: "http.proxy.tld", 104 HTTPSProxy: "secure.proxy.tld", 105 }, 106 req: "https://secure.tld/", 107 want: "http://secure.proxy.tld", 108 }, { 109 cfg: httpproxy.Config{ 110 HTTPProxy: "http.proxy.tld", 111 HTTPSProxy: "https://secure.proxy.tld", 112 }, 113 req: "https://secure.tld/", 114 want: "https://secure.proxy.tld", 115 }, { 116 cfg: httpproxy.Config{ 117 HTTPProxy: "http.proxy.tld", 118 }, 119 req: "https://secure.tld/", 120 want: "<nil>", 121 }, { 122 cfg: httpproxy.Config{ 123 HTTPProxy: "http.proxy.tld", 124 }, 125 req: "ftp://insecure.tld/", 126 want: "<nil>", 127 }, { 128 // Issue 16405: don't use HTTP_PROXY in a CGI environment, 129 // where HTTP_PROXY can be attacker-controlled. 130 cfg: httpproxy.Config{ 131 HTTPProxy: "http://10.1.2.3:8080", 132 CGI: true, 133 }, 134 want: "<nil>", 135 wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"), 136 }, { 137 // HTTPS proxy is still used even in CGI environment. 138 // (perhaps dubious but it's the historical behaviour). 139 cfg: httpproxy.Config{ 140 HTTPSProxy: "https://secure.proxy.tld", 141 CGI: true, 142 }, 143 req: "https://secure.tld/", 144 want: "https://secure.proxy.tld", 145 }, { 146 want: "<nil>", 147 }, { 148 cfg: httpproxy.Config{ 149 NoProxy: "example.com", 150 HTTPProxy: "proxy", 151 }, 152 req: "http://example.com/", 153 want: "<nil>", 154 }, { 155 cfg: httpproxy.Config{ 156 NoProxy: ".example.com", 157 HTTPProxy: "proxy", 158 }, 159 req: "http://example.com/", 160 want: "http://proxy", 161 }, { 162 cfg: httpproxy.Config{ 163 NoProxy: "ample.com", 164 HTTPProxy: "proxy", 165 }, 166 req: "http://example.com/", 167 want: "http://proxy", 168 }, { 169 cfg: httpproxy.Config{ 170 NoProxy: "example.com", 171 HTTPProxy: "proxy", 172 }, 173 req: "http://foo.example.com/", 174 want: "<nil>", 175 }, { 176 cfg: httpproxy.Config{ 177 NoProxy: ".foo.com", 178 HTTPProxy: "proxy", 179 }, 180 req: "http://example.com/", 181 want: "http://proxy", 182 }, { 183 cfg: httpproxy.Config{ 184 NoProxy: ".示例.com", 185 HTTPProxy: "proxy", 186 }, 187 req: "http://www.示例.com", 188 want: "<nil>", 189 }, { 190 cfg: httpproxy.Config{ 191 NoProxy: "xn--fsq092h.com", 192 HTTPProxy: "proxy", 193 }, 194 req: "http://www.示例.com", 195 want: "<nil>", 196 }, { 197 cfg: httpproxy.Config{ 198 NoProxy: "示例.com", 199 HTTPProxy: "proxy", 200 }, 201 req: "http://www.xn--fsq092h.com", 202 want: "<nil>", 203 }, 204 } 205 206 func testProxyForURL(t *testing.T, tt proxyForURLTest) { 207 setHelper(t) 208 reqURLStr := tt.req 209 if reqURLStr == "" { 210 reqURLStr = "http://example.com" 211 } 212 reqURL, err := url.Parse(reqURLStr) 213 if err != nil { 214 t.Errorf("invalid URL %q", reqURLStr) 215 return 216 } 217 cfg := tt.cfg 218 proxyForURL := cfg.ProxyFunc() 219 url, err := proxyForURL(reqURL) 220 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 221 t.Errorf("%v: got error = %q, want %q", tt, g, e) 222 return 223 } 224 if got := fmt.Sprintf("%s", url); got != tt.want { 225 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 226 } 227 228 // Check that changing the Config doesn't change the results 229 // of the functuon. 230 cfg = httpproxy.Config{} 231 url, err = proxyForURL(reqURL) 232 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 233 t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e) 234 return 235 } 236 if got := fmt.Sprintf("%s", url); got != tt.want { 237 t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want) 238 } 239 } 240 241 func TestProxyForURL(t *testing.T) { 242 for _, tt := range proxyForURLTests { 243 testProxyForURL(t, tt) 244 } 245 } 246 247 func TestFromEnvironment(t *testing.T) { 248 os.Setenv("HTTP_PROXY", "httpproxy") 249 os.Setenv("HTTPS_PROXY", "httpsproxy") 250 os.Setenv("NO_PROXY", "noproxy") 251 os.Setenv("REQUEST_METHOD", "") 252 got := httpproxy.FromEnvironment() 253 want := httpproxy.Config{ 254 HTTPProxy: "httpproxy", 255 HTTPSProxy: "httpsproxy", 256 NoProxy: "noproxy", 257 } 258 if *got != want { 259 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 260 } 261 } 262 263 func TestFromEnvironmentWithRequestMethod(t *testing.T) { 264 os.Setenv("HTTP_PROXY", "httpproxy") 265 os.Setenv("HTTPS_PROXY", "httpsproxy") 266 os.Setenv("NO_PROXY", "noproxy") 267 os.Setenv("REQUEST_METHOD", "PUT") 268 got := httpproxy.FromEnvironment() 269 want := httpproxy.Config{ 270 HTTPProxy: "httpproxy", 271 HTTPSProxy: "httpsproxy", 272 NoProxy: "noproxy", 273 CGI: true, 274 } 275 if *got != want { 276 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 277 } 278 } 279 280 func TestFromEnvironmentLowerCase(t *testing.T) { 281 os.Setenv("http_proxy", "httpproxy") 282 os.Setenv("https_proxy", "httpsproxy") 283 os.Setenv("no_proxy", "noproxy") 284 os.Setenv("REQUEST_METHOD", "") 285 got := httpproxy.FromEnvironment() 286 want := httpproxy.Config{ 287 HTTPProxy: "httpproxy", 288 HTTPSProxy: "httpsproxy", 289 NoProxy: "noproxy", 290 } 291 if *got != want { 292 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 293 } 294 } 295 296 var UseProxyTests = []struct { 297 host string 298 match bool 299 }{ 300 // Never proxy localhost: 301 {"localhost", false}, 302 {"127.0.0.1", false}, 303 {"127.0.0.2", false}, 304 {"[::1]", false}, 305 {"[::2]", true}, // not a loopback address 306 307 {"192.168.1.1", false}, // matches exact IPv4 308 {"192.168.1.2", true}, // ports do not match 309 {"192.168.1.3", false}, // matches exact IPv4:port 310 {"192.168.1.4", true}, // no match 311 {"10.0.0.2", false}, // matches IPv4/CIDR 312 {"[2001:db8::52:0:1]", false}, // matches exact IPv6 313 {"[2001:db8::52:0:2]", true}, // no match 314 {"[2001:db8::52:0:3]", false}, // matches exact [IPv6]:port 315 {"[2002:db8:a::123]", false}, // matches IPv6/CIDR 316 {"[fe80::424b:c8be:1643:a1b6]", true}, // no match 317 318 {"barbaz.net", true}, // does not match as .barbaz.net 319 {"www.barbaz.net", false}, // does match as .barbaz.net 320 {"foobar.com", false}, // does match as foobar.com 321 {"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com" 322 {"foofoobar.com", true}, // not match as a part of foobar.com 323 {"baz.com", true}, // not match as a part of barbaz.com 324 {"localhost.net", true}, // not match as suffix of address 325 {"local.localhost", true}, // not match as prefix as address 326 {"barbarbaz.net", true}, // not match, wrong domain 327 {"wildcard.io", true}, // does not match as *.wildcard.io 328 {"nested.wildcard.io", false}, // match as *.wildcard.io 329 {"awildcard.io", true}, // not a match because of '*' 330 } 331 332 var noProxy = "foobar.com, .barbaz.net, *.wildcard.io, 192.168.1.1, 192.168.1.2:81, 192.168.1.3:80, 10.0.0.0/30, 2001:db8::52:0:1, [2001:db8::52:0:2]:443, [2001:db8::52:0:3]:80, 2002:db8:a::45/64" 333 334 func TestUseProxy(t *testing.T) { 335 cfg := &httpproxy.Config{ 336 NoProxy: noProxy, 337 } 338 for _, test := range UseProxyTests { 339 if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match { 340 t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match) 341 } 342 } 343 } 344 345 func TestInvalidNoProxy(t *testing.T) { 346 cfg := &httpproxy.Config{ 347 NoProxy: ":1", 348 } 349 ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic 350 if !ok { 351 t.Errorf("useProxy unexpected return; got false; want true") 352 } 353 } 354 355 func TestAllNoProxy(t *testing.T) { 356 cfg := &httpproxy.Config{ 357 NoProxy: "*", 358 } 359 for _, test := range UseProxyTests { 360 if httpproxy.ExportUseProxy(cfg, test.host+":80") != false { 361 t.Errorf("useProxy(%v) = true, want false", test.host) 362 } 363 } 364 } 365 366 func BenchmarkProxyForURL(b *testing.B) { 367 cfg := &httpproxy.Config{ 368 HTTPProxy: "http://proxy.example.org", 369 HTTPSProxy: "https://proxy.example.org", 370 NoProxy: noProxy, 371 } 372 for _, test := range UseProxyTests { 373 u, err := url.Parse("https://" + test.host + ":80") 374 if err != nil { 375 b.Fatalf("parsed failed: %s", test.host) 376 } 377 proxyFunc := cfg.ProxyFunc() 378 b.Run(test.host, func(b *testing.B) { 379 for n := 0; n < b.N; n++ { 380 if au, e := proxyFunc(u); e != nil && test.match == (au != nil) { 381 b.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match) 382 } 383 } 384 }) 385 } 386 }