diff --git a/proxy/connection.go b/proxy/connection.go index cb99e9d..0561ac4 100644 --- a/proxy/connection.go +++ b/proxy/connection.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "crypto/tls" + "encoding/base64" "encoding/json" "errors" "net" @@ -105,10 +106,17 @@ func (connCtx *ConnContext) initHttpServerConn() { return } + var useProxy func(*http.Request) (*url.URL, error) + if len(connCtx.proxy.Opts.Upstream) > 0 { + upstreamUrl, _ := url.Parse(connCtx.proxy.Opts.Upstream) + useProxy = http.ProxyURL(upstreamUrl) + } else { + useProxy = http.ProxyFromEnvironment + } serverConn := newServerConn() serverConn.client = &http.Client{ Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, + Proxy: useProxy, DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { c, err := (&net.Dialer{}).DialContext(ctx, network, addr) if err != nil { @@ -151,10 +159,23 @@ func (connCtx *ConnContext) initServerTcpConn(req *http.Request) error { // test is use proxy clientReq := &http.Request{URL: &url.URL{Scheme: "https", Host: ServerConn.Address}} - proxyUrl, err := http.ProxyFromEnvironment(clientReq) - if err != nil { - return err + + var proxyUrl *url.URL + var err error + + if len(connCtx.proxy.Opts.Upstream) > 0 { + upstreamUrl, _ := url.Parse(connCtx.proxy.Opts.Upstream) + proxyUrl, err = http.ProxyURL(upstreamUrl)(clientReq) + if err != nil { + return err + } + } else { + proxyUrl, err = http.ProxyFromEnvironment(clientReq) + if err != nil { + return err + } } + var plainConn net.Conn if proxyUrl != nil { plainConn, err = getProxyConn(proxyUrl, ServerConn.Address) @@ -188,6 +209,10 @@ func getProxyConn(proxyUrl *url.URL, address string) (net.Conn, error) { Method: "CONNECT", URL: &url.URL{Opaque: address}, Host: address, + Header: http.Header{}, + } + if proxyUrl.User != nil { + connectReq.Header.Set("Proxy-Authorization", "Basic"+base64.StdEncoding.EncodeToString([]byte(proxyUrl.User.String()))) } connectCtx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) defer cancel() diff --git a/proxy/proxy.go b/proxy/proxy.go index 956653f..1bf8f20 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -16,6 +16,7 @@ type Options struct { StreamLargeBodies int64 // 当请求或响应体大于此字节时,转为 stream 模式 SslInsecure bool CaRootPath string + Upstream string } type Proxy struct {