chore: upgrade deps and attempt to enable using go1.19 (#869)

* upgrade to our go.mod enabled of psiphon-tunnel-core such that
we're now using v2.0.24 of the tunnel-core;

* upgrade to the latest lucas-clemente/quic-go release;

* upgrade to the latest ooni/oohttp release (which is based on go1.19
but the diff seems good enough to continue using go1.18.x as well);

* upgrade to the latest ooni/oocrypto release (for which we can make the
same remarks regarding using go1.18.x);

* deal with changes in lucas-clemente/quic-go API as well as changes
in what a go1.19 *tls.Conn compatible type should look like.

Unfortunately, we cannot switch to go1.19 because psiphon forks quic-go
and their fork's still not building using such a version of go.

Part of ooni/probe#2211.
This commit is contained in:
Simone Basso
2022-08-19 11:26:50 +02:00
committed by GitHub
parent 097926c51f
commit 9ffa124511
28 changed files with 291 additions and 244 deletions
@@ -179,7 +179,7 @@ func (m *Measurer) quicHandshake(ctx context.Context, index int64,
RootCAs: netxlite.NewDefaultCertPool(),
ServerName: sni,
}
_, err := dialer.DialContext(ctx, "udp", address, tlsConfig, &quic.Config{})
_, err := dialer.DialContext(ctx, address, tlsConfig, &quic.Config{})
ol.Stop(err)
sp.QUICHandshake = trace.FirstQUICHandshakeOrNil() // record the first handshake from the buffer
sp.NetworkEvents = append(sp.NetworkEvents, trace.NetworkEvents()...)
+1 -1
View File
@@ -423,7 +423,7 @@ func (mx *Measurer) QUICHandshakeWithDB(ctx context.Context, db WritableDB,
defer cancel()
qd := mx.NewQUICDialerWithoutResolver(db, mx.Logger)
defer qd.CloseIdleConnections()
qconn, err := qd.DialContext(ctx, "udp", address, config, &quic.Config{})
qconn, err := qd.DialContext(ctx, address, config, &quic.Config{})
ol.Stop(err)
return qconn, err
}
+2 -2
View File
@@ -105,7 +105,7 @@ type quicDialerDB struct {
logger model.Logger
}
func (qh *quicDialerDB) DialContext(ctx context.Context, network, address string,
func (qh *quicDialerDB) DialContext(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
started := time.Since(qh.begin).Seconds()
var state tls.ConnectionState
@@ -116,7 +116,7 @@ func (qh *quicDialerDB) DialContext(ctx context.Context, network, address string
}
dialer := netxlite.NewQUICDialerWithoutResolver(listener, qh.logger)
defer dialer.CloseIdleConnections()
sess, err := dialer.DialContext(ctx, network, address, tlsConfig, quicConfig)
sess, err := dialer.DialContext(ctx, address, tlsConfig, quicConfig)
if err == nil {
<-sess.HandshakeComplete().Done() // robustness (the dialer already does that)
state = sess.ConnectionState().TLS.ConnectionState
+2 -2
View File
@@ -32,10 +32,10 @@ type quicDialerTrace struct {
var _ model.QUICDialer = &quicDialerTrace{}
// DialContext implements model.QUICDialer.DialContext.
func (qdx *quicDialerTrace) DialContext(ctx context.Context, network string,
func (qdx *quicDialerTrace) DialContext(ctx context.Context,
address string, tlsConfig *tls.Config, quicConfig *quic.Config) (
quic.EarlyConnection, error) {
return qdx.qd.DialContext(netxlite.ContextWithTrace(ctx, qdx.tx), network, address, tlsConfig, quicConfig)
return qdx.qd.DialContext(netxlite.ContextWithTrace(ctx, qdx.tx), address, tlsConfig, quicConfig)
}
// CloseIdleConnections implements model.QUICDialer.CloseIdleConnections.
+4 -4
View File
@@ -42,7 +42,7 @@ func TestNewQUICDialerWithoutResolver(t *testing.T) {
trace := NewTrace(0, zeroTime)
var hasCorrectTrace bool
underlying := &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config,
MockDialContext: func(ctx context.Context, address string, tlsConfig *tls.Config,
quicConfig *quic.Config) (quic.EarlyConnection, error) {
gotTrace := netxlite.ContextTraceOrDefault(ctx)
hasCorrectTrace = (gotTrace == trace)
@@ -55,7 +55,7 @@ func TestNewQUICDialerWithoutResolver(t *testing.T) {
listener := &mocks.QUICListener{}
dialer := trace.NewQUICDialerWithoutResolver(listener, model.DiscardLogger)
ctx := context.Background()
conn, err := dialer.DialContext(ctx, "udp", "1.1.1.1:443", &tls.Config{}, &quic.Config{})
conn, err := dialer.DialContext(ctx, "1.1.1.1:443", &tls.Config{}, &quic.Config{})
if !errors.Is(err, expectedErr) {
t.Fatal("unexpected err", err)
}
@@ -122,7 +122,7 @@ func TestNewQUICDialerWithoutResolver(t *testing.T) {
ServerName: "dns.cloudflare.com",
}
ctx := context.Background()
qconn, err := dialer.DialContext(ctx, "udp", "1.1.1.1:443", tlsConfig, &quic.Config{})
qconn, err := dialer.DialContext(ctx, "1.1.1.1:443", tlsConfig, &quic.Config{})
if !errors.Is(err, mockedErr) {
t.Fatal("unexpected err", err)
}
@@ -231,7 +231,7 @@ func TestNewQUICDialerWithoutResolver(t *testing.T) {
ServerName: "dns.cloudflare.com",
}
ctx := context.Background()
qconn, err := dialer.DialContext(ctx, "udp", "1.1.1.1:443", tlsConfig, &quic.Config{})
qconn, err := dialer.DialContext(ctx, "1.1.1.1:443", tlsConfig, &quic.Config{})
if !errors.Is(err, mockedErr) {
t.Fatal("unexpected err", err)
}
+3 -3
View File
@@ -413,7 +413,7 @@ func TestTrace(t *testing.T) {
tx := &Trace{
NewQUICDialerWithoutResolverFn: func(listener model.QUICListener, dl model.DebugLogger) model.QUICDialer {
return &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, mockedErr
},
@@ -422,7 +422,7 @@ func TestTrace(t *testing.T) {
}
qdx := tx.newQUICDialerWithoutResolver(&mocks.QUICListener{}, model.DiscardLogger)
ctx := context.Background()
qconn, err := qdx.DialContext(ctx, "udp", "1.1.1.1:443", &tls.Config{}, &quic.Config{})
qconn, err := qdx.DialContext(ctx, "1.1.1.1:443", &tls.Config{}, &quic.Config{})
if !errors.Is(err, mockedErr) {
t.Fatal("unexpected err", err)
}
@@ -464,7 +464,7 @@ func TestTrace(t *testing.T) {
}
dialer := tx.newQUICDialerWithoutResolver(listener, model.DiscardLogger)
ctx := context.Background()
qconn, err := dialer.DialContext(ctx, "udp", "1.1.1.1:443", tlsConfig, &quic.Config{})
qconn, err := dialer.DialContext(ctx, "1.1.1.1:443", tlsConfig, &quic.Config{})
if !errors.Is(err, mockedErr) {
t.Fatal("unexpected err", err)
}
+5 -3
View File
@@ -24,17 +24,19 @@ func (ql *QUICListener) Listen(addr *net.UDPAddr) (model.UDPLikeConn, error) {
// QUICDialer is a mockable netxlite.QUICDialer.
type QUICDialer struct {
// MockDialContext allows mocking DialContext.
MockDialContext func(ctx context.Context, network, address string,
MockDialContext func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error)
// MockCloseIdleConnections allows mocking CloseIdleConnections.
MockCloseIdleConnections func()
}
var _ model.QUICDialer = &QUICDialer{}
// DialContext calls MockDialContext.
func (qcd *QUICDialer) DialContext(ctx context.Context, network, address string,
func (qcd *QUICDialer) DialContext(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return qcd.MockDialContext(ctx, network, address, tlsConfig, quicConfig)
return qcd.MockDialContext(ctx, address, tlsConfig, quicConfig)
}
// CloseIdleConnections calls MockCloseIdleConnections.
+2 -2
View File
@@ -37,14 +37,14 @@ func TestQUICDialer(t *testing.T) {
t.Run("DialContext", func(t *testing.T) {
expected := errors.New("mocked error")
qcd := &QUICDialer{
MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
MockDialContext: func(ctx context.Context, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, expected
},
}
ctx := context.Background()
tlsConfig := &tls.Config{}
quicConfig := &quic.Config{}
qconn, err := qcd.DialContext(ctx, "udp", "dns.google:443", tlsConfig, quicConfig)
qconn, err := qcd.DialContext(ctx, "dns.google:443", tlsConfig, quicConfig)
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
}
+8
View File
@@ -28,6 +28,9 @@ type TLSConn struct {
// MockHandshakeContext allows to mock the HandshakeContext method.
MockHandshakeContext func(ctx context.Context) error
// MockNetConn returns the underlying net.Conn
MockNetConn func() net.Conn
}
// ConnectionState calls MockConnectionState.
@@ -40,6 +43,11 @@ func (c *TLSConn) HandshakeContext(ctx context.Context) error {
return c.MockHandshakeContext(ctx)
}
// NetConn calls MockNetConn.
func (c *TLSConn) NetConn() net.Conn {
return c.MockNetConn()
}
// TLSDialer allows to mock netxlite.TLSDialer.
type TLSDialer struct {
// MockCloseIdleConnections allows to mock the CloseIdleConnections method.
+12
View File
@@ -60,6 +60,18 @@ func TestTLSConn(t *testing.T) {
t.Fatal("not the error we expected", err)
}
})
t.Run("NetConn", func(t *testing.T) {
conn := &Conn{}
c := &TLSConn{
MockNetConn: func() net.Conn {
return conn
},
}
if o := c.NetConn(); o != conn {
t.Fatal("unexpected result")
}
})
}
func TestTLSDialer(t *testing.T) {
+1 -1
View File
@@ -204,7 +204,7 @@ type QUICDialer interface {
// - set NextProtos to []string{"h3"}.
//
// Typically, you want to pass `&quic.Config{}` as quicConfig.
DialContext(ctx context.Context, network, address string,
DialContext(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error)
// CloseIdleConnections closes idle connections, if any.
+2 -2
View File
@@ -435,7 +435,7 @@ func TestMeasureWithQUICDialer(t *testing.T) {
NextProtos: []string{"h3"},
RootCAs: netxlite.NewDefaultCertPool(),
}
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("443"), config, &quic.Config{})
sess, err := d.DialContext(ctx, quictesting.Endpoint("443"), config, &quic.Config{})
if err != nil {
t.Fatal(err)
}
@@ -456,7 +456,7 @@ func TestMeasureWithQUICDialer(t *testing.T) {
RootCAs: netxlite.NewDefaultCertPool(),
}
// Here we assume <target-address>:1 is filtered
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("1"), config, &quic.Config{})
sess, err := d.DialContext(ctx, quictesting.Endpoint("1"), config, &quic.Config{})
if err == nil || err.Error() != netxlite.FailureGenericTimeoutError {
t.Fatal("not the error we expected", err)
}
+14 -14
View File
@@ -122,7 +122,7 @@ func ParseUDPAddr(address string) (*net.UDPAddr, error) {
//
// 2. if tlsConfig.NextProtos is empty _and_ the port is 443 or 8853,
// then we configure, respectively, "h3" and "dq".
func (d *quicDialerQUICGo) DialContext(ctx context.Context, network string,
func (d *quicDialerQUICGo) DialContext(ctx context.Context,
address string, tlsConfig *tls.Config, quicConfig *quic.Config) (
quic.EarlyConnection, error) {
udpAddr, err := ParseUDPAddr(address)
@@ -194,9 +194,9 @@ var _ model.QUICDialer = &quicDialerHandshakeCompleter{}
// DialContext implements model.QUICDialer.DialContext.
func (d *quicDialerHandshakeCompleter) DialContext(
ctx context.Context, network, address string,
ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
conn, err := d.Dialer.DialContext(ctx, network, address, tlsConfig, quicConfig)
conn, err := d.Dialer.DialContext(ctx, address, tlsConfig, quicConfig)
if err != nil {
return nil, err
}
@@ -253,7 +253,7 @@ var _ model.QUICDialer = &quicDialerResolver{}
// 1. if tlsConfig.ServerName is empty, we will use the hostname
// contained inside of the `address` endpoint.
func (d *quicDialerResolver) DialContext(
ctx context.Context, network, address string,
ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
onlyhost, onlyport, err := net.SplitHostPort(address)
if err != nil {
@@ -272,7 +272,7 @@ func (d *quicDialerResolver) DialContext(
for _, addr := range addrs {
target := net.JoinHostPort(addr, onlyport)
qconn, err := d.Dialer.DialContext(
ctx, network, target, tlsConfig, quicConfig)
ctx, target, tlsConfig, quicConfig)
if err == nil {
return qconn, nil
}
@@ -325,16 +325,16 @@ var _ model.QUICDialer = &quicDialerLogger{}
// DialContext implements QUICContextDialer.DialContext.
func (d *quicDialerLogger) DialContext(
ctx context.Context, network, address string,
ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
d.Logger.Debugf("quic_dial%s %s/%s...", d.operationSuffix, address, network)
qconn, err := d.Dialer.DialContext(ctx, network, address, tlsConfig, quicConfig)
d.Logger.Debugf("quic_dial%s %s/udp...", d.operationSuffix, address)
qconn, err := d.Dialer.DialContext(ctx, address, tlsConfig, quicConfig)
if err != nil {
d.Logger.Debugf("quic_dial%s %s/%s... %s", d.operationSuffix,
address, network, err)
d.Logger.Debugf("quic_dial%s %s/udp... %s", d.operationSuffix,
address, err)
return nil, err
}
d.Logger.Debugf("quic_dial%s %s/%s... ok", d.operationSuffix, address, network)
d.Logger.Debugf("quic_dial%s %s/udp... ok", d.operationSuffix, address)
return qconn, nil
}
@@ -358,7 +358,7 @@ var _ model.QUICDialer = &quicDialerSingleUse{}
// DialContext implements QUICDialer.DialContext.
func (s *quicDialerSingleUse) DialContext(
ctx context.Context, network, addr string, tlsCfg *tls.Config,
ctx context.Context, addr string, tlsCfg *tls.Config,
cfg *quic.Config) (quic.EarlyConnection, error) {
var qconn quic.EarlyConnection
defer s.mu.Unlock()
@@ -436,9 +436,9 @@ var _ model.QUICDialer = &quicDialerErrWrapper{}
// DialContext implements ContextDialer.DialContext
func (d *quicDialerErrWrapper) DialContext(
ctx context.Context, network string, host string,
ctx context.Context, host string,
tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
qconn, err := d.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
qconn, err := d.QUICDialer.DialContext(ctx, host, tlsCfg, cfg)
if err != nil {
return nil, NewErrWrapper(
ClassifyQUICHandshakeError, QUICHandshakeOperation, err)
+31 -31
View File
@@ -134,7 +134,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
defer systemdialer.CloseIdleConnections() // just to see it running
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "a.b.c.d", tlsConfig, &quic.Config{})
ctx, "a.b.c.d", tlsConfig, &quic.Config{})
if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") {
t.Fatal("not the error we expected", err)
}
@@ -152,7 +152,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.4.4:xyz", tlsConfig, &quic.Config{})
ctx, "8.8.4.4:xyz", tlsConfig, &quic.Config{})
if err == nil || !strings.HasSuffix(err.Error(), "invalid syntax") {
t.Fatal("not the error we expected", err)
}
@@ -170,7 +170,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "a.b.c.d:0", tlsConfig, &quic.Config{})
ctx, "a.b.c.d:0", tlsConfig, &quic.Config{})
if !errors.Is(err, ErrInvalidIP) {
t.Fatal("not the error we expected", err)
}
@@ -193,7 +193,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{})
ctx, "8.8.8.8:443", tlsConfig, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
}
@@ -212,7 +212,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel() // fail immediately
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{})
ctx, "8.8.8.8:443", tlsConfig, &quic.Config{})
if !errors.Is(err, context.Canceled) {
t.Fatal("not the error we expected", err)
}
@@ -238,7 +238,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{})
ctx, "8.8.8.8:443", tlsConfig, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
}
@@ -279,7 +279,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.8.8:8853", tlsConfig, &quic.Config{})
ctx, "8.8.8.8:8853", tlsConfig, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
}
@@ -318,7 +318,7 @@ func TestQUICDialerQUICGo(t *testing.T) {
}
ctx := context.Background()
qconn, err := systemdialer.DialContext(
ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{})
ctx, "8.8.8.8:443", tlsConfig, &quic.Config{})
if err != nil {
t.Fatal(err)
}
@@ -336,14 +336,14 @@ func TestQUICDialerHandshakeCompleter(t *testing.T) {
expected := errors.New("mocked error")
d := &quicDialerHandshakeCompleter{
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, expected
},
},
}
ctx := context.Background()
conn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", &tls.Config{}, &quic.Config{})
conn, err := d.DialContext(ctx, "8.8.8.8:443", &tls.Config{}, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("unexpected err", err)
}
@@ -369,13 +369,13 @@ func TestQUICDialerHandshakeCompleter(t *testing.T) {
}
d := &quicDialerHandshakeCompleter{
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return expected, nil
},
},
}
conn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", &tls.Config{}, &quic.Config{})
conn, err := d.DialContext(ctx, "8.8.8.8:443", &tls.Config{}, &quic.Config{})
if !errors.Is(err, context.Canceled) {
t.Fatal("unexpected err", err)
}
@@ -398,14 +398,14 @@ func TestQUICDialerHandshakeCompleter(t *testing.T) {
}
d := &quicDialerHandshakeCompleter{
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return expected, nil
},
},
}
conn, err := d.DialContext(
context.Background(), "udp", "8.8.8.8:443", &tls.Config{}, &quic.Config{})
context.Background(), "8.8.8.8:443", &tls.Config{}, &quic.Config{})
if err != nil {
t.Fatal(err)
}
@@ -489,7 +489,7 @@ func TestQUICDialerResolver(t *testing.T) {
Resolver: NewStdlibResolver(log.Log),
Dialer: &quicDialerQUICGo{}}
qconn, err := dialer.DialContext(
context.Background(), "udp", "www.google.com",
context.Background(), "www.google.com",
tlsConfig, &quic.Config{})
if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") {
t.Fatal("not the error we expected")
@@ -508,7 +508,7 @@ func TestQUICDialerResolver(t *testing.T) {
},
}}
qconn, err := dialer.DialContext(
context.Background(), "udp", "dns.google.com:853",
context.Background(), "dns.google.com:853",
tlsConfig, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
@@ -528,7 +528,7 @@ func TestQUICDialerResolver(t *testing.T) {
QUICListener: &quicListenerStdlib{},
}}
qconn, err := dialer.DialContext(
context.Background(), "udp", "8.8.4.4:x",
context.Background(), "8.8.4.4:x",
tlsConf, &quic.Config{})
if err == nil {
t.Fatal("expected an error here")
@@ -548,14 +548,14 @@ func TestQUICDialerResolver(t *testing.T) {
dialer := &quicDialerResolver{
Resolver: NewStdlibResolver(log.Log),
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
gotTLSConfig = tlsConfig
return nil, expected
},
}}
qconn, err := dialer.DialContext(
context.Background(), "udp", "8.8.4.4:443",
context.Background(), "8.8.4.4:443",
tlsConfig, &quic.Config{})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
@@ -576,13 +576,13 @@ func TestQUICDialerResolver(t *testing.T) {
dialer := &quicDialerResolver{
Resolver: NewStdlibResolver(log.Log),
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return expectedQConn, nil
},
}}
qconn, err := dialer.DialContext(
context.Background(), "udp", "8.8.4.4:443",
context.Background(), "8.8.4.4:443",
&tls.Config{}, &quic.Config{})
if err != nil {
t.Fatal(err)
@@ -637,7 +637,7 @@ func TestQUICLoggerDialer(t *testing.T) {
}
d := &quicDialerLogger{
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network string,
MockDialContext: func(ctx context.Context,
address string, tlsConfig *tls.Config,
quicConfig *quic.Config) (quic.EarlyConnection, error) {
return &mocks.QUICEarlyConnection{
@@ -653,7 +653,7 @@ func TestQUICLoggerDialer(t *testing.T) {
ctx := context.Background()
tlsConfig := &tls.Config{}
quicConfig := &quic.Config{}
qconn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig)
qconn, err := d.DialContext(ctx, "8.8.8.8:443", tlsConfig, quicConfig)
if err != nil {
t.Fatal(err)
}
@@ -675,7 +675,7 @@ func TestQUICLoggerDialer(t *testing.T) {
expected := errors.New("mocked error")
d := &quicDialerLogger{
Dialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network string,
MockDialContext: func(ctx context.Context,
address string, tlsConfig *tls.Config,
quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, expected
@@ -686,7 +686,7 @@ func TestQUICLoggerDialer(t *testing.T) {
ctx := context.Background()
tlsConfig := &tls.Config{}
quicConfig := &quic.Config{}
qconn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig)
qconn, err := d.DialContext(ctx, "8.8.8.8:443", tlsConfig, quicConfig)
if !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
}
@@ -705,7 +705,7 @@ func TestNewSingleUseQUICDialer(t *testing.T) {
qd := NewSingleUseQUICDialer(qconn)
defer qd.CloseIdleConnections()
outconn, err := qd.DialContext(
context.Background(), "", "", &tls.Config{}, &quic.Config{})
context.Background(), "", &tls.Config{}, &quic.Config{})
if err != nil {
t.Fatal(err)
}
@@ -714,7 +714,7 @@ func TestNewSingleUseQUICDialer(t *testing.T) {
}
for i := 0; i < 4; i++ {
outconn, err = qd.DialContext(
context.Background(), "", "", &tls.Config{}, &quic.Config{})
context.Background(), "", &tls.Config{}, &quic.Config{})
if !errors.Is(err, ErrNoConnReuse) {
t.Fatal("not the error we expected", err)
}
@@ -904,13 +904,13 @@ func TestQUICDialerErrWrapper(t *testing.T) {
expectedConn := &mocks.QUICEarlyConnection{}
d := &quicDialerErrWrapper{
QUICDialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
MockDialContext: func(ctx context.Context, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return expectedConn, nil
},
},
}
ctx := context.Background()
qconn, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{})
qconn, err := d.DialContext(ctx, "", &tls.Config{}, &quic.Config{})
if err != nil {
t.Fatal(err)
}
@@ -923,13 +923,13 @@ func TestQUICDialerErrWrapper(t *testing.T) {
expectedErr := io.EOF
d := &quicDialerErrWrapper{
QUICDialer: &mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
MockDialContext: func(ctx context.Context, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, expectedErr
},
},
}
ctx := context.Background()
qconn, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{})
qconn, err := d.DialContext(ctx, "", &tls.Config{}, &quic.Config{})
if err == nil || err.Error() != FailureEOFError {
t.Fatal("unexpected err", err)
}
+2 -8
View File
@@ -13,6 +13,7 @@ import (
"net"
"time"
ootls "github.com/ooni/oocrypto/tls"
oohttp "github.com/ooni/oohttp"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/runtimex"
@@ -238,14 +239,7 @@ func (h *tlsHandshakerConfigurable) newConn(conn net.Conn, config *tls.Config) (
if h.NewConn != nil {
return h.NewConn(conn, config)
}
// This used to be the place where we created a TLSConn using
// github.com/ooni/oocrypto's TLS. However, it seems this strategy
// does not correctly pick up the CPU capabilities. So, we have
// now disabled oocrypto until we investigate, to avoid making the
// development branch worse than it could in terms of TLS fingerprint.
//
// TODO(https://github.com/ooni/probe/issues/2122)
return tls.Client(conn, config), nil
return ootls.NewClientConnStdlib(conn, config)
}
// tlsHandshakerLogger is a TLSHandshaker with logging.
+16 -1
View File
@@ -36,8 +36,14 @@ func NewTLSHandshakerUTLS(logger model.DebugLogger, id *utls.ClientHelloID) mode
// utlsConn implements TLSConn and uses a utls UConn as its underlying connection
type utlsConn struct {
// We include the real UConn
*utls.UConn
// This field helps with writing tests
testableHandshake func() error
// Required by NetConn
nc net.Conn
}
// Ensures that a utlsConn implements the TLSConn interface.
@@ -85,7 +91,12 @@ func newConnUTLSWithHelloID(conn net.Conn, config *tls.Config, cid *utls.ClientH
ServerName: config.ServerName,
}
tlsConn := utls.UClient(conn, uConfig, *cid)
return &utlsConn{UConn: tlsConn}, nil
oconn := &utlsConn{
UConn: tlsConn,
testableHandshake: nil,
nc: conn,
}
return oconn, nil
}
// ErrUTLSHandshakePanic indicates that there was panic handshaking
@@ -136,3 +147,7 @@ func (c *utlsConn) ConnectionState() tls.ConnectionState {
TLSUnique: uState.TLSUnique,
}
}
func (c *utlsConn) NetConn() net.Conn {
return c.nc
}
+13
View File
@@ -10,6 +10,7 @@ import (
"time"
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/model/mocks"
utls "gitlab.com/yawning/utls.git"
)
@@ -92,6 +93,18 @@ func TestUTLSConn(t *testing.T) {
wg.Wait()
})
})
t.Run("NetConn", func(t *testing.T) {
factory := newConnUTLS(&utls.HelloChrome_70)
conn := &mocks.Conn{}
tconn, err := factory(conn, &tls.Config{})
if err != nil {
t.Fatal(err)
}
if tconn.NetConn() != conn {
t.Fatal("NetConn is not WAI")
}
})
}
func Test_newConnUTLSWithHelloID(t *testing.T) {
+5 -5
View File
@@ -40,7 +40,7 @@ func (s *Saver) WrapQUICDialer(qd model.QUICDialer) model.QUICDialer {
}
// DialContext implements QUICDialer.DialContext
func (h *QUICDialerSaver) DialContext(ctx context.Context, network string,
func (h *QUICDialerSaver) DialContext(ctx context.Context,
host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
start := time.Now()
// TODO(bassosimone): in the future we probably want to also save
@@ -48,12 +48,12 @@ func (h *QUICDialerSaver) DialContext(ctx context.Context, network string,
h.Saver.Write(&EventQUICHandshakeStart{&EventValue{
Address: host,
NoTLSVerify: tlsCfg.InsecureSkipVerify,
Proto: network,
Proto: "udp",
TLSNextProtos: tlsCfg.NextProtos,
TLSServerName: tlsCfg.ServerName,
Time: start,
}})
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
sess, err := h.QUICDialer.DialContext(ctx, host, tlsCfg, cfg)
stop := time.Now()
if err != nil {
// TODO(bassosimone): here we should save the peer certs
@@ -62,7 +62,7 @@ func (h *QUICDialerSaver) DialContext(ctx context.Context, network string,
Duration: stop.Sub(start),
Err: NewFailureStr(err),
NoTLSVerify: tlsCfg.InsecureSkipVerify,
Proto: network,
Proto: "udp",
TLSNextProtos: tlsCfg.NextProtos,
TLSPeerCerts: [][]byte{},
TLSServerName: tlsCfg.ServerName,
@@ -75,7 +75,7 @@ func (h *QUICDialerSaver) DialContext(ctx context.Context, network string,
Address: host,
Duration: stop.Sub(start),
NoTLSVerify: tlsCfg.InsecureSkipVerify,
Proto: network,
Proto: "udp",
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
TLSNegotiatedProto: state.NegotiatedProtocol,
TLSNextProtos: tlsCfg.NextProtos,
+4 -4
View File
@@ -91,7 +91,7 @@ func TestQUICDialerSaver(t *testing.T) {
},
}
dialer := saver.WrapQUICDialer(&mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return returnedConn, nil
},
@@ -103,7 +103,7 @@ func TestQUICDialerSaver(t *testing.T) {
ServerName: "dns.google",
}
quicConfig := &quic.Config{}
conn, err := dialer.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig)
conn, err := dialer.DialContext(ctx, "8.8.8.8:443", tlsConfig, quicConfig)
if err != nil {
t.Fatal(err)
}
@@ -131,7 +131,7 @@ func TestQUICDialerSaver(t *testing.T) {
expected := errors.New("mocked error")
saver := &Saver{}
dialer := saver.WrapQUICDialer(&mocks.QUICDialer{
MockDialContext: func(ctx context.Context, network, address string,
MockDialContext: func(ctx context.Context, address string,
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) {
return nil, expected
},
@@ -143,7 +143,7 @@ func TestQUICDialerSaver(t *testing.T) {
ServerName: "dns.google",
}
quicConfig := &quic.Config{}
conn, err := dialer.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig)
conn, err := dialer.DialContext(ctx, "8.8.8.8:443", tlsConfig, quicConfig)
if !errors.Is(err, expected) {
t.Fatal("unexpected err", err)
}
@@ -93,7 +93,7 @@ func dialQUIC(ctx context.Context, address string,
config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) {
ql := netxlite.NewQUICListener()
d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log)
qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{})
qconn, err := d.DialContext(ctx, address, config, &quic.Config{})
if err != nil {
return nil, tls.ConnectionState{}, err
}
+1 -1
View File
@@ -94,7 +94,7 @@ func dialQUIC(ctx context.Context, address string,
config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) {
ql := netxlite.NewQUICListener()
d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log)
qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{})
qconn, err := d.DialContext(ctx, address, config, &quic.Config{})
if err != nil {
return nil, tls.ConnectionState{}, err
}
@@ -53,7 +53,7 @@ creating a system resolver, except that we also need to specify the
UDP endpoint address at which the server is listening.
```Go
reso := netxlite.NewParallelResolverUDP(log.Log, dialer, *serverAddr)
reso := netxlite.NewParallelUDPResolver(log.Log, dialer, *serverAddr)
```
The API we invoke is the same as in the previous chapter, though,
@@ -106,7 +106,7 @@ func dialQUIC(ctx context.Context, address string,
config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) {
ql := netxlite.NewQUICListener()
d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log)
qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{})
qconn, err := d.DialContext(ctx, address, config, &quic.Config{})
if err != nil {
return nil, tls.ConnectionState{}, err
}
+1 -1
View File
@@ -107,7 +107,7 @@ func dialQUIC(ctx context.Context, address string,
config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) {
ql := netxlite.NewQUICListener()
d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log)
qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{})
qconn, err := d.DialContext(ctx, address, config, &quic.Config{})
if err != nil {
return nil, tls.ConnectionState{}, err
}