github.com/imannamdari/v2ray-core/v5@v5.0.5/transport/internet/tls/config.go (about)

     1  package tls
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"encoding/base64"
     8  	"encoding/pem"
     9  	"fmt"
    10  	"strings"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/imannamdari/v2ray-core/v5/common/net"
    15  	"github.com/imannamdari/v2ray-core/v5/common/protocol/tls/cert"
    16  	"github.com/imannamdari/v2ray-core/v5/transport/internet"
    17  )
    18  
    19  var globalSessionCache = tls.NewLRUClientSessionCache(128)
    20  
    21  const exp8357 = "experiment:8357"
    22  
    23  // ParseCertificate converts a cert.Certificate to Certificate.
    24  func ParseCertificate(c *cert.Certificate) *Certificate {
    25  	if c != nil {
    26  		certPEM, keyPEM := c.ToPEM()
    27  		return &Certificate{
    28  			Certificate: certPEM,
    29  			Key:         keyPEM,
    30  		}
    31  	}
    32  	return nil
    33  }
    34  
    35  func (c *Config) loadSelfCertPool(usage Certificate_Usage) (*x509.CertPool, error) {
    36  	root := x509.NewCertPool()
    37  	for _, cert := range c.Certificate {
    38  		if cert.Usage == usage {
    39  			if !root.AppendCertsFromPEM(cert.Certificate) {
    40  				return nil, newError("failed to append cert").AtWarning()
    41  			}
    42  		}
    43  	}
    44  	return root, nil
    45  }
    46  
    47  // BuildCertificates builds a list of TLS certificates from proto definition.
    48  func (c *Config) BuildCertificates() []tls.Certificate {
    49  	certs := make([]tls.Certificate, 0, len(c.Certificate))
    50  	for _, entry := range c.Certificate {
    51  		if entry.Usage != Certificate_ENCIPHERMENT {
    52  			continue
    53  		}
    54  		keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key)
    55  		if err != nil {
    56  			newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
    57  			continue
    58  		}
    59  		certs = append(certs, keyPair)
    60  	}
    61  	return certs
    62  }
    63  
    64  func isCertificateExpired(c *tls.Certificate) bool {
    65  	if c.Leaf == nil && len(c.Certificate) > 0 {
    66  		if pc, err := x509.ParseCertificate(c.Certificate[0]); err == nil {
    67  			c.Leaf = pc
    68  		}
    69  	}
    70  
    71  	// If leaf is not there, the certificate is probably not used yet. We trust user to provide a valid certificate.
    72  	return c.Leaf != nil && c.Leaf.NotAfter.Before(time.Now().Add(time.Minute*2))
    73  }
    74  
    75  func issueCertificate(rawCA *Certificate, domain string) (*tls.Certificate, error) {
    76  	parent, err := cert.ParseCertificate(rawCA.Certificate, rawCA.Key)
    77  	if err != nil {
    78  		return nil, newError("failed to parse raw certificate").Base(err)
    79  	}
    80  	newCert, err := cert.Generate(parent, cert.CommonName(domain), cert.DNSNames(domain))
    81  	if err != nil {
    82  		return nil, newError("failed to generate new certificate for ", domain).Base(err)
    83  	}
    84  	newCertPEM, newKeyPEM := newCert.ToPEM()
    85  	cert, err := tls.X509KeyPair(newCertPEM, newKeyPEM)
    86  	return &cert, err
    87  }
    88  
    89  func (c *Config) getCustomCA() []*Certificate {
    90  	certs := make([]*Certificate, 0, len(c.Certificate))
    91  	for _, certificate := range c.Certificate {
    92  		if certificate.Usage == Certificate_AUTHORITY_ISSUE {
    93  			certs = append(certs, certificate)
    94  		}
    95  	}
    96  	return certs
    97  }
    98  
    99  func getGetCertificateFunc(c *tls.Config, ca []*Certificate) func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
   100  	var access sync.RWMutex
   101  
   102  	return func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
   103  		domain := hello.ServerName
   104  		certExpired := false
   105  
   106  		access.RLock()
   107  		certificate, found := c.NameToCertificate[domain]
   108  		access.RUnlock()
   109  
   110  		if found {
   111  			if !isCertificateExpired(certificate) {
   112  				return certificate, nil
   113  			}
   114  			certExpired = true
   115  		}
   116  
   117  		if certExpired {
   118  			newCerts := make([]tls.Certificate, 0, len(c.Certificates))
   119  
   120  			access.Lock()
   121  			for _, certificate := range c.Certificates {
   122  				cert := certificate
   123  				if !isCertificateExpired(&cert) {
   124  					newCerts = append(newCerts, cert)
   125  				} else if cert.Leaf != nil {
   126  					expTime := cert.Leaf.NotAfter.Format(time.RFC3339)
   127  					newError("old certificate for ", domain, " (expire on ", expTime, ") discard").AtInfo().WriteToLog()
   128  				}
   129  			}
   130  
   131  			c.Certificates = newCerts
   132  			access.Unlock()
   133  		}
   134  
   135  		var issuedCertificate *tls.Certificate
   136  
   137  		// Create a new certificate from existing CA if possible
   138  		for _, rawCert := range ca {
   139  			if rawCert.Usage == Certificate_AUTHORITY_ISSUE {
   140  				newCert, err := issueCertificate(rawCert, domain)
   141  				if err != nil {
   142  					newError("failed to issue new certificate for ", domain).Base(err).WriteToLog()
   143  					continue
   144  				}
   145  				parsed, err := x509.ParseCertificate(newCert.Certificate[0])
   146  				if err == nil {
   147  					newCert.Leaf = parsed
   148  					expTime := parsed.NotAfter.Format(time.RFC3339)
   149  					newError("new certificate for ", domain, " (expire on ", expTime, ") issued").AtInfo().WriteToLog()
   150  				} else {
   151  					newError("failed to parse new certificate for ", domain).Base(err).WriteToLog()
   152  				}
   153  
   154  				access.Lock()
   155  				c.Certificates = append(c.Certificates, *newCert)
   156  				issuedCertificate = &c.Certificates[len(c.Certificates)-1]
   157  				access.Unlock()
   158  				break
   159  			}
   160  		}
   161  
   162  		if issuedCertificate == nil {
   163  			return nil, newError("failed to create a new certificate for ", domain)
   164  		}
   165  
   166  		access.Lock()
   167  		c.BuildNameToCertificate()
   168  		access.Unlock()
   169  
   170  		return issuedCertificate, nil
   171  	}
   172  }
   173  
   174  func (c *Config) IsExperiment8357() bool {
   175  	return strings.HasPrefix(c.ServerName, exp8357)
   176  }
   177  
   178  func (c *Config) parseServerName() string {
   179  	if c.IsExperiment8357() {
   180  		return c.ServerName[len(exp8357):]
   181  	}
   182  
   183  	return c.ServerName
   184  }
   185  
   186  func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   187  	if c.PinnedPeerCertificateChainSha256 != nil {
   188  		hashValue := GenerateCertChainHash(rawCerts)
   189  		for _, v := range c.PinnedPeerCertificateChainSha256 {
   190  			if hmac.Equal(hashValue, v) {
   191  				return nil
   192  			}
   193  		}
   194  		return newError("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
   195  	}
   196  	return nil
   197  }
   198  
   199  // GetTLSConfig converts this Config into tls.Config.
   200  func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
   201  	root, err := c.getCertPool()
   202  	if err != nil {
   203  		newError("failed to load system root certificate").AtError().Base(err).WriteToLog()
   204  	}
   205  
   206  	if c == nil {
   207  		return &tls.Config{
   208  			ClientSessionCache:     globalSessionCache,
   209  			RootCAs:                root,
   210  			InsecureSkipVerify:     false,
   211  			NextProtos:             nil,
   212  			SessionTicketsDisabled: true,
   213  		}
   214  	}
   215  
   216  	clientRoot, err := c.loadSelfCertPool(Certificate_AUTHORITY_VERIFY_CLIENT)
   217  	if err != nil {
   218  		newError("failed to load client root certificate").AtError().Base(err).WriteToLog()
   219  	}
   220  
   221  	var echConfigs []tls.ECHConfig
   222  	if c.EnableEch {
   223  		echPEMKey := fmt.Sprintf("-----BEGIN ECH CONFIGS-----\n%s\n-----END ECH CONFIGS-----", ECH)
   224  
   225  		block, rest := pem.Decode([]byte(echPEMKey))
   226  		if block == nil || block.Type != "ECH CONFIGS" || len(rest) > 0 {
   227  			newError("failed to PEM-decode the ECH configs").AtError().WriteToLog()
   228  		}
   229  
   230  		echConfigs, err = tls.UnmarshalECHConfigs(block.Bytes)
   231  		if err != nil {
   232  			newError("failed to unmarshal ECH configs").AtError().WriteToLog()
   233  		}
   234  	}
   235  
   236  	config := &tls.Config{
   237  		ClientSessionCache:     globalSessionCache,
   238  		RootCAs:                root,
   239  		InsecureSkipVerify:     c.AllowInsecure,
   240  		NextProtos:             c.NextProtocol,
   241  		SessionTicketsDisabled: !c.EnableSessionResumption,
   242  		VerifyPeerCertificate:  c.verifyPeerCert,
   243  		ClientCAs:              clientRoot,
   244  		ECHEnabled:             c.EnableEch,
   245  		ClientECHConfigs:       echConfigs,
   246  	}
   247  
   248  	for _, opt := range opts {
   249  		opt(config)
   250  	}
   251  
   252  	config.Certificates = c.BuildCertificates()
   253  	config.BuildNameToCertificate()
   254  
   255  	caCerts := c.getCustomCA()
   256  	if len(caCerts) > 0 {
   257  		config.GetCertificate = getGetCertificateFunc(config, caCerts)
   258  	}
   259  
   260  	if sn := c.parseServerName(); len(sn) > 0 {
   261  		config.ServerName = sn
   262  	}
   263  
   264  	if len(config.NextProtos) == 0 {
   265  		config.NextProtos = []string{"h2", "http/1.1"}
   266  	}
   267  
   268  	if c.VerifyClientCertificate {
   269  		config.ClientAuth = tls.RequireAndVerifyClientCert
   270  	}
   271  	return config
   272  }
   273  
   274  // Option for building TLS config.
   275  type Option func(*tls.Config)
   276  
   277  // WithDestination sets the server name in TLS config.
   278  func WithDestination(dest net.Destination) Option {
   279  	return func(config *tls.Config) {
   280  		if dest.Address.Family().IsDomain() && config.ServerName == "" {
   281  			config.ServerName = dest.Address.Domain()
   282  		}
   283  	}
   284  }
   285  
   286  // WithNextProto sets the ALPN values in TLS config.
   287  func WithNextProto(protocol ...string) Option {
   288  	return func(config *tls.Config) {
   289  		if len(config.NextProtos) == 0 {
   290  			config.NextProtos = protocol
   291  		}
   292  	}
   293  }
   294  
   295  // ConfigFromStreamSettings fetches Config from stream settings. Nil if not found.
   296  func ConfigFromStreamSettings(settings *internet.MemoryStreamConfig) *Config {
   297  	if settings == nil {
   298  		return nil
   299  	}
   300  	if settings.SecuritySettings == nil {
   301  		return nil
   302  	}
   303  	// Fail close for unknown TLS settings type.
   304  	// For TLS Clients, Security Engine should be used, instead of this.
   305  	config := settings.SecuritySettings.(*Config)
   306  	return config
   307  }