[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [meek/utls_2] Honor a ServerName in utls.Config if given.
commit 553a0b6d63f36987e542460187957f49780740a7
Author: David Fifield <david@xxxxxxxxxxxxxxx>
Date: Wed Feb 6 16:58:23 2019 -0700
Honor a ServerName in utls.Config if given.
---
meek-client/utls.go | 12 +++--
meek-client/utls_test.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 5 deletions(-)
diff --git a/meek-client/utls.go b/meek-client/utls.go
index 1ea0cd0..6f3d594 100644
--- a/meek-client/utls.go
+++ b/meek-client/utls.go
@@ -94,12 +94,14 @@ func dialUTLS(network, addr string, cfg *utls.Config, clientHelloID *utls.Client
if err != nil {
return nil, err
}
- serverName, _, err := net.SplitHostPort(addr)
- if err != nil {
- return nil, err
- }
uconn := utls.UClient(conn, cfg, *clientHelloID)
- uconn.SetSNI(serverName)
+ if cfg == nil || cfg.ServerName == "" {
+ serverName, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ uconn.SetSNI(serverName)
+ }
err = uconn.Handshake()
if err != nil {
return nil, err
diff --git a/meek-client/utls_test.go b/meek-client/utls_test.go
index 8facb88..8607604 100644
--- a/meek-client/utls_test.go
+++ b/meek-client/utls_test.go
@@ -1,8 +1,14 @@
package main
import (
+ "bytes"
+ "io"
+ "net"
"net/http"
+ "net/url"
"testing"
+
+ utls "github.com/refraction-networking/utls"
)
func TestCopyPublicFieldsHTTPTransport(t *testing.T) {
@@ -39,3 +45,118 @@ func TestCopyPublicFieldsHTTPTransport(t *testing.T) {
t.Errorf("mismatch on MaxResponseHeaderBytes")
}
}
+
+// Return a byte slice which is the ClientHello sent when rt does a RoundTrip.
+// Opens a temporary listener on an ephemeral port on localhost. The host you
+// provide can be an IP address like "127.0.0.1" or a name like "localhost", but
+// it has to resolve to localhost.
+func clientHelloResultingFromRoundTrip(t *testing.T, host string, rt *UTLSRoundTripper) ([]byte, error) {
+ ch := make(chan []byte, 1)
+
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return nil, err
+ }
+ defer ln.Close()
+
+ go func() {
+ defer func() {
+ close(ch)
+ }()
+ conn, err := ln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer conn.Close()
+ buf := make([]byte, 1024)
+ n, err := conn.Read(buf)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ ch <- buf[:n]
+ }()
+
+ _, port, err := net.SplitHostPort(ln.Addr().String())
+ if err != nil {
+ return nil, err
+ }
+ u := &url.URL{
+ Scheme: "https",
+ Host: net.JoinHostPort(host, port),
+ }
+ req, err := http.NewRequest("POST", u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ // The RoundTrip fails because the goroutine "server" hangs up. So
+ // ignore an EOF error.
+ _, err = rt.RoundTrip(req)
+ if err != nil && err != io.EOF {
+ return nil, err
+ }
+
+ return <-ch, nil
+}
+
+func TestUTLSServerName(t *testing.T) {
+ const clientHelloIDName = "HelloFirefox_63"
+
+ // No ServerName, dial IP address. Results in an invalid server_name
+ // extension with a 0-length host_name. Not sure if that's what it
+ // should do, but check if the behavior ever changes.
+ rt, err := NewUTLSRoundTripper(clientHelloIDName, &utls.Config{InsecureSkipVerify: true}, nil)
+ if err != nil {
+ panic(err)
+ }
+ buf, err := clientHelloResultingFromRoundTrip(t, "127.0.0.1", rt.(*UTLSRoundTripper))
+ if err != nil {
+ panic(err)
+ }
+ if !bytes.Contains(buf, []byte("\x00\x00\x00\x05\x00\x03\x00\x00\x00")) {
+ t.Errorf("expected 0-length server_name extension with no ServerName and IP address dial")
+ }
+
+ // No ServerName, dial hostname. server_name extension should come from
+ // the dial address.
+ rt, err = NewUTLSRoundTripper(clientHelloIDName, &utls.Config{InsecureSkipVerify: true}, nil)
+ if err != nil {
+ panic(err)
+ }
+ buf, err = clientHelloResultingFromRoundTrip(t, "localhost", rt.(*UTLSRoundTripper))
+ if err != nil {
+ panic(err)
+ }
+ if !bytes.Contains(buf, []byte("\x00\x00\x00\x0e\x00\x0c\x00\x00\x09localhost")) {
+ t.Errorf("expected \"localhost\" server_name extension with no ServerName and hostname dial")
+ }
+
+ // Given ServerName, dial IP address. server_name extension should from
+ // the ServerName.
+ rt, err = NewUTLSRoundTripper(clientHelloIDName, &utls.Config{InsecureSkipVerify: true, ServerName: "test.example"}, nil)
+ if err != nil {
+ panic(err)
+ }
+ buf, err = clientHelloResultingFromRoundTrip(t, "127.0.0.1", rt.(*UTLSRoundTripper))
+ if err != nil {
+ panic(err)
+ }
+ if !bytes.Contains(buf, []byte("\x00\x00\x00\x11\x00\x0f\x00\x00\x0ctest.example")) {
+ t.Errorf("expected \"test.example\" server_name extension with given ServerName and IP address dial")
+ }
+
+ // Given ServerName, dial hostname. server_name extension should from
+ // the ServerName.
+ rt, err = NewUTLSRoundTripper(clientHelloIDName, &utls.Config{InsecureSkipVerify: true, ServerName: "test.example"}, nil)
+ if err != nil {
+ panic(err)
+ }
+ buf, err = clientHelloResultingFromRoundTrip(t, "localhost", rt.(*UTLSRoundTripper))
+ if err != nil {
+ panic(err)
+ }
+ if !bytes.Contains(buf, []byte("\x00\x00\x00\x11\x00\x0f\x00\x00\x0ctest.example")) {
+ t.Errorf("expected \"test.example\" server_name extension with given ServerName and hostname dial")
+ }
+}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits