diff --git a/common/session/context.go b/common/session/context.go index a2c97d37..f2c8de7f 100644 --- a/common/session/context.go +++ b/common/session/context.go @@ -24,6 +24,7 @@ const ( allowedNetworkKey ctx.SessionKey = 9 handlerSessionKey ctx.SessionKey = 10 mitmAlpn11Key ctx.SessionKey = 11 + mitmServerNameKey ctx.SessionKey = 12 ) func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context { @@ -174,3 +175,14 @@ func MitmAlpn11FromContext(ctx context.Context) bool { } return false } + +func ContextWithMitmServerName(ctx context.Context, serverName string) context.Context { + return context.WithValue(ctx, mitmServerNameKey, serverName) +} + +func MitmServerNameFromContext(ctx context.Context) string { + if val, ok := ctx.Value(mitmServerNameKey).(string); ok { + return val + } + return "" +} diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 16b659c4..962b39ee 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -411,6 +411,7 @@ type TLSConfig struct { CurvePreferences *StringList `json:"curvePreferences"` MasterKeyLog string `json:"masterKeyLog"` ServerNameToVerify string `json:"serverNameToVerify"` + VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"` } // Build implements Buildable. @@ -469,10 +470,11 @@ func (c *TLSConfig) Build() (proto.Message, error) { } config.MasterKeyLog = c.MasterKeyLog - config.ServerNameToVerify = c.ServerNameToVerify - if config.ServerNameToVerify != "" && config.Fingerprint == "unsafe" { - return nil, errors.New(`serverNameToVerify only works with uTLS for now`) + + if c.ServerNameToVerify != "" { + return nil, errors.PrintRemovedFeatureError("serverNameToVerify", "verifyPeerCertInNames") } + config.VerifyPeerCertInNames = c.VerifyPeerCertInNames return config, nil } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 6bd3e28f..c16135f5 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -64,10 +64,6 @@ func (d *DokodemoDoor) policy() policy.Session { return p } -type hasHandshakeAddressContext interface { - HandshakeAddressContext(ctx context.Context) net.Address -} - // Process implements proxy.Inbound. func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error { errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr()) @@ -87,14 +83,14 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st destinationOverridden = true } } - if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden { - addr := handshake.HandshakeAddressContext(ctx) - if addr != nil { - dest.Address = addr - if conn.(*tls.Conn).ConnectionState().NegotiatedProtocol == "http/1.1" { - ctx = session.ContextWithMitmAlpn11(ctx, true) - } + if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden { + if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" { + dest.Address = net.DomainAddress(serverName) destinationOverridden = true + ctx = session.ContextWithMitmServerName(ctx, serverName) + } + if tlsConn.NegotiatedProtocol() == "http/1.1" { + ctx = session.ContextWithMitmAlpn11(ctx, true) } } } diff --git a/transport/internet/tcp/dialer.go b/transport/internet/tcp/dialer.go index abc2688e..8d9bbf78 100644 --- a/transport/internet/tcp/dialer.go +++ b/transport/internet/tcp/dialer.go @@ -14,6 +14,10 @@ import ( "github.com/xtls/xray-core/transport/internet/tls" ) +func IsFromMitm(str string) bool { + return strings.ToLower(str) == "frommitm" +} + // Dial dials a new TCP connection to the given destination. func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) { errors.LogInfo(ctx, "dialing TCP to ", dest) @@ -23,11 +27,28 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me } if config := tls.ConfigFromStreamSettings(streamSettings); config != nil { + mitmServerName := session.MitmServerNameFromContext(ctx) + mitmAlpn11 := session.MitmAlpn11FromContext(ctx) tlsConfig := config.GetTLSConfig(tls.WithDestination(dest)) + if IsFromMitm(tlsConfig.ServerName) { + tlsConfig.ServerName = mitmServerName + } + if r, ok := tlsConfig.Rand.(*tls.RandCarrier); ok && len(r.VerifyPeerCertInNames) > 0 && IsFromMitm(r.VerifyPeerCertInNames[0]) { + r.VerifyPeerCertInNames = r.VerifyPeerCertInNames[1:] + after := mitmServerName + for { + if len(after) > 0 { + r.VerifyPeerCertInNames = append(r.VerifyPeerCertInNames, after) + } + _, after, _ = strings.Cut(after, ".") + if !strings.Contains(after, ".") { + break + } + } + } if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil { conn = tls.UClient(conn, tlsConfig, fingerprint) - if len(tlsConfig.NextProtos) == 1 && (tlsConfig.NextProtos[0] == "http/1.1" || - (strings.ToLower(tlsConfig.NextProtos[0]) == "frommitm" && session.MitmAlpn11FromContext(ctx))) { + if len(tlsConfig.NextProtos) == 1 && (tlsConfig.NextProtos[0] == "http/1.1" || (IsFromMitm(tlsConfig.NextProtos[0]) && mitmAlpn11)) { if err := conn.(*tls.UConn).WebsocketHandshakeContext(ctx); err != nil { return nil, err } @@ -37,14 +58,17 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me } } } else { - if len(tlsConfig.NextProtos) == 1 && strings.ToLower(tlsConfig.NextProtos[0]) == "frommitm" { - if session.MitmAlpn11FromContext(ctx) { - tlsConfig.NextProtos = []string{"http/1.1"} // new slice + if len(tlsConfig.NextProtos) == 1 && IsFromMitm(tlsConfig.NextProtos[0]) { + if mitmAlpn11 { + tlsConfig.NextProtos[0] = "http/1.1" } else { tlsConfig.NextProtos = nil } } conn = tls.Client(conn, tlsConfig) + if err := conn.(*tls.Conn).HandshakeContext(ctx); err != nil { + return nil, err + } } } else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil { if conn, err = reality.UClient(conn, config, ctx, dest); err != nil { diff --git a/transport/internet/tls/config.go b/transport/internet/tls/config.go index 8278cafb..8788b579 100644 --- a/transport/internet/tls/config.go +++ b/transport/internet/tls/config.go @@ -9,6 +9,7 @@ import ( "crypto/x509" "encoding/base64" "os" + "slices" "strings" "sync" "time" @@ -277,10 +278,35 @@ func (c *Config) parseServerName() string { return c.ServerName } -func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { - if c.PinnedPeerCertificateChainSha256 != nil { +func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + if r.VerifyPeerCertInNames != nil { + if len(r.VerifyPeerCertInNames) > 0 { + certs := make([]*x509.Certificate, len(rawCerts)) + for i, asn1Data := range rawCerts { + certs[i], _ = x509.ParseCertificate(asn1Data) + } + opts := x509.VerifyOptions{ + Roots: r.RootCAs, + CurrentTime: time.Now(), + Intermediates: x509.NewCertPool(), + } + for _, cert := range certs[1:] { + opts.Intermediates.AddCert(cert) + } + for _, opts.DNSName = range r.VerifyPeerCertInNames { + if _, err := certs[0].Verify(opts); err == nil { + return nil + } + } + } + if r.PinnedPeerCertificateChainSha256 == nil { + errors.New("peer cert is invalid.") + } + } + + if r.PinnedPeerCertificateChainSha256 != nil { hashValue := GenerateCertChainHash(rawCerts) - for _, v := range c.PinnedPeerCertificateChainSha256 { + for _, v := range r.PinnedPeerCertificateChainSha256 { if hmac.Equal(hashValue, v) { return nil } @@ -288,11 +314,11 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert return errors.New("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue)) } - if c.PinnedPeerCertificatePublicKeySha256 != nil { + if r.PinnedPeerCertificatePublicKeySha256 != nil { for _, v := range verifiedChains { for _, cert := range v { publicHash := GenerateCertPublicKeyHash(cert) - for _, c := range c.PinnedPeerCertificatePublicKeySha256 { + for _, c := range r.PinnedPeerCertificatePublicKeySha256 { if hmac.Equal(publicHash, c) { return nil } @@ -305,7 +331,10 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert } type RandCarrier struct { - ServerNameToVerify string + RootCAs *x509.CertPool + VerifyPeerCertInNames []string + PinnedPeerCertificateChainSha256 [][]byte + PinnedPeerCertificatePublicKeySha256 [][]byte } func (r *RandCarrier) Read(p []byte) (n int, err error) { @@ -329,16 +358,25 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config { } } + randCarrier := &RandCarrier{ + RootCAs: root, + VerifyPeerCertInNames: slices.Clone(c.VerifyPeerCertInNames), + PinnedPeerCertificateChainSha256: c.PinnedPeerCertificateChainSha256, + PinnedPeerCertificatePublicKeySha256: c.PinnedPeerCertificatePublicKeySha256, + } config := &tls.Config{ - Rand: &RandCarrier{ - ServerNameToVerify: c.ServerNameToVerify, - }, + Rand: randCarrier, ClientSessionCache: globalSessionCache, RootCAs: root, InsecureSkipVerify: c.AllowInsecure, - NextProtos: c.NextProtocol, + NextProtos: slices.Clone(c.NextProtocol), SessionTicketsDisabled: !c.EnableSessionResumption, - VerifyPeerCertificate: c.verifyPeerCert, + VerifyPeerCertificate: randCarrier.verifyPeerCert, + } + if len(c.VerifyPeerCertInNames) > 0 { + config.InsecureSkipVerify = true + } else { + randCarrier.VerifyPeerCertInNames = nil } for _, opt := range opts { diff --git a/transport/internet/tls/config.pb.go b/transport/internet/tls/config.pb.go index e59fe502..43053c78 100644 --- a/transport/internet/tls/config.pb.go +++ b/transport/internet/tls/config.pb.go @@ -202,20 +202,21 @@ type Config struct { // TLS Client Hello fingerprint (uTLS). Fingerprint string `protobuf:"bytes,11,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` RejectUnknownSni bool `protobuf:"varint,12,opt,name=reject_unknown_sni,json=rejectUnknownSni,proto3" json:"reject_unknown_sni,omitempty"` - // @Document A pinned certificate chain sha256 hash. - // @Document If the server's hash does not match this value, the connection will be aborted. - // @Document This value replace allow_insecure. + // @Document Some certificate chain sha256 hashes. + // @Document After normal validation or allow_insecure, if the server's cert chain hash does not match any of these values, the connection will be aborted. // @Critical PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"` - // @Document A pinned certificate public key sha256 hash. - // @Document If the server's public key hash does not match this value, the connection will be aborted. - // @Document This value replace allow_insecure. + // @Document Some certificate public key sha256 hashes. + // @Document After normal validation (required), if the verified cert's public key hash does not match any of these values, the connection will be aborted. // @Critical PinnedPeerCertificatePublicKeySha256 [][]byte `protobuf:"bytes,14,rep,name=pinned_peer_certificate_public_key_sha256,json=pinnedPeerCertificatePublicKeySha256,proto3" json:"pinned_peer_certificate_public_key_sha256,omitempty"` MasterKeyLog string `protobuf:"bytes,15,opt,name=master_key_log,json=masterKeyLog,proto3" json:"master_key_log,omitempty"` // Lists of string as CurvePreferences values. - CurvePreferences []string `protobuf:"bytes,16,rep,name=curve_preferences,json=curvePreferences,proto3" json:"curve_preferences,omitempty"` - ServerNameToVerify string `protobuf:"bytes,17,opt,name=server_name_to_verify,json=serverNameToVerify,proto3" json:"server_name_to_verify,omitempty"` + CurvePreferences []string `protobuf:"bytes,16,rep,name=curve_preferences,json=curvePreferences,proto3" json:"curve_preferences,omitempty"` + // @Document Replaces server_name to verify the peer cert. + // @Document After allow_insecure (automatically), if the server's cert can't be verified by any of these names, pinned_peer_certificate_chain_sha256 will be tried. + // @Critical + VerifyPeerCertInNames []string `protobuf:"bytes,17,rep,name=verify_peer_cert_in_names,json=verifyPeerCertInNames,proto3" json:"verify_peer_cert_in_names,omitempty"` } func (x *Config) Reset() { @@ -353,11 +354,11 @@ func (x *Config) GetCurvePreferences() []string { return nil } -func (x *Config) GetServerNameToVerify() string { +func (x *Config) GetVerifyPeerCertInNames() []string { if x != nil { - return x.ServerNameToVerify + return x.VerifyPeerCertInNames } - return "" + return nil } var File_transport_internet_tls_config_proto protoreflect.FileDescriptor @@ -391,7 +392,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{ 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, - 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0x93, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0x9a, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65, @@ -437,18 +438,19 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{ 0x52, 0x0c, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x72, 0x76, 0x65, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x42, 0x73, - 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, - 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, - 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x19, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, + 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x49, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, + 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, + 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/transport/internet/tls/config.proto b/transport/internet/tls/config.proto index bb2564a3..c52d0be1 100644 --- a/transport/internet/tls/config.proto +++ b/transport/internet/tls/config.proto @@ -69,16 +69,14 @@ message Config { bool reject_unknown_sni = 12; - /* @Document A pinned certificate chain sha256 hash. - @Document If the server's hash does not match this value, the connection will be aborted. - @Document This value replace allow_insecure. + /* @Document Some certificate chain sha256 hashes. + @Document After normal validation or allow_insecure, if the server's cert chain hash does not match any of these values, the connection will be aborted. @Critical */ repeated bytes pinned_peer_certificate_chain_sha256 = 13; - /* @Document A pinned certificate public key sha256 hash. - @Document If the server's public key hash does not match this value, the connection will be aborted. - @Document This value replace allow_insecure. + /* @Document Some certificate public key sha256 hashes. + @Document After normal validation (required), if the verified cert's public key hash does not match any of these values, the connection will be aborted. @Critical */ repeated bytes pinned_peer_certificate_public_key_sha256 = 14; @@ -88,5 +86,9 @@ message Config { // Lists of string as CurvePreferences values. repeated string curve_preferences = 16; - string server_name_to_verify = 17; + /* @Document Replaces server_name to verify the peer cert. + @Document After allow_insecure (automatically), if the server's cert can't be verified by any of these names, pinned_peer_certificate_chain_sha256 will be tried. + @Critical + */ + repeated string verify_peer_cert_in_names = 17; } diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go index e15231f4..bdf77d9a 100644 --- a/transport/internet/tls/tls.go +++ b/transport/internet/tls/tls.go @@ -16,6 +16,7 @@ type Interface interface { net.Conn HandshakeContext(ctx context.Context) error VerifyHostname(host string) error + HandshakeContextServerName(ctx context.Context) string NegotiatedProtocol() string } @@ -43,15 +44,11 @@ func (c *Conn) WriteMultiBuffer(mb buf.MultiBuffer) error { return err } -func (c *Conn) HandshakeAddressContext(ctx context.Context) net.Address { +func (c *Conn) HandshakeContextServerName(ctx context.Context) string { if err := c.HandshakeContext(ctx); err != nil { - return nil + return "" } - state := c.ConnectionState() - if state.ServerName == "" { - return nil - } - return net.ParseAddress(state.ServerName) + return c.ConnectionState().ServerName } func (c *Conn) NegotiatedProtocol() string { @@ -85,15 +82,11 @@ func (c *UConn) Close() error { return c.Conn.Close() } -func (c *UConn) HandshakeAddressContext(ctx context.Context) net.Address { +func (c *UConn) HandshakeContextServerName(ctx context.Context) string { if err := c.HandshakeContext(ctx); err != nil { - return nil + return "" } - state := c.ConnectionState() - if state.ServerName == "" { - return nil - } - return net.ParseAddress(state.ServerName) + return c.ConnectionState().ServerName } // WebsocketHandshake basically calls UConn.Handshake inside it but it will only send @@ -134,17 +127,13 @@ func UClient(c net.Conn, config *tls.Config, fingerprint *utls.ClientHelloID) ne } func copyConfig(c *tls.Config) *utls.Config { - serverNameToVerify := "" - if r, ok := c.Rand.(*RandCarrier); ok { - serverNameToVerify = r.ServerNameToVerify - } return &utls.Config{ - RootCAs: c.RootCAs, - ServerName: c.ServerName, - InsecureSkipVerify: c.InsecureSkipVerify, - VerifyPeerCertificate: c.VerifyPeerCertificate, - KeyLogWriter: c.KeyLogWriter, - InsecureServerNameToVerify: serverNameToVerify, + Rand: c.Rand, + RootCAs: c.RootCAs, + ServerName: c.ServerName, + InsecureSkipVerify: c.InsecureSkipVerify, + VerifyPeerCertificate: c.VerifyPeerCertificate, + KeyLogWriter: c.KeyLogWriter, } }