mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-29 06:31:56 +00:00
TLS client: Use Xray-core's built-in RootCAs by default (avoids maliciously injected CA in the OS) (#7105)
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3745598515 https://github.com/XTLS/Xray-core/pull/7098#issuecomment-6053012480 https://github.com/XTLS/Xray-core/pull/7105#issuecomment-6093006914
This commit is contained in:
1 parent
836a6fed38
commit
5af2e9c228
8 files changed
+78
-34
No files matched your search
@@ -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
|
||||
}
|
||||
@@ -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 (
|
||||
|
||||
@@ -86,4 +86,6 @@ message Config {
|
||||
SocketConfig ech_socket_settings = 21;
|
||||
|
||||
repeated bytes pinned_peer_cert_sha256 = 22;
|
||||
|
||||
bool use_system_ca = 23;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user