Use bundle CA as default

This commit is contained in:
Fangliding
2026-10-08 14:42:53 +08:00
parent 8989adfd3f
commit adff74795e
8 changed files with 78 additions and 34 deletions
+1
View File
@@ -55,6 +55,7 @@ require (
github.com/vishvananda/netns v0.0.5 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/crypto/x509roots/fallback v0.0.0-20261005185213-c3db4df58582 // indirect
golang.org/x/text v0.42.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.49.0 // indirect
+2
View File
@@ -91,6 +91,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA=
golang.org/x/crypto/x509roots/fallback v0.0.0-20261005185213-c3db4df58582 h1:wjDBrGbfLuifgrVLFEWUBJYAfh5Q1wkMc5t0FY0tCbs=
golang.org/x/crypto/x509roots/fallback v0.0.0-20261005185213-c3db4df58582/go.mod h1:HPze8vhfG6fO06AM+VSvxRm4E3+5Yk375mgrJ5M2z1E=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+2
View File
@@ -316,6 +316,7 @@ type TLSConfig struct {
ECHServerKeys string `json:"echServerKeys"`
ECHConfigList string `json:"echConfigList"`
ECHSocketSettings *SocketConfig `json:"echSockopt"`
UseSystemCA bool `json:"useSystemCA"`
}
// Build implements Buildable.
@@ -403,6 +404,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
}
config.EchSocketSettings = ss
}
config.UseSystemCa = c.UseSystemCA
return config, nil
}
+37
View File
@@ -19,6 +19,7 @@ import (
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol/tls/cert"
"github.com/xtls/xray-core/transport/internet"
"golang.org/x/crypto/x509roots/fallback/bundle"
)
var globalSessionCache = tls.NewLRUClientSessionCache(128)
@@ -578,3 +579,39 @@ func verifyChain(certs []*x509.Certificate, pinnedPeerCertSha256 [][]byte) (veri
}
return certNotFound, nil
}
var bundleCertPool = sync.OnceValue(func() *x509.CertPool {
pool := x509.NewCertPool()
for r := range bundle.Roots() {
cert, err := x509.ParseCertificate(r.Certificate)
if err != nil {
continue
}
if r.Constraint != nil {
pool.AddCertWithConstraint(cert, r.Constraint)
} else {
pool.AddCert(cert)
}
}
return pool
})
var systemCertPool = sync.OnceValue(func() *x509.CertPool {
pool, err := x509.SystemCertPool()
if err != nil {
// use bundle cert pool as fallback
pool = bundleCertPool()
}
return pool
})
// pool should not be modified directly, use CertPool.Clone() if needed.
func loadCA(useSystem bool) *x509.CertPool {
var pool *x509.CertPool
if useSystem {
pool = systemCertPool()
} else {
pool = bundleCertPool()
}
return pool
}
+11 -2
View File
@@ -206,6 +206,7 @@ type Config struct {
EchConfigList string `protobuf:"bytes,19,opt,name=ech_config_list,json=echConfigList,proto3" json:"ech_config_list,omitempty"`
EchSocketSettings *internet.SocketConfig `protobuf:"bytes,21,opt,name=ech_socket_settings,json=echSocketSettings,proto3" json:"ech_socket_settings,omitempty"`
PinnedPeerCertSha256 [][]byte `protobuf:"bytes,22,rep,name=pinned_peer_cert_sha256,json=pinnedPeerCertSha256,proto3" json:"pinned_peer_cert_sha256,omitempty"`
UseSystemCa bool `protobuf:"varint,23,opt,name=use_system_ca,json=useSystemCa,proto3" json:"use_system_ca,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -359,6 +360,13 @@ func (x *Config) GetPinnedPeerCertSha256() [][]byte {
return nil
}
func (x *Config) GetUseSystemCa() bool {
if x != nil {
return x.UseSystemCa
}
return false
}
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
const file_transport_internet_tls_config_proto_rawDesc = "" +
@@ -377,7 +385,7 @@ const file_transport_internet_tls_config_proto_rawDesc = "" +
"\x05Usage\x12\x10\n" +
"\fENCIPHERMENT\x10\x00\x12\x14\n" +
"\x10AUTHORITY_VERIFY\x10\x01\x12\x13\n" +
"\x0fAUTHORITY_ISSUE\x10\x02\"\xa6\x06\n" +
"\x0fAUTHORITY_ISSUE\x10\x02\"\xca\x06\n" +
"\x06Config\x12J\n" +
"\vcertificate\x18\x02 \x03(\v2(.xray.transport.internet.tls.CertificateR\vcertificate\x12\x1f\n" +
"\vserver_name\x18\x03 \x01(\tR\n" +
@@ -398,7 +406,8 @@ const file_transport_internet_tls_config_proto_rawDesc = "" +
"\x0fech_server_keys\x18\x12 \x01(\fR\rechServerKeys\x12&\n" +
"\x0fech_config_list\x18\x13 \x01(\tR\rechConfigList\x12U\n" +
"\x13ech_socket_settings\x18\x15 \x01(\v2%.xray.transport.internet.SocketConfigR\x11echSocketSettings\x125\n" +
"\x17pinned_peer_cert_sha256\x18\x16 \x03(\fR\x14pinnedPeerCertSha256Bs\n" +
"\x17pinned_peer_cert_sha256\x18\x16 \x03(\fR\x14pinnedPeerCertSha256\x12\"\n" +
"\ruse_system_ca\x18\x17 \x01(\bR\vuseSystemCaBs\n" +
"\x1fcom.xray.transport.internet.tlsP\x01Z0github.com/xtls/xray-core/transport/internet/tls\xaa\x02\x1bXray.Transport.Internet.Tlsb\x06proto3"
var (
+2
View File
@@ -86,4 +86,6 @@ message Config {
SocketConfig ech_socket_settings = 21;
repeated bytes pinned_peer_cert_sha256 = 22;
bool use_system_ca = 23;
}
+3 -30
View File
@@ -5,50 +5,23 @@ package tls
import (
"crypto/x509"
"sync"
"github.com/xtls/xray-core/common/errors"
)
type rootCertsCache struct {
sync.Mutex
pool *x509.CertPool
}
func (c *rootCertsCache) load() (*x509.CertPool, error) {
c.Lock()
defer c.Unlock()
if c.pool != nil {
return c.pool, nil
}
pool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}
c.pool = pool
return pool, nil
}
var rootCerts rootCertsCache
func (c *Config) getCertPool() (*x509.CertPool, error) {
if c.DisableSystemRoot {
return c.loadSelfCertPool()
}
if len(c.Certificate) == 0 {
return rootCerts.load()
return loadCA(c.UseSystemCa), nil
}
pool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.New("system root").Base(err)
}
pool := loadCA(c.UseSystemCa).Clone()
for _, cert := range c.Certificate {
if !pool.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("append cert to root").Base(err)
return nil, errors.New("append cert to root")
}
}
return pool, nil
+20 -2
View File
@@ -3,12 +3,30 @@
package tls
import "crypto/x509"
import (
"crypto/x509"
"github.com/xtls/xray-core/common/errors"
)
func (c *Config) getCertPool() (*x509.CertPool, error) {
if c.DisableSystemRoot {
return c.loadSelfCertPool()
}
return nil, nil
// Windows should keep RootCAs nil for using the system CA.
if c.UseSystemCa && len(c.Certificate) == 0 {
return nil, nil
}
if len(c.Certificate) == 0 {
return loadCA(c.UseSystemCa), nil
}
pool := loadCA(c.UseSystemCa).Clone()
for _, cert := range c.Certificate {
if !pool.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("failed to append cert")
}
}
return pool, nil
}