fix({simplequic,tls}ping): default SNI to URL's hostname (#753)

See https://github.com/ooni/probe/issues/2111
This commit is contained in:
Simone Basso 2022-05-24 16:29:13 +02:00 committed by GitHub
parent 83cf447edd
commit b68b8e1e8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 8 deletions

View File

@ -8,6 +8,7 @@ import (
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@ -58,6 +59,17 @@ func (c *Config) repetitions() int64 {
return 10 return 10
} }
func (c *Config) sni(address string) string {
if c.SNI != "" {
return c.SNI
}
addr, _, err := net.SplitHostPort(address)
if err != nil {
return ""
}
return addr
}
// TestKeys contains the experiment results. // TestKeys contains the experiment results.
type TestKeys struct { type TestKeys struct {
Pings []*SinglePing `json:"pings"` Pings []*SinglePing `json:"pings"`
@ -118,9 +130,6 @@ func (m *Measurer) Run(
if parsed.Port() == "" { if parsed.Port() == "" {
return errMissingPort return errMissingPort
} }
if m.config.SNI == "" {
sess.Logger().Warn("no -O SNI=<SNI> specified from command line")
}
tk := new(TestKeys) tk := new(TestKeys)
measurement.TestKeys = tk measurement.TestKeys = tk
out := make(chan *measurex.EndpointMeasurement) out := make(chan *measurex.EndpointMeasurement)
@ -162,7 +171,7 @@ func (m *Measurer) quicHandshake(ctx context.Context, mxmx *measurex.Measurer,
return mxmx.QUICHandshake(ctx, address, &tls.Config{ return mxmx.QUICHandshake(ctx, address, &tls.Config{
NextProtos: strings.Split(m.config.alpn(), " "), NextProtos: strings.Split(m.config.alpn(), " "),
RootCAs: netxlite.NewDefaultCertPool(), RootCAs: netxlite.NewDefaultCertPool(),
ServerName: m.config.SNI, ServerName: m.config.sni(address),
}) })
} }

View File

@ -186,3 +186,51 @@ func generateTLSConfig() *tls.Config {
NextProtos: []string{"quic-echo-example"}, NextProtos: []string{"quic-echo-example"},
} }
} }
func TestConfig_sni(t *testing.T) {
type fields struct {
SNI string
}
type args struct {
address string
}
tests := []struct {
name string
fields fields
args args
want string
}{{
name: "with config.SNI being set",
fields: fields{
SNI: "x.org",
},
args: args{
address: "google.com:443",
},
want: "x.org",
}, {
name: "with invalid endpoint",
fields: fields{},
args: args{
address: "google.com",
},
want: "",
}, {
name: "with valid endpoint",
fields: fields{},
args: args{
address: "google.com:443",
},
want: "google.com",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Config{
SNI: tt.fields.SNI,
}
if got := c.sni(tt.args.address); got != tt.want {
t.Fatalf("Config.sni() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -8,6 +8,7 @@ import (
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@ -58,6 +59,17 @@ func (c *Config) repetitions() int64 {
return 10 return 10
} }
func (c *Config) sni(address string) string {
if c.SNI != "" {
return c.SNI
}
addr, _, err := net.SplitHostPort(address)
if err != nil {
return ""
}
return addr
}
// TestKeys contains the experiment results. // TestKeys contains the experiment results.
type TestKeys struct { type TestKeys struct {
Pings []*SinglePing `json:"pings"` Pings []*SinglePing `json:"pings"`
@ -119,9 +131,6 @@ func (m *Measurer) Run(
if parsed.Port() == "" { if parsed.Port() == "" {
return errMissingPort return errMissingPort
} }
if m.config.SNI == "" {
sess.Logger().Warn("no -O SNI=<SNI> specified from command line")
}
tk := new(TestKeys) tk := new(TestKeys)
measurement.TestKeys = tk measurement.TestKeys = tk
out := make(chan *measurex.EndpointMeasurement) out := make(chan *measurex.EndpointMeasurement)
@ -165,7 +174,7 @@ func (m *Measurer) tlsConnectAndHandshake(ctx context.Context, mxmx *measurex.Me
return mxmx.TLSConnectAndHandshake(ctx, address, &tls.Config{ return mxmx.TLSConnectAndHandshake(ctx, address, &tls.Config{
NextProtos: strings.Split(m.config.alpn(), " "), NextProtos: strings.Split(m.config.alpn(), " "),
RootCAs: netxlite.NewDefaultCertPool(), RootCAs: netxlite.NewDefaultCertPool(),
ServerName: m.config.SNI, ServerName: m.config.sni(address),
}) })
} }

View File

@ -119,3 +119,51 @@ func TestMeasurer_run(t *testing.T) {
} }
}) })
} }
func TestConfig_sni(t *testing.T) {
type fields struct {
SNI string
}
type args struct {
address string
}
tests := []struct {
name string
fields fields
args args
want string
}{{
name: "with config.SNI being set",
fields: fields{
SNI: "x.org",
},
args: args{
address: "google.com:443",
},
want: "x.org",
}, {
name: "with invalid endpoint",
fields: fields{},
args: args{
address: "google.com",
},
want: "",
}, {
name: "with valid endpoint",
fields: fields{},
args: args{
address: "google.com:443",
},
want: "google.com",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Config{
SNI: tt.fields.SNI,
}
if got := c.sni(tt.args.address); got != tt.want {
t.Fatalf("Config.sni() = %v, want %v", got, tt.want)
}
})
}
}