github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/tls/config.go (about) 1 // +build !confonly 2 3 package tls 4 5 import ( 6 "crypto/tls" 7 "crypto/x509" 8 "strings" 9 "sync" 10 "time" 11 12 "v2ray.com/core/common/net" 13 "v2ray.com/core/common/protocol/tls/cert" 14 "v2ray.com/core/transport/internet" 15 ) 16 17 var ( 18 globalSessionCache = tls.NewLRUClientSessionCache(128) 19 ) 20 21 const exp8357 = "experiment:8357" 22 23 // ParseCertificate converts a cert.Certificate to Certificate. 24 func ParseCertificate(c *cert.Certificate) *Certificate { 25 certPEM, keyPEM := c.ToPEM() 26 return &Certificate{ 27 Certificate: certPEM, 28 Key: keyPEM, 29 } 30 } 31 32 func (c *Config) loadSelfCertPool() (*x509.CertPool, error) { 33 root := x509.NewCertPool() 34 for _, cert := range c.Certificate { 35 if !root.AppendCertsFromPEM(cert.Certificate) { 36 return nil, newError("failed to append cert").AtWarning() 37 } 38 } 39 return root, nil 40 } 41 42 // BuildCertificates builds a list of TLS certificates from proto definition. 43 func (c *Config) BuildCertificates() []tls.Certificate { 44 certs := make([]tls.Certificate, 0, len(c.Certificate)) 45 for _, entry := range c.Certificate { 46 if entry.Usage != Certificate_ENCIPHERMENT { 47 continue 48 } 49 keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key) 50 if err != nil { 51 newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog() 52 continue 53 } 54 certs = append(certs, keyPair) 55 } 56 return certs 57 } 58 59 func isCertificateExpired(c *tls.Certificate) bool { 60 if c.Leaf == nil && len(c.Certificate) > 0 { 61 if pc, err := x509.ParseCertificate(c.Certificate[0]); err == nil { 62 c.Leaf = pc 63 } 64 } 65 66 // If leaf is not there, the certificate is probably not used yet. We trust user to provide a valid certificate. 67 return c.Leaf != nil && c.Leaf.NotAfter.Before(time.Now().Add(-time.Minute)) 68 } 69 70 func issueCertificate(rawCA *Certificate, domain string) (*tls.Certificate, error) { 71 parent, err := cert.ParseCertificate(rawCA.Certificate, rawCA.Key) 72 if err != nil { 73 return nil, newError("failed to parse raw certificate").Base(err) 74 } 75 newCert, err := cert.Generate(parent, cert.CommonName(domain), cert.DNSNames(domain)) 76 if err != nil { 77 return nil, newError("failed to generate new certificate for ", domain).Base(err) 78 } 79 newCertPEM, newKeyPEM := newCert.ToPEM() 80 cert, err := tls.X509KeyPair(newCertPEM, newKeyPEM) 81 return &cert, err 82 } 83 84 func (c *Config) getCustomCA() []*Certificate { 85 certs := make([]*Certificate, 0, len(c.Certificate)) 86 for _, certificate := range c.Certificate { 87 if certificate.Usage == Certificate_AUTHORITY_ISSUE { 88 certs = append(certs, certificate) 89 } 90 } 91 return certs 92 } 93 94 func getGetCertificateFunc(c *tls.Config, ca []*Certificate) func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { 95 var access sync.RWMutex 96 97 return func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { 98 domain := hello.ServerName 99 certExpired := false 100 101 access.RLock() 102 certificate, found := c.NameToCertificate[domain] 103 access.RUnlock() 104 105 if found { 106 if !isCertificateExpired(certificate) { 107 return certificate, nil 108 } 109 certExpired = true 110 } 111 112 if certExpired { 113 newCerts := make([]tls.Certificate, 0, len(c.Certificates)) 114 115 access.Lock() 116 for _, certificate := range c.Certificates { 117 if !isCertificateExpired(&certificate) { 118 newCerts = append(newCerts, certificate) 119 } 120 } 121 122 c.Certificates = newCerts 123 access.Unlock() 124 } 125 126 var issuedCertificate *tls.Certificate 127 128 // Create a new certificate from existing CA if possible 129 for _, rawCert := range ca { 130 if rawCert.Usage == Certificate_AUTHORITY_ISSUE { 131 newCert, err := issueCertificate(rawCert, domain) 132 if err != nil { 133 newError("failed to issue new certificate for ", domain).Base(err).WriteToLog() 134 continue 135 } 136 137 access.Lock() 138 c.Certificates = append(c.Certificates, *newCert) 139 issuedCertificate = &c.Certificates[len(c.Certificates)-1] 140 access.Unlock() 141 break 142 } 143 } 144 145 if issuedCertificate == nil { 146 return nil, newError("failed to create a new certificate for ", domain) 147 } 148 149 access.Lock() 150 c.BuildNameToCertificate() 151 access.Unlock() 152 153 return issuedCertificate, nil 154 } 155 } 156 157 func (c *Config) IsExperiment8357() bool { 158 return strings.HasPrefix(c.ServerName, exp8357) 159 } 160 161 func (c *Config) parseServerName() string { 162 if c.IsExperiment8357() { 163 return c.ServerName[len(exp8357):] 164 } 165 166 return c.ServerName 167 } 168 169 // GetTLSConfig converts this Config into tls.Config. 170 func (c *Config) GetTLSConfig(opts ...Option) *tls.Config { 171 root, err := c.getCertPool() 172 if err != nil { 173 newError("failed to load system root certificate").AtError().Base(err).WriteToLog() 174 } 175 176 config := &tls.Config{ 177 ClientSessionCache: globalSessionCache, 178 RootCAs: root, 179 InsecureSkipVerify: c.AllowInsecure, 180 NextProtos: c.NextProtocol, 181 SessionTicketsDisabled: c.DisableSessionResumption, 182 } 183 if c == nil { 184 return config 185 } 186 187 for _, opt := range opts { 188 opt(config) 189 } 190 191 config.Certificates = c.BuildCertificates() 192 config.BuildNameToCertificate() 193 194 caCerts := c.getCustomCA() 195 if len(caCerts) > 0 { 196 config.GetCertificate = getGetCertificateFunc(config, caCerts) 197 } 198 199 if sn := c.parseServerName(); len(sn) > 0 { 200 config.ServerName = sn 201 } 202 203 if len(config.NextProtos) == 0 { 204 config.NextProtos = []string{"h2", "http/1.1"} 205 } 206 207 return config 208 } 209 210 // Option for building TLS config. 211 type Option func(*tls.Config) 212 213 // WithDestination sets the server name in TLS config. 214 func WithDestination(dest net.Destination) Option { 215 return func(config *tls.Config) { 216 if dest.Address.Family().IsDomain() && config.ServerName == "" { 217 config.ServerName = dest.Address.Domain() 218 } 219 } 220 } 221 222 // WithNextProto sets the ALPN values in TLS config. 223 func WithNextProto(protocol ...string) Option { 224 return func(config *tls.Config) { 225 if len(config.NextProtos) == 0 { 226 config.NextProtos = protocol 227 } 228 } 229 } 230 231 // ConfigFromStreamSettings fetches Config from stream settings. Nil if not found. 232 func ConfigFromStreamSettings(settings *internet.MemoryStreamConfig) *Config { 233 if settings == nil { 234 return nil 235 } 236 config, ok := settings.SecuritySettings.(*Config) 237 if !ok { 238 return nil 239 } 240 return config 241 }