Files
x/util/utls_test.go
T
2026-06-28 12:08:30 +08:00

110 lines
3.5 KiB
Go

package util
import (
stdtls "crypto/tls"
"net"
"testing"
tls "github.com/refraction-networking/utls"
)
func TestNewUTLSConfigPreservesClientSettings(t *testing.T) {
called := false
cfg := NewUTLSConfig(&stdtls.Config{
ServerName: "example.com",
InsecureSkipVerify: true,
NextProtos: []string{"h2", "http/1.1"},
MinVersion: stdtls.VersionTLS12,
MaxVersion: stdtls.VersionTLS13,
CipherSuites: []uint16{stdtls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
CurvePreferences: []stdtls.CurveID{stdtls.X25519, stdtls.CurveP256},
DynamicRecordSizingDisabled: true,
Renegotiation: stdtls.RenegotiateOnceAsClient,
VerifyConnection: func(state stdtls.ConnectionState) error {
called = true
if state.ServerName != "example.com" {
t.Fatalf("ServerName = %q, want example.com", state.ServerName)
}
return nil
},
})
if cfg.ServerName != "example.com" {
t.Fatalf("ServerName = %q, want example.com", cfg.ServerName)
}
if !cfg.InsecureSkipVerify {
t.Fatal("InsecureSkipVerify was not preserved")
}
if len(cfg.NextProtos) != 2 || cfg.NextProtos[0] != "h2" || cfg.NextProtos[1] != "http/1.1" {
t.Fatalf("NextProtos = %v", cfg.NextProtos)
}
if cfg.MinVersion != tls.VersionTLS12 || cfg.MaxVersion != tls.VersionTLS13 {
t.Fatalf("version range = %x-%x", cfg.MinVersion, cfg.MaxVersion)
}
if len(cfg.CipherSuites) != 1 || cfg.CipherSuites[0] != tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 {
t.Fatalf("CipherSuites = %v", cfg.CipherSuites)
}
if len(cfg.CurvePreferences) != 2 || cfg.CurvePreferences[0] != tls.X25519 || cfg.CurvePreferences[1] != tls.CurveP256 {
t.Fatalf("CurvePreferences = %v", cfg.CurvePreferences)
}
if !cfg.DynamicRecordSizingDisabled {
t.Fatal("DynamicRecordSizingDisabled was not preserved")
}
if cfg.Renegotiation != tls.RenegotiateOnceAsClient {
t.Fatalf("Renegotiation = %v", cfg.Renegotiation)
}
if cfg.VerifyConnection == nil {
t.Fatal("VerifyConnection was not preserved")
}
if err := cfg.VerifyConnection(tls.ConnectionState{ServerName: "example.com"}); err != nil {
t.Fatal(err)
}
if !called {
t.Fatal("VerifyConnection wrapper was not called")
}
}
func TestNewUTLSChromeClientBuildsChromeHello(t *testing.T) {
c1, c2 := net.Pipe()
defer c1.Close()
defer c2.Close()
client := NewUTLSChromeClient(c1, &stdtls.Config{ServerName: "example.com"})
if client.ClientHelloID != tls.HelloChrome_Auto {
t.Fatalf("ClientHelloID = %+v, want %+v", client.ClientHelloID, tls.HelloChrome_Auto)
}
if err := client.BuildHandshakeStateWithoutSession(); err != nil {
t.Fatal(err)
}
if len(client.Extensions) == 0 {
t.Fatal("Chrome ClientHello has no extensions")
}
}
func TestNewUTLSWebSocketClientAppliesCustomSpec(t *testing.T) {
c1, c2 := net.Pipe()
defer c1.Close()
defer c2.Close()
client, err := NewUTLSWebSocketClient(c1, &stdtls.Config{
ServerName: "example.com",
NextProtos: []string{"h2"},
MinVersion: stdtls.VersionTLS13,
}, false)
if err != nil {
t.Fatal(err)
}
if client.ClientHelloID != tls.HelloCustom {
t.Fatalf("ClientHelloID = %+v, want %+v", client.ClientHelloID, tls.HelloCustom)
}
if len(client.Extensions) == 0 {
t.Fatal("custom WebSocket ClientHello preset has no extensions")
}
if err := client.BuildHandshakeStateWithoutSession(); err != nil {
t.Fatal(err)
}
if len(client.HandshakeState.Hello.AlpnProtocols) != 1 || client.HandshakeState.Hello.AlpnProtocols[0] != "http/1.1" {
t.Fatalf("ALPN = %v, want [http/1.1]", client.HandshakeState.Hello.AlpnProtocols)
}
}