Skip to content
Snippets Groups Projects
Commit 5a98c444 authored by David Fifield's avatar David Fifield
Browse files

First try at utls integration.

Disables proxy support: I'm using http.Transport.DialTLS to hook into
utls, and http.Transport.Proxy is ignored when DialTLS is set. We'll
have to manually make our own proxy connections within DialTLS.

It doesn't work properly yet because the HelloChrome_Auto fingerprint
we're using includes "h2" in the ALPN extension, which causes the server
to think it should use HTTP/2. The client side, however, uses HTTP/1.1
because it disable automatic HTTP/2 configuration when DialTLS is set.
So you have an HTTP/1.1 client talking to an HTTP/2 server, and an error
message like this:
	error in handling request: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x00\x00\x12\x04\x00\x00\x00\x00\x00\x00\x05\x00\x10\x00\x00\x00\x03\x00\x00\x00\xfa\x00\x06\x00\x10\x01@"

As a workaround, I'm not calling UConn.Handshake() before returning the
UConn from DialTLS. This seems to cause the caller to remove the ALPN
extension, thereby negotiating HTTP/1.1 on both sides. The downside are
the loss of HTTP/2, and the fact that a missing ALPN extension means our
fingerprint doesn't match what it's supposed to.
parent d1e64ca3
No related branches found
No related tags found
No related merge requests found
......@@ -48,6 +48,7 @@ import (
"time"
"git.torproject.org/pluggable-transports/goptlib.git"
tls "github.com/refraction-networking/utls"
)
const (
......@@ -337,10 +338,7 @@ func acceptLoop(ln *pt.SocksListener) error {
// configuration.
func checkProxyURL(u *url.URL) error {
if options.HelperAddr == nil {
// Without the helper we only support HTTP proxies.
if u.Scheme != "http" {
return fmt.Errorf("don't understand proxy URL scheme %q", u.Scheme)
}
return fmt.Errorf("no proxy allowed")
} else {
// With the helper we can use HTTP and SOCKS (because it is the
// browser that does the proxying, not us).
......@@ -433,6 +431,41 @@ func main() {
}
}
httpTransport.DialContext = nil
httpTransport.Dial = func(network, addr string) (net.Conn, error) {
panic("disable plaintext")
}
httpTransport.DialTLS = func(network, addr string) (net.Conn, error) {
if httpTransport.TLSClientConfig != nil {
return nil, fmt.Errorf("error: non-nil TLSClientConfig")
}
config := &tls.Config{}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
config.ServerName = addr[:colonPos]
conn, err := net.Dial(network, addr)
if err != nil {
return nil, err
}
uconn := tls.UClient(conn, config, tls.HelloChrome_Auto)
// We cannot call uconn.Handshake() here: it causes the server
// to use HTTP/2, when the client is still using HTTP/1.1,
// because net/http disables automatic HTTP/2 support when using
// DialTLS.
// https://github.com/golang/go/issues/21753
// "Auto-HTTP/2 is disabled by DialTLS being set"
// https://github.com/golang/go/issues/21336
// But: returning without calling uconn.Handshake causes the
// ClientHello to lack the ALPN extension entirely...
//
// err = uconn.Handshake()
return uconn, err
}
listeners := make([]net.Listener, 0)
for _, methodName := range ptInfo.MethodNames {
switch methodName {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment