Просмотр исходного кода

Fix uTLS fingerprints support

Thank @HirbodBehnam https://github.com/XTLS/Xray-core/issues/461
RPRX 5 лет назад
Родитель
Сommit
4bf8b6d89c
3 измененных файлов с 34 добавлено и 26 удалено
  1. 4 3
      transport/internet/tcp/dialer.go
  2. 0 10
      transport/internet/tls/config.go
  3. 30 13
      transport/internet/tls/tls.go

+ 4 - 3
transport/internet/tcp/dialer.go

@@ -3,8 +3,6 @@ package tcp
 import (
 	"context"
 
-	utls "github.com/refraction-networking/utls"
-
 	"github.com/xtls/xray-core/common"
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/common/session"
@@ -24,7 +22,10 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
 	if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
 		tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
 		if fingerprint, ok := tls.Fingerprints[config.Fingerprint]; ok {
-			conn = utls.UClient(conn, tls.CopyConfig(tlsConfig), fingerprint)
+			conn = tls.UClient(conn, tlsConfig, fingerprint)
+			if err := conn.(*tls.UConn).Handshake(); err != nil {
+				return nil, err
+			}
 		} else {
 			conn = tls.Client(conn, tlsConfig)
 		}

+ 0 - 10
transport/internet/tls/config.go

@@ -18,8 +18,6 @@ var (
 	globalSessionCache = tls.NewLRUClientSessionCache(128)
 )
 
-const exp8357 = "experiment:8357"
-
 // ParseCertificate converts a cert.Certificate to Certificate.
 func ParseCertificate(c *cert.Certificate) *Certificate {
 	if c != nil {
@@ -240,15 +238,7 @@ func getNewGetCertficateFunc(certs []*tls.Certificate) func(hello *tls.ClientHel
 	}
 }
 
-func (c *Config) IsExperiment8357() bool {
-	return strings.HasPrefix(c.ServerName, exp8357)
-}
-
 func (c *Config) parseServerName() string {
-	if c.IsExperiment8357() {
-		return c.ServerName[len(exp8357):]
-	}
-
 	return c.ServerName
 }
 

+ 30 - 13
transport/internet/tls/tls.go

@@ -43,26 +43,43 @@ func Client(c net.Conn, config *tls.Config) net.Conn {
 	return &Conn{Conn: tlsConn}
 }
 
-var Fingerprints = map[string]utls.ClientHelloID{
-	"chrome":     utls.HelloChrome_Auto,
-	"firefox":    utls.HelloFirefox_Auto,
-	"safari":     utls.HelloIOS_Auto,
-	"randomized": utls.HelloRandomized,
+// Server initiates a TLS server handshake on the given connection.
+func Server(c net.Conn, config *tls.Config) net.Conn {
+	tlsConn := tls.Server(c, config)
+	return &Conn{Conn: tlsConn}
+}
+
+type UConn struct {
+	*utls.UConn
+}
+
+func (c *UConn) HandshakeAddress() net.Address {
+	if err := c.Handshake(); err != nil {
+		return nil
+	}
+	state := c.ConnectionState()
+	if state.ServerName == "" {
+		return nil
+	}
+	return net.ParseAddress(state.ServerName)
 }
 
-func CopyConfig(c *tls.Config) *utls.Config {
+func UClient(c net.Conn, config *tls.Config, fingerprint *utls.ClientHelloID) net.Conn {
+	utlsConn := utls.UClient(c, copyConfig(config), *fingerprint)
+	return &UConn{UConn: utlsConn}
+}
+
+func copyConfig(c *tls.Config) *utls.Config {
 	return &utls.Config{
 		RootCAs:            c.RootCAs,
-		NextProtos:         c.NextProtos,
 		ServerName:         c.ServerName,
 		InsecureSkipVerify: c.InsecureSkipVerify,
-		MinVersion:         c.MinVersion,
-		MaxVersion:         c.MaxVersion,
 	}
 }
 
-// Server initiates a TLS server handshake on the given connection.
-func Server(c net.Conn, config *tls.Config) net.Conn {
-	tlsConn := tls.Server(c, config)
-	return &Conn{Conn: tlsConn}
+var Fingerprints = map[string]*utls.ClientHelloID{
+	"chrome":     &utls.HelloChrome_Auto,
+	"firefox":    &utls.HelloFirefox_Auto,
+	"safari":     &utls.HelloIOS_Auto,
+	"randomized": &utls.HelloRandomized,
 }