From 4bf8b6d89c6e7295044a247a79c3ee4f5fcc68a1 Mon Sep 17 00:00:00 2001
From: RPRX <63339210+rprx@users.noreply.github.com>
Date: Thu, 1 Apr 2021 09:15:18 +0000
Subject: [PATCH 1/4] Fix uTLS fingerprints support

Thank @HirbodBehnam https://github.com/XTLS/Xray-core/issues/461
---
 transport/internet/tcp/dialer.go |  7 +++--
 transport/internet/tls/config.go | 10 ------
 transport/internet/tls/tls.go    | 53 +++++++++++++++++++++-----------
 3 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/transport/internet/tcp/dialer.go b/transport/internet/tcp/dialer.go
index e2c6a1b8..968acbeb 100644
--- a/transport/internet/tcp/dialer.go
+++ b/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)
 		}
diff --git a/transport/internet/tls/config.go b/transport/internet/tls/config.go
index 961bea09..e39a9a4f 100644
--- a/transport/internet/tls/config.go
+++ b/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
 }
 
diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go
index 1e0329bf..b33eaf69 100644
--- a/transport/internet/tls/tls.go
+++ b/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,
-}
-
-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}
 }
+
+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 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,
+		ServerName:         c.ServerName,
+		InsecureSkipVerify: c.InsecureSkipVerify,
+	}
+}
+
+var Fingerprints = map[string]*utls.ClientHelloID{
+	"chrome":     &utls.HelloChrome_Auto,
+	"firefox":    &utls.HelloFirefox_Auto,
+	"safari":     &utls.HelloIOS_Auto,
+	"randomized": &utls.HelloRandomized,
+}

From f65c21337cbd2183b88a1af1787acd2b8d940183 Mon Sep 17 00:00:00 2001
From: Jim Han <50871214+JimhHan@users.noreply.github.com>
Date: Thu, 1 Apr 2021 21:08:53 +0800
Subject: [PATCH 2/4] v1.4.2

---
 core/core.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/core.go b/core/core.go
index 3c2772e3..1553ab7b 100644
--- a/core/core.go
+++ b/core/core.go
@@ -18,7 +18,7 @@ import (
 )
 
 var (
-	version  = "1.4.1"
+	version  = "1.4.2"
 	build    = "Custom"
 	codename = "Xray, Penetrates Everything."
 	intro    = "A unified platform for anti-censorship."

From 1d13a8da4907802c0fc506a989100b81d7abd604 Mon Sep 17 00:00:00 2001
From: lucifer <lucifer@koredump.org>
Date: Mon, 5 Apr 2021 09:00:46 +0800
Subject: [PATCH 3/4] fix grpc dial ipv6 address (#476)

---
 transport/internet/grpc/dial.go | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/transport/internet/grpc/dial.go b/transport/internet/grpc/dial.go
index ed7ad3b5..99c483be 100644
--- a/transport/internet/grpc/dial.go
+++ b/transport/internet/grpc/dial.go
@@ -90,8 +90,14 @@ func getGrpcClient(ctx context.Context, dest net.Destination, tlsConfig *tls.Con
 		dialOption = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig.GetTLSConfig()))
 	}
 
+	var grpcDestHost string
+	if dest.Address.Family().IsDomain() {
+		grpcDestHost = dest.Address.Domain()
+	} else {
+		grpcDestHost = dest.Address.IP().String()
+	}
 	conn, err := grpc.Dial(
-		gonet.JoinHostPort(dest.Address.String(), dest.Port.String()),
+		gonet.JoinHostPort(grpcDestHost, dest.Port.String()),
 		dialOption,
 		grpc.WithConnectParams(grpc.ConnectParams{
 			Backoff: backoff.Config{

From bf94fb53caf61244abeb031a6088566290702a0d Mon Sep 17 00:00:00 2001
From: Bhoppi Chaw <bhoppi@users.noreply.github.com>
Date: Wed, 7 Apr 2021 00:37:28 +0800
Subject: [PATCH 4/4] Fix QUIC disconnecting issue (#475)

Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
---
 transport/internet/quic/dialer.go | 2 +-
 transport/internet/quic/hub.go    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/transport/internet/quic/dialer.go b/transport/internet/quic/dialer.go
index e5a33129..a1d5488f 100644
--- a/transport/internet/quic/dialer.go
+++ b/transport/internet/quic/dialer.go
@@ -148,7 +148,7 @@ func (s *clientSessions) openConnection(destAddr net.Addr, config *Config, tlsCo
 
 	quicConfig := &quic.Config{
 		ConnectionIDLength: 12,
-		MaxIdleTimeout:     time.Second * 30,
+		KeepAlive:          true,
 	}
 
 	conn, err := wrapSysConn(rawConn, config)
diff --git a/transport/internet/quic/hub.go b/transport/internet/quic/hub.go
index eebf1617..605b52dc 100644
--- a/transport/internet/quic/hub.go
+++ b/transport/internet/quic/hub.go
@@ -103,7 +103,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
 
 	quicConfig := &quic.Config{
 		ConnectionIDLength:    12,
-		MaxIdleTimeout:        time.Second * 45,
+		KeepAlive:             true,
 		MaxIncomingStreams:    32,
 		MaxIncomingUniStreams: -1,
 	}