github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/xtls/config.go (about)

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