|
@@ -48,20 +48,22 @@ package upstreamproxy
|
|
|
import (
|
|
import (
|
|
|
"bufio"
|
|
"bufio"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
- "golang.org/x/net/proxy"
|
|
|
|
|
"net"
|
|
"net"
|
|
|
"net/http"
|
|
"net/http"
|
|
|
"net/http/httputil"
|
|
"net/http/httputil"
|
|
|
"net/url"
|
|
"net/url"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
+
|
|
|
|
|
+ "golang.org/x/net/proxy"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// httpProxy is a HTTP connect proxy.
|
|
// httpProxy is a HTTP connect proxy.
|
|
|
type httpProxy struct {
|
|
type httpProxy struct {
|
|
|
- hostPort string
|
|
|
|
|
- username string
|
|
|
|
|
- password string
|
|
|
|
|
- forward proxy.Dialer
|
|
|
|
|
|
|
+ hostPort string
|
|
|
|
|
+ username string
|
|
|
|
|
+ password string
|
|
|
|
|
+ forward proxy.Dialer
|
|
|
|
|
+ customHeaders http.Header
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func newHTTP(uri *url.URL, forward proxy.Dialer) (proxy.Dialer, error) {
|
|
func newHTTP(uri *url.URL, forward proxy.Dialer) (proxy.Dialer, error) {
|
|
@@ -73,15 +75,20 @@ func newHTTP(uri *url.URL, forward proxy.Dialer) (proxy.Dialer, error) {
|
|
|
hp.password, _ = uri.User.Password()
|
|
hp.password, _ = uri.User.Password()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if upstreamProyConfig, ok := forward.(*UpstreamProxyConfig); ok {
|
|
|
|
|
+ hp.customHeaders = upstreamProyConfig.CustomHeaders
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return hp, nil
|
|
return hp, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (hp *httpProxy) Dial(network, addr string) (net.Conn, error) {
|
|
func (hp *httpProxy) Dial(network, addr string) (net.Conn, error) {
|
|
|
// Dial and create the http client connection.
|
|
// Dial and create the http client connection.
|
|
|
pc := &proxyConn{
|
|
pc := &proxyConn{
|
|
|
- authState: HTTP_AUTH_STATE_UNCHALLENGED,
|
|
|
|
|
- dialFn: hp.forward.Dial,
|
|
|
|
|
- proxyAddr: hp.hostPort,
|
|
|
|
|
|
|
+ authState: HTTP_AUTH_STATE_UNCHALLENGED,
|
|
|
|
|
+ dialFn: hp.forward.Dial,
|
|
|
|
|
+ proxyAddr: hp.hostPort,
|
|
|
|
|
+ customHeaders: hp.customHeaders,
|
|
|
}
|
|
}
|
|
|
err := pc.makeNewClientConn()
|
|
err := pc.makeNewClientConn()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -116,6 +123,7 @@ handshakeLoop:
|
|
|
type proxyConn struct {
|
|
type proxyConn struct {
|
|
|
dialFn DialFunc
|
|
dialFn DialFunc
|
|
|
proxyAddr string
|
|
proxyAddr string
|
|
|
|
|
+ customHeaders http.Header
|
|
|
httpClientConn *httputil.ClientConn
|
|
httpClientConn *httputil.ClientConn
|
|
|
hijackedConn net.Conn
|
|
hijackedConn net.Conn
|
|
|
staleReader *bufio.Reader
|
|
staleReader *bufio.Reader
|
|
@@ -144,6 +152,10 @@ func (pc *proxyConn) handshake(addr, username, password string) error {
|
|
|
req.Close = false
|
|
req.Close = false
|
|
|
req.Header.Set("User-Agent", "")
|
|
req.Header.Set("User-Agent", "")
|
|
|
|
|
|
|
|
|
|
+ for k, s := range pc.customHeaders {
|
|
|
|
|
+ req.Header[k] = s
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if pc.authState == HTTP_AUTH_STATE_CHALLENGED {
|
|
if pc.authState == HTTP_AUTH_STATE_CHALLENGED {
|
|
|
err := pc.authenticator.Authenticate(req, pc.authResponse)
|
|
err := pc.authenticator.Authenticate(req, pc.authResponse)
|
|
|
if err != nil {
|
|
if err != nil {
|