This commit forward ports dedd84fa7ecb09f718f6b1a9c83999cb37b34dfa. Original commit message: - - - This diff changes code the release/3.11 branch to ensure we're not using dns.google and www.google.com over HTTP3. As documented in https://github.com/ooni/probe/issues/1873, since this morning (approx) these services do not support HTTP3 anymore. (I didn't bother with checking whether this issue affects _other_ Google services; I just limited my analysis to the services that we were using as part of testing.) This patch WILL require forward porting to the master branch.
This commit is contained in:
parent
3dad324f09
commit
0a322ebab0
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -84,12 +85,11 @@ func TestGetFailure(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetH3Success(t *testing.T) {
|
func TestGetH3Success(t *testing.T) {
|
||||||
u, err := url.Parse("https://www.google.com")
|
u := &url.URL{Scheme: "https", Host: quictesting.Domain, Path: "/"}
|
||||||
runtimex.PanicOnError(err, "url.Parse failed for clearly good URL")
|
|
||||||
h3u := &h3URL{URL: u, proto: "h3"}
|
h3u := &h3URL{URL: u, proto: "h3"}
|
||||||
resp, err := explorer.getH3(h3u, nil)
|
resp, err := explorer.getH3(h3u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error")
|
t.Fatal("unexpected error", err)
|
||||||
}
|
}
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
t.Fatal("unexpected nil response")
|
t.Fatal("unexpected nil response")
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -297,8 +298,7 @@ func TestGenerateHTTPSTLSFailure(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateH3(t *testing.T) {
|
func TestGenerateH3(t *testing.T) {
|
||||||
u, err := url.Parse("https://www.google.com")
|
u := &url.URL{Scheme: "https", Host: quictesting.Domain, Path: "/"}
|
||||||
runtimex.PanicOnError(err, "url.Parse failed")
|
|
||||||
rt := &RoundTrip{
|
rt := &RoundTrip{
|
||||||
Proto: "h3",
|
Proto: "h3",
|
||||||
Request: &http.Request{
|
Request: &http.Request{
|
||||||
|
@ -309,10 +309,7 @@ func TestGenerateH3(t *testing.T) {
|
||||||
},
|
},
|
||||||
SortIndex: 0,
|
SortIndex: 0,
|
||||||
}
|
}
|
||||||
endpointMeasurement := generator.GenerateH3Endpoint(context.Background(), rt, "173.194.76.103:443")
|
endpointMeasurement := generator.GenerateH3Endpoint(context.Background(), rt, quictesting.Endpoint("443"))
|
||||||
if err != nil {
|
|
||||||
t.Fatal("unexpected err")
|
|
||||||
}
|
|
||||||
if endpointMeasurement == nil {
|
if endpointMeasurement == nil {
|
||||||
t.Fatal("unexpected nil urlMeasurement")
|
t.Fatal("unexpected nil urlMeasurement")
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ var allmakers = []*resolvermaker{{
|
||||||
url: "http3://cloudflare-dns.com/dns-query",
|
url: "http3://cloudflare-dns.com/dns-query",
|
||||||
}, {
|
}, {
|
||||||
url: "https://dns.google/dns-query",
|
url: "https://dns.google/dns-query",
|
||||||
}, {
|
|
||||||
url: "http3://dns.google/dns-query",
|
|
||||||
}, {
|
}, {
|
||||||
url: "https://dns.quad9.net/dns-query",
|
url: "https://dns.quad9.net/dns-query",
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -8,9 +8,10 @@ import (
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestErrorWrapperQUICDialerInvalidCertificate(t *testing.T) {
|
func TestErrorWrapperQUICDialerFailure(t *testing.T) {
|
||||||
nextprotos := []string{"h3"}
|
nextprotos := []string{"h3"}
|
||||||
servername := "example.com"
|
servername := "example.com"
|
||||||
tlsConf := &tls.Config{
|
tlsConf := &tls.Config{
|
||||||
|
@ -21,17 +22,16 @@ func TestErrorWrapperQUICDialerInvalidCertificate(t *testing.T) {
|
||||||
dlr := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
dlr := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
}}
|
}}
|
||||||
// use Google IP
|
|
||||||
sess, err := dlr.DialContext(context.Background(), "udp",
|
sess, err := dlr.DialContext(context.Background(), "udp",
|
||||||
"216.58.212.164:443", tlsConf, &quic.Config{})
|
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected an error here")
|
t.Fatal("expected an error here")
|
||||||
}
|
}
|
||||||
if sess != nil {
|
if sess != nil {
|
||||||
t.Fatal("expected nil sess here")
|
t.Fatal("expected nil sess here")
|
||||||
}
|
}
|
||||||
if err.Error() != netxlite.FailureSSLInvalidCertificate {
|
if err.Error() != netxlite.FailureSSLFailedHandshake {
|
||||||
t.Fatal("unexpected failure")
|
t.Fatal("unexpected failure", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +39,12 @@ func TestErrorWrapperQUICDialerSuccess(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
tlsConf := &tls.Config{
|
tlsConf := &tls.Config{
|
||||||
NextProtos: []string{"h3"},
|
NextProtos: []string{"h3"},
|
||||||
ServerName: "www.google.com",
|
ServerName: quictesting.Domain,
|
||||||
}
|
}
|
||||||
d := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
d := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
}}
|
}}
|
||||||
sess, err := d.DialContext(ctx, "udp", "216.58.212.164:443", tlsConf, &quic.Config{})
|
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockDialer struct {
|
type MockDialer struct {
|
||||||
|
@ -30,7 +31,7 @@ func (d MockDialer) DialContext(ctx context.Context, network, host string,
|
||||||
|
|
||||||
func TestHandshakeSaverSuccess(t *testing.T) {
|
func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
nextprotos := []string{"h3"}
|
nextprotos := []string{"h3"}
|
||||||
servername := "www.google.com"
|
servername := quictesting.Domain
|
||||||
tlsConf := &tls.Config{
|
tlsConf := &tls.Config{
|
||||||
NextProtos: nextprotos,
|
NextProtos: nextprotos,
|
||||||
ServerName: servername,
|
ServerName: servername,
|
||||||
|
@ -43,7 +44,7 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
sess, err := dlr.DialContext(context.Background(), "udp",
|
sess, err := dlr.DialContext(context.Background(), "udp",
|
||||||
"216.58.212.164:443", tlsConf, &quic.Config{})
|
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error", err)
|
t.Fatal("unexpected error", err)
|
||||||
}
|
}
|
||||||
|
@ -57,7 +58,7 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
if ev[0].Name != "quic_handshake_start" {
|
if ev[0].Name != "quic_handshake_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[0].TLSServerName != "www.google.com" {
|
if ev[0].TLSServerName != quictesting.Domain {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[0].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[0].TLSNextProtos, nextprotos) {
|
||||||
|
@ -78,7 +79,7 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
if !reflect.DeepEqual(ev[1].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[1].TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[1].TLSServerName != "www.google.com" {
|
if ev[1].TLSServerName != quictesting.Domain {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if ev[1].Time.Before(ev[0].Time) {
|
if ev[1].Time.Before(ev[0].Time) {
|
||||||
|
@ -101,7 +102,7 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
sess, err := dlr.DialContext(context.Background(), "udp",
|
sess, err := dlr.DialContext(context.Background(), "udp",
|
||||||
"216.58.212.164:443", tlsConf, &quic.Config{})
|
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected an error here")
|
t.Fatal("expected an error here")
|
||||||
}
|
}
|
||||||
|
@ -115,8 +116,7 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||||
if ev.NoTLSVerify == true {
|
if ev.NoTLSVerify == true {
|
||||||
t.Fatal("expected NoTLSVerify to be false")
|
t.Fatal("expected NoTLSVerify to be false")
|
||||||
}
|
}
|
||||||
if !strings.Contains(ev.Err.Error(),
|
if !strings.HasSuffix(ev.Err.Error(), "tls: handshake failure") {
|
||||||
"certificate is valid for www.google.com, not "+servername) {
|
|
||||||
t.Fatal("unexpected error", ev.Err)
|
t.Fatal("unexpected error", ev.Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quicx"
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quicx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||||
// This is the most common use case for collecting reads, writes
|
// This is the most common use case for collecting reads, writes
|
||||||
tlsConf := &tls.Config{
|
tlsConf := &tls.Config{
|
||||||
NextProtos: []string{"h3"},
|
NextProtos: []string{"h3"},
|
||||||
ServerName: "www.google.com",
|
ServerName: quictesting.Domain,
|
||||||
}
|
}
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
systemdialer := &netxlite.QUICDialerQUICGo{
|
systemdialer := &netxlite.QUICDialerQUICGo{
|
||||||
|
@ -52,7 +53,7 @@ func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := systemdialer.DialContext(context.Background(), "udp",
|
_, err := systemdialer.DialContext(context.Background(), "udp",
|
||||||
"216.58.212.164:443", tlsConf, &quic.Config{})
|
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ import (
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite/filtering"
|
"github.com/ooni/probe-cli/v3/internal/netxlite/filtering"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
utls "gitlab.com/yawning/utls.git"
|
utls "gitlab.com/yawning/utls.git"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -435,11 +437,11 @@ func TestMeasureWithQUICDialer(t *testing.T) {
|
||||||
defer d.CloseIdleConnections()
|
defer d.CloseIdleConnections()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
ServerName: "dns.google",
|
ServerName: quictesting.Domain,
|
||||||
NextProtos: []string{"h3"},
|
NextProtos: []string{"h3"},
|
||||||
RootCAs: netxlite.NewDefaultCertPool(),
|
RootCAs: netxlite.NewDefaultCertPool(),
|
||||||
}
|
}
|
||||||
sess, err := d.DialContext(ctx, "udp", "8.8.4.4:443", config, &quic.Config{})
|
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("443"), config, &quic.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -455,12 +457,12 @@ func TestMeasureWithQUICDialer(t *testing.T) {
|
||||||
defer d.CloseIdleConnections()
|
defer d.CloseIdleConnections()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
ServerName: "dns.google",
|
ServerName: quictesting.Domain,
|
||||||
NextProtos: []string{"h3"},
|
NextProtos: []string{"h3"},
|
||||||
RootCAs: netxlite.NewDefaultCertPool(),
|
RootCAs: netxlite.NewDefaultCertPool(),
|
||||||
}
|
}
|
||||||
// Here we assume 8.8.4.4:1 is filtered
|
// Here we assume <target-address>:1 is filtered
|
||||||
sess, err := d.DialContext(ctx, "udp", "8.8.4.4:1", config, &quic.Config{})
|
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("1"), config, &quic.Config{})
|
||||||
if err == nil || err.Error() != netxlite.FailureGenericTimeoutError {
|
if err == nil || err.Error() != netxlite.FailureGenericTimeoutError {
|
||||||
t.Fatal("not the error we expected", err)
|
t.Fatal("not the error we expected", err)
|
||||||
}
|
}
|
||||||
|
@ -502,7 +504,8 @@ func TestHTTP3Transport(t *testing.T) {
|
||||||
)
|
)
|
||||||
txp := netxlite.NewHTTP3Transport(log.Log, d, &tls.Config{})
|
txp := netxlite.NewHTTP3Transport(log.Log, d, &tls.Config{})
|
||||||
client := &http.Client{Transport: txp}
|
client := &http.Client{Transport: txp}
|
||||||
resp, err := client.Get("https://www.google.com/robots.txt")
|
URL := (&url.URL{Scheme: "https", Host: quictesting.Domain, Path: "/"}).String()
|
||||||
|
resp, err := client.Get(URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
38
internal/netxlite/quictesting/quictesting.go
Normal file
38
internal/netxlite/quictesting/quictesting.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Package quictesting contains code useful to test QUIC.
|
||||||
|
package quictesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Domain is the the domain we should be testing using QUIC.
|
||||||
|
const Domain = "www.cloudflare.com"
|
||||||
|
|
||||||
|
// Address is the address we should be testing using QUIC.
|
||||||
|
var Address string
|
||||||
|
|
||||||
|
// Endpoint returns the endpoint to test using QUIC by combining
|
||||||
|
// the Address variable with the given port.
|
||||||
|
func Endpoint(port string) string {
|
||||||
|
return net.JoinHostPort(Address, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
const timeout = 10 * time.Second
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
reso := &net.Resolver{}
|
||||||
|
addrs, err := reso.LookupHost(ctx, Domain)
|
||||||
|
runtimex.PanicOnError(err, "reso.LookupHost failed")
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if !strings.Contains(addr, ":") {
|
||||||
|
Address = addr
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
internal/netxlite/quictesting/quictesting_test.go
Normal file
20
internal/netxlite/quictesting/quictesting_test.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package quictesting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWorksAsIntended(t *testing.T) {
|
||||||
|
epnt := Endpoint("443")
|
||||||
|
addr, port, err := net.SplitHostPort(epnt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if addr != Address {
|
||||||
|
t.Fatal("invalid addr")
|
||||||
|
}
|
||||||
|
if port != "443" {
|
||||||
|
t.Fatal("invalid port")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user