enable utls for websteps (#442)

This diff enables `websteps` to use uTLS for TLS parroting. It integrates the `oohttp.StdlibTransport` wrapper which uses the `ooni/oohttp` fork. `oohttp` supports TLS-like connections like `utls.Conn`.
As a prototype, the testhelper and `websteps` code now uses the `utls.HelloChrome_Auto` fingerprint, i.e. the simulated TLS fingerprint of the Google Chrome browser.

It is a further contribution for my GSoC project.

Reference issue: https://github.com/ooni/probe/issues/1733
This commit is contained in:
kelmenhorst
2021-08-18 16:10:27 +02:00
committed by GitHub
parent 21a2b315fe
commit 1874f7a7c2
10 changed files with 66 additions and 123 deletions
+28 -11
View File
@@ -9,9 +9,9 @@ import (
"net/url"
"sync"
"github.com/apex/log"
"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/http3"
oohttp "github.com/ooni/oohttp"
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
"github.com/ooni/probe-cli/v3/internal/errorsx"
"github.com/ooni/probe-cli/v3/internal/netxlite"
@@ -53,8 +53,8 @@ func NewQUICDialerResolver(resolver netxlite.Resolver) netxlite.QUICContextDiale
return dialer
}
// NewSingleH3Transport creates an http3.RoundTripper
func NewSingleH3Transport(qsess quic.EarlySession, tlscfg *tls.Config, qcfg *quic.Config) *http3.RoundTripper {
// NewSingleH3Transport creates an http3.RoundTripper.
func NewSingleH3Transport(qsess quic.EarlySession, tlscfg *tls.Config, qcfg *quic.Config) http.RoundTripper {
transport := &http3.RoundTripper{
DisableCompression: true,
TLSClientConfig: tlscfg,
@@ -64,16 +64,33 @@ func NewSingleH3Transport(qsess quic.EarlySession, tlscfg *tls.Config, qcfg *qui
return transport
}
// NewSingleTransport determines the appropriate HTTP Transport from the ALPN
func NewSingleTransport(conn net.Conn) (transport http.RoundTripper) {
// NewSingleTransport creates a new HTTP transport with a single-use dialer.
func NewSingleTransport(conn net.Conn) http.RoundTripper {
singledialer := &SingleDialer{conn: &conn}
transport = http.DefaultTransport.(*http.Transport).Clone()
transport.(*http.Transport).DialContext = singledialer.DialContext
transport.(*http.Transport).DialTLSContext = singledialer.DialContext
transport.(*http.Transport).DisableCompression = true
transport.(*http.Transport).MaxConnsPerHost = 1
transport := newBaseTransport()
transport.DialContext = singledialer.DialContext
transport.DialTLSContext = singledialer.DialContext
return transport
}
transport = &netxlite.HTTPTransportLogger{Logger: log.Log, HTTPTransport: transport.(*http.Transport)}
// NewSingleTransport creates a new HTTP transport with a custom dialer and handshaker.
func NewTransportWithDialer(dialer netxlite.Dialer, tlsConfig *tls.Config, handshaker netxlite.TLSHandshaker) http.RoundTripper {
transport := newBaseTransport()
transport.DialContext = dialer.DialContext
transport.DialTLSContext = (&netxlite.TLSDialer{
Config: tlsConfig,
Dialer: dialer,
TLSHandshaker: handshaker,
}).DialTLSContext
return transport
}
// newBaseTransport creates a new HTTP transport with the default dialer.
func newBaseTransport() (transport *oohttp.StdlibTransport) {
base := oohttp.DefaultTransport.(*oohttp.Transport).Clone()
base.DisableCompression = true
base.MaxConnsPerHost = 1
transport = &oohttp.StdlibTransport{Transport: base}
return transport
}
+11 -4
View File
@@ -1,16 +1,23 @@
package websteps
import (
"context"
"crypto/tls"
"net"
"github.com/ooni/probe-cli/v3/internal/netxlite"
utls "gitlab.com/yawning/utls.git"
)
// TLSDo performs the TLS check.
func TLSDo(conn net.Conn, hostname string) (*tls.Conn, error) {
tlsConn := tls.Client(conn, &tls.Config{
func TLSDo(ctx context.Context, conn net.Conn, hostname string) (net.Conn, error) {
tlsConf := &tls.Config{
ServerName: hostname,
NextProtos: []string{"h2", "http/1.1"},
})
err := tlsConn.Handshake()
}
h := &netxlite.TLSHandshakerConfigurable{
NewConn: netxlite.NewConnUTLS(&utls.HelloChrome_Auto),
}
tlsConn, _, err := h.Handshake(ctx, conn, tlsConf)
return tlsConn, err
}
@@ -241,7 +241,7 @@ func (m *Measurer) measureEndpointHTTPS(ctx context.Context, URL *url.URL, endpo
defer conn.Close()
// TLS handshake step
tlsconn, err := TLSDo(conn, URL.Hostname())
tlsconn, err := TLSDo(ctx, conn, URL.Hostname())
endpointMeasurement.TLSHandshake = &TLSHandshakeMeasurement{
Failure: archival.NewFailure(err),
}