[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [obfs4/master] transports/meeklite: Add `utls` argument to configure behavior
commit e4020b18f7aaafe9f4cb345630bfe18a5e44a8d2
Author: Yawning Angel <yawning@xxxxxxxxxxxxxxx>
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
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits