[tor-commits] [meek/utls_2] socks5 proxy support for uTLS.

dcf at torproject.org dcf at torproject.org
Sat Feb 2 08:54:26 UTC 2019


commit 34f28e8273062c1f6f6fa60f7816dca63a191a5e
Author: David Fifield <david at bamsoftware.com>
Date:   Sat Feb 2 01:52:10 2019 -0700

    socks5 proxy support for uTLS.
---
 meek-client/meek-client.go |  2 +-
 meek-client/utls.go        | 59 ++++++++++++++++++++++++++++++++++++----------
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/meek-client/meek-client.go b/meek-client/meek-client.go
index 462eeb3..5cc889c 100644
--- a/meek-client/meek-client.go
+++ b/meek-client/meek-client.go
@@ -323,7 +323,7 @@ func handler(conn *pt.SocksConn) error {
 		}
 		info.RoundTripper = helperRoundTripper
 	} else if utlsOK {
-		info.RoundTripper, err = NewUTLSRoundTripper(utlsName, nil)
+		info.RoundTripper, err = NewUTLSRoundTripper(utlsName, nil, options.ProxyURL)
 		if err != nil {
 			return err
 		}
diff --git a/meek-client/utls.go b/meek-client/utls.go
index 7372c20..67cf104 100644
--- a/meek-client/utls.go
+++ b/meek-client/utls.go
@@ -45,6 +45,7 @@ import (
 
 	utls "github.com/refraction-networking/utls"
 	"golang.org/x/net/http2"
+	"golang.org/x/net/proxy"
 )
 
 // Copy the public fields (fields for which CanSet is true) from src to dst.
@@ -85,12 +86,8 @@ func addrForDial(url *url.URL) (string, error) {
 
 // Analogous to tls.Dial. Connect to the given address and initiate a TLS
 // handshake using the given ClientHelloID, returning the resulting connection.
-func dialUTLS(network, addr string, cfg *utls.Config, clientHelloID *utls.ClientHelloID) (*utls.UConn, error) {
-	if options.ProxyURL != nil {
-		return nil, fmt.Errorf("no proxy allowed with uTLS")
-	}
-
-	conn, err := net.Dial(network, addr)
+func dialUTLS(network, addr string, cfg *utls.Config, clientHelloID *utls.ClientHelloID, forward proxy.Dialer) (*utls.UConn, error) {
+	conn, err := forward.Dial(network, addr)
 	if err != nil {
 		return nil, err
 	}
@@ -116,6 +113,7 @@ type UTLSRoundTripper struct {
 
 	clientHelloID *utls.ClientHelloID
 	config        *utls.Config
+	proxyDialer   proxy.Dialer
 	rt            http.RoundTripper
 }
 
@@ -136,7 +134,7 @@ func (rt *UTLSRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
 		// On the first call, make an http.Transport or http2.Transport
 		// as appropriate.
 		var err error
-		rt.rt, err = makeRoundTripper(req.URL, rt.clientHelloID, rt.config)
+		rt.rt, err = makeRoundTripper(req.URL, rt.clientHelloID, rt.config, rt.proxyDialer)
 		if err != nil {
 			return nil, err
 		}
@@ -145,16 +143,48 @@ func (rt *UTLSRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
 	return rt.rt.RoundTrip(req)
 }
 
-func makeRoundTripper(url *url.URL, clientHelloID *utls.ClientHelloID, cfg *utls.Config) (http.RoundTripper, error) {
+func makeProxyDialer(proxyURL *url.URL) (proxy.Dialer, error) {
+	var proxyDialer proxy.Dialer = proxy.Direct
+	if proxyURL == nil {
+		return proxyDialer, nil
+	}
+
+	proxyAddr, err := addrForDial(proxyURL)
+	if err != nil {
+		return nil, err
+	}
+
+	var auth *proxy.Auth
+	if userpass := proxyURL.User; userpass != nil {
+		auth = &proxy.Auth{
+			User: userpass.Username(),
+		}
+		if password, ok := userpass.Password(); ok {
+			auth.Password = password
+		}
+	}
+
+	switch proxyURL.Scheme {
+	case "socks5":
+		proxyDialer, err = proxy.SOCKS5("tcp", proxyAddr, auth, proxyDialer)
+	default:
+		return nil, fmt.Errorf("cannot use proxy scheme %q with uTLS", proxyURL.Scheme)
+	}
+
+	return proxyDialer, err
+}
+
+func makeRoundTripper(url *url.URL, clientHelloID *utls.ClientHelloID, cfg *utls.Config, proxyDialer proxy.Dialer) (http.RoundTripper, error) {
 	addr, err := addrForDial(url)
 	if err != nil {
 		return nil, err
 	}
 
-	// Connect to the given address and initiate a TLS handshake using
-	// the given ClientHelloID. Return the resulting connection.
+	// Connect to the given address, through a proxy if requested, and
+	// initiate a TLS handshake using the given ClientHelloID. Return the
+	// resulting connection.
 	dial := func(network, addr string) (*utls.UConn, error) {
-		return dialUTLS(network, addr, cfg, clientHelloID)
+		return dialUTLS(network, addr, cfg, clientHelloID, proxyDialer)
 	}
 
 	bootstrapConn, err := dial("tcp", addr)
@@ -237,7 +267,7 @@ var clientHelloIDMap = map[string]*utls.ClientHelloID{
 	"helloios_11_1":         &utls.HelloIOS_11_1,
 }
 
-func NewUTLSRoundTripper(name string, cfg *utls.Config) (http.RoundTripper, error) {
+func NewUTLSRoundTripper(name string, cfg *utls.Config, proxyURL *url.URL) (http.RoundTripper, error) {
 	// Lookup is case-insensitive.
 	clientHelloID, ok := clientHelloIDMap[strings.ToLower(name)]
 	if !ok {
@@ -247,8 +277,13 @@ func NewUTLSRoundTripper(name string, cfg *utls.Config) (http.RoundTripper, erro
 		// Special case for "none" and HelloGolang.
 		return httpRoundTripper, nil
 	}
+	proxyDialer, err := makeProxyDialer(proxyURL)
+	if err != nil {
+		return nil, err
+	}
 	return &UTLSRoundTripper{
 		clientHelloID: clientHelloID,
 		config:        cfg,
+		proxyDialer:   proxyDialer,
 	}, nil
 }





More information about the tor-commits mailing list