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
This commit is contained in:
RPRX 2025-02-08 12:11:25 +00:00 committed by GitHub
parent db5f18b98c
commit d4c7cd02fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 14 deletions

View File

@ -433,6 +433,13 @@ func (c *TLSConfig) Build() (proto.Message, error) {
if c.ALPN != nil && len(*c.ALPN) > 0 { if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN) 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 { if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 {
config.CurvePreferences = []string(*c.CurvePreferences) config.CurvePreferences = []string(*c.CurvePreferences)
} }
@ -443,7 +450,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.CipherSuites = c.CipherSuites config.CipherSuites = c.CipherSuites
config.Fingerprint = strings.ToLower(c.Fingerprint) config.Fingerprint = strings.ToLower(c.Fingerprint)
if config.Fingerprint != "unsafe" && tls.GetFingerprint(config.Fingerprint) == nil { 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 config.RejectUnknownSni = c.RejectUnknownSNI
@ -472,7 +479,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MasterKeyLog = c.MasterKeyLog config.MasterKeyLog = c.MasterKeyLog
if c.ServerNameToVerify != "" { if c.ServerNameToVerify != "" {
return nil, errors.PrintRemovedFeatureError("serverNameToVerify", "verifyPeerCertInNames") return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
} }
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames config.VerifyPeerCertInNames = c.VerifyPeerCertInNames

View File

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

View File

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