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  }