Sfoglia il codice sorgente

MITM freedom RAW TLS: Allow "fromMitm" to be written at any position in `verifyPeerCertInNames`, Add checking for `alpn` "fromMitm"

https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2643340434
RPRX 8 mesi fa
parent
commit
d4c7cd02fd

+ 9 - 2
infra/conf/transport_internet.go

@@ -433,6 +433,13 @@ func (c *TLSConfig) Build() (proto.Message, error) {
 	if c.ALPN != nil && len(*c.ALPN) > 0 {
 		config.NextProtocol = []string(*c.ALPN)
 	}
+	if len(config.NextProtocol) > 1 {
+		for _, p := range config.NextProtocol {
+			if tcp.IsFromMitm(p) {
+				return nil, errors.New(`only one element is allowed in "alpn" when using "fromMitm" in it`)
+			}
+		}
+	}
 	if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 {
 		config.CurvePreferences = []string(*c.CurvePreferences)
 	}
@@ -443,7 +450,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
 	config.CipherSuites = c.CipherSuites
 	config.Fingerprint = strings.ToLower(c.Fingerprint)
 	if config.Fingerprint != "unsafe" && tls.GetFingerprint(config.Fingerprint) == nil {
-		return nil, errors.New(`unknown fingerprint: `, config.Fingerprint)
+		return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
 	}
 	config.RejectUnknownSni = c.RejectUnknownSNI
 
@@ -472,7 +479,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
 	config.MasterKeyLog = c.MasterKeyLog
 
 	if c.ServerNameToVerify != "" {
-		return nil, errors.PrintRemovedFeatureError("serverNameToVerify", "verifyPeerCertInNames")
+		return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
 	}
 	config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
 

+ 19 - 11
transport/internet/tcp/dialer.go

@@ -2,6 +2,7 @@ package tcp
 
 import (
 	"context"
+	"slices"
 	"strings"
 
 	"github.com/xtls/xray-core/common"
@@ -33,17 +34,24 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
 		if IsFromMitm(tlsConfig.ServerName) {
 			tlsConfig.ServerName = mitmServerName
 		}
-		r, ok := tlsConfig.Rand.(*tls.RandCarrier)
-		isFromMitmVerify := ok && len(r.VerifyPeerCertInNames) > 0 && IsFromMitm(r.VerifyPeerCertInNames[0])
-		if isFromMitmVerify {
-			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, ".") {
+		isFromMitmVerify := false
+		if r, ok := tlsConfig.Rand.(*tls.RandCarrier); ok && len(r.VerifyPeerCertInNames) > 0 {
+			for i, name := range r.VerifyPeerCertInNames {
+				if IsFromMitm(name) {
+					isFromMitmVerify = true
+					r.VerifyPeerCertInNames[0], r.VerifyPeerCertInNames[i] = r.VerifyPeerCertInNames[i], 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
+						}
+					}
+					slices.Reverse(r.VerifyPeerCertInNames)
 					break
 				}
 			}

+ 1 - 1
transport/internet/tls/config.go

@@ -300,7 +300,7 @@ func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509
 			}
 		}
 		if r.PinnedPeerCertificateChainSha256 == nil {
-			errors.New("peer cert is invalid.")
+			return errors.New("peer cert is invalid.")
 		}
 	}