commit e4020b18f7aaafe9f4cb345630bfe18a5e44a8d2
Author: Yawning Angel <[email protected]>
Date:   Mon Jan 21 18:47:42 2019 +0000

    transports/meeklite: Add `utls` argument to configure behavior
    
    Per dcf:
    > As for the TODO, my plan was was to expose a "utls" SOCKS arg
    > to make it configurable per bridge, and just reuse the utls
    > Client Hello ID names:
    >       utls=HelloChrome_Auto
    
    This adds support for all currently supported utls ClientHello IDs
    with the following caveats/differences:
    
     * `none` - Disables using utls entirely, forces `crypto/tls`.
     * `HelloGolang` - Alias of `none`, since using utls is pointless.
     * `HelloCustom` - Omitted as pointless.
---
 transports/meeklite/meek.go      | 21 ++++++++++++++-
 transports/meeklite/transport.go | 58 ++++++++++++++++++++++++++++++----------
 2 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/transports/meeklite/meek.go b/transports/meeklite/meek.go
index fb6aa0d..e009916 100644
--- a/transports/meeklite/meek.go
+++ b/transports/meeklite/meek.go
@@ -44,6 +44,8 @@ import (
        "sync"
        "time"
 
+       utls "github.com/refraction-networking/utls"
+
        "git.torproject.org/pluggable-transports/goptlib.git"
        "gitlab.com/yawning/obfs4.git/transports/base"
 )
@@ -51,6 +53,7 @@ import (
 const (
        urlArg   = "url"
        frontArg = "front"
+       utlsArg  = "utls"
 
        maxChanBacklog = 16
 
@@ -73,6 +76,8 @@ var (
 type meekClientArgs struct {
        url   *gourl.URL
        front string
+
+       utls *utls.ClientHelloID
 }
 
 func (ca *meekClientArgs) Network() string {
@@ -104,6 +109,12 @@ func newClientArgs(args *pt.Args) (ca *meekClientArgs, err 
error) {
        // Parse the (optional) front argument.
        ca.front, _ = args.Get(frontArg)
 
+       // Parse the (optional) utls argument.
+       utlsOpt, _ := args.Get(utlsArg)
+       if ca.utls, err = parseClientHelloID(utlsOpt); err != nil {
+               return nil, err
+       }
+
        return ca, nil
 }
 
@@ -343,10 +354,18 @@ func newMeekConn(network, addr string, dialFn 
base.DialFunc, ca *meekClientArgs)
                return nil, err
        }
 
+       var rt http.RoundTripper
+       switch ca.utls {
+       case nil:
+               rt = &http.Transport{Dial: dialFn}
+       default:
+               rt = newRoundTripper(dialFn, ca.utls)
+       }
+
        conn := &meekConn{
                args:            ca,
                sessionID:       id,
-               roundTripper:    newRoundTripper(dialFn),
+               roundTripper:    rt,
                workerWrChan:    make(chan []byte, maxChanBacklog),
                workerRdChan:    make(chan []byte, maxChanBacklog),
                workerCloseChan: make(chan struct{}),
diff --git a/transports/meeklite/transport.go b/transports/meeklite/transport.go
index 6ccef31..59000a3 100644
--- a/transports/meeklite/transport.go
+++ b/transports/meeklite/transport.go
@@ -33,13 +33,35 @@ import (
        "gitlab.com/yawning/obfs4.git/transports/base"
 )
 
-var errProtocolNegotiated = errors.New("meek_lite: protocol negotiated")
+var (
+       errProtocolNegotiated = errors.New("meek_lite: protocol negotiated")
+
+       // This should be kept in sync with what is available in utls.
+       clientHelloIDMap = map[string]*utls.ClientHelloID{
+               "hellogolang":           nil, // Don't bother with utls.
+               "hellorandomized":       &utls.HelloRandomized,
+               "hellorandomizedalpn":   &utls.HelloRandomizedALPN,
+               "hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
+               "hellofirefox_auto":     &utls.HelloFirefox_Auto,
+               "hellofirefox_55":       &utls.HelloFirefox_55,
+               "hellofirefox_56":       &utls.HelloFirefox_56,
+               "hellofirefox_63":       &utls.HelloFirefox_63,
+               "hellochrome_auto":      &utls.HelloChrome_Auto,
+               "hellochrome_58":        &utls.HelloChrome_58,
+               "hellochrome_62":        &utls.HelloChrome_62,
+               "hellochrome_70":        &utls.HelloChrome_70,
+               "helloios_auto":         &utls.HelloIOS_Auto,
+               "helloios_11_1":         &utls.HelloIOS_11_1,
+       }
+       defaultClientHello = &utls.HelloChrome_Auto
+)
 
 type roundTripper struct {
        sync.Mutex
 
-       transport http.RoundTripper
-       dialFn    base.DialFunc
+       clientHelloID *utls.ClientHelloID
+       dialFn        base.DialFunc
+       transport     http.RoundTripper
 
        initConn net.Conn
 }
@@ -105,15 +127,7 @@ func (rt *roundTripper) dialTLS(network, addr string) 
(net.Conn, error) {
                host = addr
        }
 
-       // TODO: Make this configurable.  What "works" is host dependent.
-       //  * HelloChrome_Auto  - Failures in a stand alone testcase against 
google.com
-       //  * HelloFirefox_Auto - Fails with the azure bridge, incompatible 
group.
-       //  * HelloIOS_Auto     - Seems to work.
-       //
-       // Since HelloChrome_Auto works with azure, that's what'll be used for
-       // now, since that's what the overwelming vast majority of people will
-       // use.
-       conn := utls.UClient(rawConn, &utls.Config{ServerName: host}, 
utls.HelloChrome_Auto)
+       conn := utls.UClient(rawConn, &utls.Config{ServerName: host}, 
*rt.clientHelloID)
        if err = conn.Handshake(); err != nil {
                conn.Close()
                return nil, err
@@ -154,10 +168,26 @@ func getDialTLSAddr(u *url.URL) string {
        return net.JoinHostPort(u.Host, u.Scheme)
 }
 
-func newRoundTripper(dialFn base.DialFunc) http.RoundTripper {
+func newRoundTripper(dialFn base.DialFunc, clientHelloID *utls.ClientHelloID) 
http.RoundTripper {
        return &roundTripper{
-               dialFn: dialFn,
+               clientHelloID: clientHelloID,
+               dialFn:        dialFn,
+       }
+}
+
+func parseClientHelloID(s string) (*utls.ClientHelloID, error) {
+       s = strings.ToLower(s)
+       switch s {
+       case "none":
+               return nil, nil
+       case "":
+               return defaultClientHello, nil
+       default:
+               if ret := clientHelloIDMap[s]; ret != nil {
+                       return ret, nil
+               }
        }
+       return nil, fmt.Errorf("invalid ClientHelloID: '%v'", s)
 }
 
 func init() {

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to