github.com/astaguna/popon-core@v0.0.0-20231019235610-96e42d76a5ff/psiphon/tlsDialer.go (about)

     1  /*
     2   * Copyright (c) 2015, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  /*
    21  Copyright (c) 2012 The Go Authors. All rights reserved.
    22  
    23  Redistribution and use in source and binary forms, with or without
    24  modification, are permitted provided that the following conditions are
    25  met:
    26  
    27     * Redistributions of source code must retain the above copyright
    28  notice, this list of conditions and the following disclaimer.
    29     * Redistributions in binary form must reproduce the above
    30  copyright notice, this list of conditions and the following disclaimer
    31  in the documentation and/or other materials provided with the
    32  distribution.
    33     * Neither the name of Google Inc. nor the names of its
    34  contributors may be used to endorse or promote products derived from
    35  this software without specific prior written permission.
    36  
    37  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    38  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    39  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    40  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    41  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    42  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    43  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    44  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    45  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    46  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    47  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    48  */
    49  
    50  // Originally based on https://gopkg.in/getlantern/tlsdialer.v1.
    51  
    52  package psiphon
    53  
    54  import (
    55  	"bytes"
    56  	"context"
    57  	"crypto/sha256"
    58  	"crypto/x509"
    59  	"encoding/base64"
    60  	"encoding/hex"
    61  	std_errors "errors"
    62  	"io/ioutil"
    63  	"math"
    64  	"net"
    65  
    66  	"github.com/astaguna/popon-core/psiphon/common"
    67  	"github.com/astaguna/popon-core/psiphon/common/errors"
    68  	"github.com/astaguna/popon-core/psiphon/common/parameters"
    69  	"github.com/astaguna/popon-core/psiphon/common/prng"
    70  	"github.com/astaguna/popon-core/psiphon/common/protocol"
    71  	tris "github.com/astaguna/tls-tris"
    72  	utls "github.com/refraction-networking/utls"
    73  )
    74  
    75  // CustomTLSConfig specifies the parameters for a CustomTLSDial, supporting
    76  // many TLS-related network obfuscation mechanisms.
    77  type CustomTLSConfig struct {
    78  
    79  	// Parameters is the active set of parameters.Parameters to use for the TLS
    80  	// dial. Must not be nil.
    81  	Parameters *parameters.Parameters
    82  
    83  	// Dial is the network connection dialer. TLS is layered on top of a new
    84  	// network connection created with dialer. Must not be nil.
    85  	Dial common.Dialer
    86  
    87  	// DialAddr overrides the "addr" input to Dial when specified
    88  	DialAddr string
    89  
    90  	// UseDialAddrSNI specifies whether to always use the dial "addr"
    91  	// host name in the SNI server_name field. When DialAddr is set,
    92  	// its host name is used.
    93  	UseDialAddrSNI bool
    94  
    95  	// SNIServerName specifies the value to set in the SNI
    96  	// server_name field. When blank, SNI is omitted. Note that
    97  	// underlying TLS code also automatically omits SNI when
    98  	// the server_name is an IP address.
    99  	// SNIServerName is ignored when UseDialAddrSNI is true.
   100  	SNIServerName string
   101  
   102  	// DisableSystemRootCAs, when true, disables loading system root CAs when
   103  	// verifying the server certificate chain. Set DisableSystemRootCAs only in
   104  	// cases where system root CAs cannot be loaded; for example, if
   105  	// unsupported (iOS < 12) or insufficient memory (VPN extension on iOS <
   106  	// 15).
   107  	//
   108  	// When DisableSystemRootCAs is set, both VerifyServerName and VerifyPins
   109  	// must be set.
   110  	DisableSystemRootCAs bool
   111  
   112  	// VerifyServerName specifies a domain name that must appear in the server
   113  	// certificate. When specified, certificate verification checks for
   114  	// VerifyServerName in the server certificate, in place of the dial or SNI
   115  	// hostname.
   116  	VerifyServerName string
   117  
   118  	// VerifyPins specifies one or more certificate pin values, one of which must
   119  	// appear in the verified server certificate chain. A pin value is the
   120  	// base64-encoded SHA2 digest of a certificate's public key. When specified,
   121  	// at least one pin must match at least one certificate in the chain, at any
   122  	// position; e.g., the root CA may be pinned, or the server certificate,
   123  	// etc.
   124  	VerifyPins []string
   125  
   126  	// VerifyLegacyCertificate is a special case self-signed server
   127  	// certificate case. Ignores IP SANs and basic constraints. No
   128  	// certificate chain. Just checks that the server presented the
   129  	// specified certificate.
   130  	//
   131  	// When VerifyLegacyCertificate is set, none of VerifyServerName, VerifyPins,
   132  	// SkipVerify may be set.
   133  	VerifyLegacyCertificate *x509.Certificate
   134  
   135  	// SkipVerify completely disables server certificate verification.
   136  	//
   137  	// When SkipVerify is set, none of VerifyServerName, VerifyPins,
   138  	// VerifyLegacyCertificate may be set.
   139  	SkipVerify bool
   140  
   141  	// TLSProfile specifies a particular indistinguishable TLS profile to use for
   142  	// the TLS dial. Setting TLSProfile allows the caller to pin the selection so
   143  	// all TLS connections in a certain context (e.g. a single meek connection)
   144  	// use a consistent value. The value should be selected by calling
   145  	// SelectTLSProfile, which will pick a value at random, subject to
   146  	// compatibility constraints.
   147  	//
   148  	// When TLSProfile is "", a profile is selected at random and
   149  	// DisableFrontingProviderTLSProfiles is ignored.
   150  	TLSProfile string
   151  
   152  	// NoDefaultTLSSessionID specifies whether to set a TLS session ID by
   153  	// default, for a new TLS connection that is not resuming a session.
   154  	// When nil, the parameter is set randomly.
   155  	NoDefaultTLSSessionID *bool
   156  
   157  	// RandomizedTLSProfileSeed specifies the PRNG seed to use when generating
   158  	// a randomized TLS ClientHello, which applies to TLS profiles where
   159  	// protocol.TLSProfileIsRandomized is true. The PRNG seed allows for
   160  	// optional replay of a particular randomized Client Hello.
   161  	RandomizedTLSProfileSeed *prng.Seed
   162  
   163  	// TLSPadding indicates whether to move or add a TLS padding extension to the
   164  	// front of the exension list and apply the specified padding length. Ignored
   165  	// when 0.
   166  	TLSPadding int
   167  
   168  	// TrustedCACertificatesFilename specifies a file containing trusted
   169  	// CA certs. See Config.TrustedCACertificatesFilename.
   170  	TrustedCACertificatesFilename string
   171  
   172  	// ObfuscatedSessionTicketKey enables obfuscated session tickets
   173  	// using the specified key.
   174  	ObfuscatedSessionTicketKey string
   175  
   176  	// PassthroughMessage, when specified, is a 32 byte value that is sent in the
   177  	// ClientHello random value field. The value should be generated using
   178  	// obfuscator.MakeTLSPassthroughMessage.
   179  	PassthroughMessage []byte
   180  
   181  	clientSessionCache utls.ClientSessionCache
   182  }
   183  
   184  // EnableClientSessionCache initializes a cache to use to persist session
   185  // tickets, enabling TLS session resumability across multiple
   186  // CustomTLSDial calls or dialers using the same CustomTLSConfig.
   187  func (config *CustomTLSConfig) EnableClientSessionCache() {
   188  	if config.clientSessionCache == nil {
   189  		config.clientSessionCache = utls.NewLRUClientSessionCache(0)
   190  	}
   191  }
   192  
   193  // NewCustomTLSDialer creates a new dialer based on CustomTLSDial.
   194  func NewCustomTLSDialer(config *CustomTLSConfig) common.Dialer {
   195  	return func(ctx context.Context, network, addr string) (net.Conn, error) {
   196  		return CustomTLSDial(ctx, network, addr, config)
   197  	}
   198  }
   199  
   200  // CustomTLSDial dials a new TLS connection using the parameters set in
   201  // CustomTLSConfig.
   202  //
   203  // The dial aborts if ctx becomes Done before the dial completes.
   204  func CustomTLSDial(
   205  	ctx context.Context,
   206  	network, addr string,
   207  	config *CustomTLSConfig) (net.Conn, error) {
   208  
   209  	if (config.SkipVerify &&
   210  		(config.VerifyLegacyCertificate != nil ||
   211  			len(config.VerifyServerName) > 0 ||
   212  			len(config.VerifyPins) > 0)) ||
   213  
   214  		(config.VerifyLegacyCertificate != nil &&
   215  			(config.SkipVerify ||
   216  				len(config.VerifyServerName) > 0 ||
   217  				len(config.VerifyPins) > 0)) ||
   218  
   219  		(config.DisableSystemRootCAs &&
   220  			(!config.SkipVerify &&
   221  				(len(config.VerifyServerName) == 0 ||
   222  					len(config.VerifyPins) == 0))) {
   223  
   224  		return nil, errors.TraceNew("incompatible certification verification parameters")
   225  	}
   226  
   227  	p := config.Parameters.Get()
   228  
   229  	dialAddr := addr
   230  	if config.DialAddr != "" {
   231  		dialAddr = config.DialAddr
   232  	}
   233  
   234  	rawConn, err := config.Dial(ctx, network, dialAddr)
   235  	if err != nil {
   236  		return nil, errors.Trace(err)
   237  	}
   238  
   239  	hostname, _, err := net.SplitHostPort(dialAddr)
   240  	if err != nil {
   241  		rawConn.Close()
   242  		return nil, errors.Trace(err)
   243  	}
   244  
   245  	var tlsConfigRootCAs *x509.CertPool
   246  	if !config.SkipVerify &&
   247  		config.VerifyLegacyCertificate == nil &&
   248  		config.TrustedCACertificatesFilename != "" {
   249  
   250  		tlsConfigRootCAs = x509.NewCertPool()
   251  		certData, err := ioutil.ReadFile(config.TrustedCACertificatesFilename)
   252  		if err != nil {
   253  			return nil, errors.Trace(err)
   254  		}
   255  		tlsConfigRootCAs.AppendCertsFromPEM(certData)
   256  	}
   257  
   258  	// In some cases, config.SkipVerify is false, but
   259  	// utls.Config.InsecureSkipVerify will be set to true to disable verification
   260  	// in utls that will otherwise fail: when SNI is omitted, and when
   261  	// VerifyServerName differs from SNI. In these cases, the certificate chain
   262  	// is verified in VerifyPeerCertificate.
   263  
   264  	tlsConfigInsecureSkipVerify := false
   265  	tlsConfigServerName := ""
   266  	verifyServerName := hostname
   267  
   268  	if config.SkipVerify {
   269  		tlsConfigInsecureSkipVerify = true
   270  	}
   271  
   272  	if config.UseDialAddrSNI {
   273  
   274  		// Set SNI to match the dial hostname. This is the standard case.
   275  		tlsConfigServerName = hostname
   276  
   277  	} else if config.SNIServerName != "" {
   278  
   279  		// Set a custom SNI value. If this value doesn't match the server
   280  		// certificate, SkipVerify and/or VerifyServerName may need to be
   281  		// configured; but by itself this case doesn't necessarily require
   282  		// custom certificate verification.
   283  		tlsConfigServerName = config.SNIServerName
   284  
   285  	} else {
   286  
   287  		// Omit SNI. If SkipVerify is not set, this case requires custom certificate
   288  		// verification, which will check that the server certificate matches either
   289  		// the dial hostname or VerifyServerName, as if the SNI were set to one of
   290  		// those values.
   291  		tlsConfigInsecureSkipVerify = true
   292  	}
   293  
   294  	// When VerifyServerName does not match the SNI, custom certificate
   295  	// verification is necessary.
   296  	if config.VerifyServerName != "" && config.VerifyServerName != tlsConfigServerName {
   297  		verifyServerName = config.VerifyServerName
   298  		tlsConfigInsecureSkipVerify = true
   299  	}
   300  
   301  	// With the VerifyPeerCertificate callback, we perform any custom certificate
   302  	// verification at the same point in the TLS handshake as standard utls
   303  	// verification; and abort the handshake at the same point, if custom
   304  	// verification fails.
   305  	var tlsConfigVerifyPeerCertificate func([][]byte, [][]*x509.Certificate) error
   306  	if !config.SkipVerify {
   307  		tlsConfigVerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   308  
   309  			if config.VerifyLegacyCertificate != nil {
   310  				return verifyLegacyCertificate(
   311  					rawCerts, config.VerifyLegacyCertificate)
   312  			}
   313  
   314  			if tlsConfigInsecureSkipVerify {
   315  
   316  				// Limitation: this verification path does not set the utls.Conn's
   317  				// ConnectionState certificate information.
   318  
   319  				if len(verifiedChains) > 0 {
   320  					return errors.TraceNew("unexpected verified chains")
   321  				}
   322  				var err error
   323  				verifiedChains, err = verifyServerCertificate(
   324  					tlsConfigRootCAs, rawCerts, verifyServerName, config.DisableSystemRootCAs)
   325  				if err != nil {
   326  					return errors.Trace(err)
   327  				}
   328  			}
   329  
   330  			if len(config.VerifyPins) > 0 {
   331  				err := verifyCertificatePins(
   332  					config.VerifyPins, verifiedChains)
   333  				if err != nil {
   334  					return errors.Trace(err)
   335  				}
   336  			}
   337  
   338  			return nil
   339  		}
   340  	}
   341  
   342  	tlsConfig := &utls.Config{
   343  		RootCAs:               tlsConfigRootCAs,
   344  		InsecureSkipVerify:    tlsConfigInsecureSkipVerify,
   345  		ServerName:            tlsConfigServerName,
   346  		VerifyPeerCertificate: tlsConfigVerifyPeerCertificate,
   347  	}
   348  
   349  	var randomizedTLSProfileSeed *prng.Seed
   350  	selectedTLSProfile := config.TLSProfile
   351  
   352  	if selectedTLSProfile == "" {
   353  		selectedTLSProfile, _, randomizedTLSProfileSeed, err = SelectTLSProfile(false, false, false, "", p)
   354  		if err != nil {
   355  			return nil, errors.Trace(err)
   356  		}
   357  	}
   358  
   359  	utlsClientHelloID, utlsClientHelloSpec, err := getUTLSClientHelloID(
   360  		p, selectedTLSProfile)
   361  	if err != nil {
   362  		return nil, errors.Trace(err)
   363  	}
   364  
   365  	isRandomized := protocol.TLSProfileIsRandomized(selectedTLSProfile)
   366  	if isRandomized {
   367  
   368  		// Give config.RandomizedTLSProfileSeed precedence over the seed
   369  		// generated by SelectTLSProfile if selectedTLSProfile == "".
   370  		if config.RandomizedTLSProfileSeed != nil {
   371  			randomizedTLSProfileSeed = config.RandomizedTLSProfileSeed
   372  		}
   373  
   374  		if randomizedTLSProfileSeed == nil {
   375  
   376  			randomizedTLSProfileSeed, err = prng.NewSeed()
   377  			if err != nil {
   378  				return nil, errors.Trace(err)
   379  			}
   380  		}
   381  
   382  		utlsClientHelloID.Seed = new(utls.PRNGSeed)
   383  		*utlsClientHelloID.Seed = [32]byte(*randomizedTLSProfileSeed)
   384  
   385  		weights := utls.DefaultWeights
   386  		weights.TLSVersMax_Set_VersionTLS13 = 0.5
   387  		utlsClientHelloID.Weights = &weights
   388  	}
   389  
   390  	// As noted here,
   391  	// https://gitlab.com/yawning/obfs4/commit/ca6765e3e3995144df2b1ca9f0e9d823a7f8a47c,
   392  	// the dynamic record sizing optimization in crypto/tls is not commonly
   393  	// implemented in browsers. Disable it for all utls parrots and select it
   394  	// randomly when using the randomized client hello.
   395  	if isRandomized {
   396  		PRNG, err := prng.NewPRNGWithSaltedSeed(randomizedTLSProfileSeed, "tls-dynamic-record-sizing")
   397  		if err != nil {
   398  			return nil, errors.Trace(err)
   399  		}
   400  		tlsConfig.DynamicRecordSizingDisabled = PRNG.FlipCoin()
   401  	} else {
   402  		tlsConfig.DynamicRecordSizingDisabled = true
   403  	}
   404  
   405  	conn := utls.UClient(rawConn, tlsConfig, utlsClientHelloID)
   406  
   407  	if utlsClientHelloSpec != nil {
   408  		err := conn.ApplyPreset(utlsClientHelloSpec)
   409  		if err != nil {
   410  			return nil, errors.Trace(err)
   411  		}
   412  	}
   413  
   414  	clientSessionCache := config.clientSessionCache
   415  	if clientSessionCache == nil {
   416  		clientSessionCache = utls.NewLRUClientSessionCache(0)
   417  	}
   418  
   419  	conn.SetSessionCache(clientSessionCache)
   420  
   421  	// TODO: can conn.SetClientRandom be made to take effect if called here? In
   422  	// testing, the random value appears to be overwritten. As is, the overhead
   423  	// of needRemarshal is now always required to handle
   424  	// config.PassthroughMessage.
   425  
   426  	// Build handshake state in advance to obtain the TLS version, which is used
   427  	// to determine whether the following customizations may be applied. Don't use
   428  	// getClientHelloVersion, since that may incur additional overhead.
   429  
   430  	err = conn.BuildHandshakeState()
   431  	if err != nil {
   432  		return nil, errors.Trace(err)
   433  	}
   434  
   435  	isTLS13 := false
   436  	for _, vers := range conn.HandshakeState.Hello.SupportedVersions {
   437  		if vers == utls.VersionTLS13 {
   438  			isTLS13 = true
   439  			break
   440  		}
   441  	}
   442  
   443  	// Add the obfuscated session ticket only when using TLS 1.2.
   444  	//
   445  	// Obfuscated session tickets are not currently supported in TLS 1.3, but we
   446  	// allow UNFRONTED-MEEK-SESSION-TICKET-OSSH to use TLS 1.3 profiles for
   447  	// additional diversity/capacity; TLS 1.3 encrypts the server certificate,
   448  	// so the desired obfuscated session tickets property of obfuscating server
   449  	// certificates is satisfied. We know that when the ClientHello offers TLS
   450  	// 1.3, the Psiphon server, in these direct protocol cases, will negotiate
   451  	// it.
   452  
   453  	if config.ObfuscatedSessionTicketKey != "" && !isTLS13 {
   454  
   455  		var obfuscatedSessionTicketKey [32]byte
   456  
   457  		key, err := hex.DecodeString(config.ObfuscatedSessionTicketKey)
   458  		if err == nil && len(key) != 32 {
   459  			err = std_errors.New("invalid obfuscated session key length")
   460  		}
   461  		if err != nil {
   462  			return nil, errors.Trace(err)
   463  		}
   464  		copy(obfuscatedSessionTicketKey[:], key)
   465  
   466  		obfuscatedSessionState, err := tris.NewObfuscatedClientSessionState(
   467  			obfuscatedSessionTicketKey)
   468  		if err != nil {
   469  			return nil, errors.Trace(err)
   470  		}
   471  
   472  		conn.SetSessionState(
   473  			utls.MakeClientSessionState(
   474  				obfuscatedSessionState.SessionTicket,
   475  				obfuscatedSessionState.Vers,
   476  				obfuscatedSessionState.CipherSuite,
   477  				obfuscatedSessionState.MasterSecret,
   478  				nil,
   479  				nil))
   480  
   481  		// Apply changes to utls
   482  		err = conn.BuildHandshakeState()
   483  		if err != nil {
   484  			return nil, errors.Trace(err)
   485  		}
   486  
   487  		// Ensure that TLS ClientHello has required session ticket extension and
   488  		// obfuscated session ticket cipher suite; the latter is required by
   489  		// utls/tls.Conn.loadSession. If these requirements are not met the
   490  		// obfuscation session ticket would be ignored, so fail.
   491  
   492  		if !tris.ContainsObfuscatedSessionTicketCipherSuite(
   493  			conn.HandshakeState.Hello.CipherSuites) {
   494  			return nil, errors.TraceNew(
   495  				"missing obfuscated session ticket cipher suite")
   496  		}
   497  
   498  		if len(conn.HandshakeState.Hello.SessionTicket) == 0 {
   499  			return nil, errors.TraceNew("missing session ticket extension")
   500  		}
   501  	}
   502  
   503  	// Perform at most one remarshal for the following ClientHello
   504  	// modifications.
   505  	needRemarshal := false
   506  
   507  	// Either pre-TLS 1.3 ClientHellos or any randomized ClientHello is a
   508  	// candidate for NoDefaultSessionID logic.
   509  	if len(conn.HandshakeState.Hello.SessionTicket) == 0 &&
   510  		(!isTLS13 || utlsClientHelloID.Client == "Randomized") {
   511  
   512  		var noDefaultSessionID bool
   513  		if config.NoDefaultTLSSessionID != nil {
   514  			noDefaultSessionID = *config.NoDefaultTLSSessionID
   515  		} else {
   516  			noDefaultSessionID = config.Parameters.Get().WeightedCoinFlip(
   517  				parameters.NoDefaultTLSSessionIDProbability)
   518  		}
   519  
   520  		if noDefaultSessionID {
   521  			conn.HandshakeState.Hello.SessionId = nil
   522  			needRemarshal = true
   523  		}
   524  	}
   525  
   526  	// utls doesn't omit the server_name extension when the ServerName value is
   527  	// empty or an IP address. To avoid a fingerprintable invalid/unusual
   528  	// server_name extension, remove it in these cases.
   529  	if tlsConfigServerName == "" || net.ParseIP(tlsConfigServerName) != nil {
   530  
   531  		// Assumes only one SNIExtension.
   532  		// TODO: use new UConn.RemoveSNIExtension function?
   533  		deleteIndex := -1
   534  		for index, extension := range conn.Extensions {
   535  			if _, ok := extension.(*utls.SNIExtension); ok {
   536  				deleteIndex = index
   537  				break
   538  			}
   539  		}
   540  		if deleteIndex != -1 {
   541  			conn.Extensions = append(
   542  				conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
   543  		}
   544  		needRemarshal = true
   545  	}
   546  
   547  	if config.TLSPadding > 0 {
   548  
   549  		tlsPadding := config.TLSPadding
   550  
   551  		// Maximum padding size per RFC 7685
   552  		if tlsPadding > 65535 {
   553  			tlsPadding = 65535
   554  		}
   555  
   556  		// Assumes only one PaddingExtension.
   557  		deleteIndex := -1
   558  		for index, extension := range conn.Extensions {
   559  			if _, ok := extension.(*utls.UtlsPaddingExtension); ok {
   560  				deleteIndex = index
   561  				break
   562  			}
   563  		}
   564  		if deleteIndex != -1 {
   565  			conn.Extensions = append(
   566  				conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
   567  		}
   568  
   569  		paddingExtension := &utls.UtlsPaddingExtension{
   570  			PaddingLen: tlsPadding,
   571  			WillPad:    true,
   572  		}
   573  		conn.Extensions = append([]utls.TLSExtension{paddingExtension}, conn.Extensions...)
   574  
   575  		needRemarshal = true
   576  
   577  	}
   578  
   579  	if config.PassthroughMessage != nil {
   580  		err := conn.SetClientRandom(config.PassthroughMessage)
   581  		if err != nil {
   582  			return nil, errors.Trace(err)
   583  		}
   584  
   585  		needRemarshal = true
   586  	}
   587  
   588  	if needRemarshal {
   589  		// Apply changes to utls
   590  		err = conn.MarshalClientHello()
   591  		if err != nil {
   592  			return nil, errors.Trace(err)
   593  		}
   594  	}
   595  
   596  	// Perform the TLS Handshake.
   597  
   598  	resultChannel := make(chan error)
   599  
   600  	go func() {
   601  		resultChannel <- conn.Handshake()
   602  	}()
   603  
   604  	select {
   605  	case err = <-resultChannel:
   606  	case <-ctx.Done():
   607  		err = ctx.Err()
   608  		// Interrupt the goroutine
   609  		rawConn.Close()
   610  		<-resultChannel
   611  	}
   612  
   613  	if err != nil {
   614  		rawConn.Close()
   615  		return nil, errors.Trace(err)
   616  	}
   617  
   618  	return conn, nil
   619  }
   620  
   621  func verifyLegacyCertificate(rawCerts [][]byte, expectedCertificate *x509.Certificate) error {
   622  	if len(rawCerts) < 1 {
   623  		return errors.TraceNew("missing certificate")
   624  	}
   625  	if !bytes.Equal(rawCerts[0], expectedCertificate.Raw) {
   626  		return errors.TraceNew("unexpected certificate")
   627  	}
   628  	return nil
   629  }
   630  
   631  // verifyServerCertificate parses and verifies the provided chain. If
   632  // successful, it returns the verified chains that were built.
   633  //
   634  // WARNING: disableSystemRootCAs must only be set when the certificate
   635  // chain has been, or will be, verified with verifyCertificatePins.
   636  func verifyServerCertificate(
   637  	rootCAs *x509.CertPool, rawCerts [][]byte, verifyServerName string, disableSystemRootCAs bool) ([][]*x509.Certificate, error) {
   638  
   639  	// This duplicates the verification logic in utls (and standard crypto/tls).
   640  
   641  	certs := make([]*x509.Certificate, len(rawCerts))
   642  	for i, rawCert := range rawCerts {
   643  		cert, err := x509.ParseCertificate(rawCert)
   644  		if err != nil {
   645  			return nil, errors.Trace(err)
   646  		}
   647  		certs[i] = cert
   648  	}
   649  
   650  	// Ensure system root CAs are not loaded, which will cause verification to
   651  	// fail. Instead use the root certificate of the chain received from the
   652  	// server as a trusted root certificate, which allows the chain and server
   653  	// name to be verified while ignoring whether the root certificate is
   654  	// trusted by the system.
   655  	if rootCAs == nil && disableSystemRootCAs {
   656  		rootCAs = x509.NewCertPool()
   657  		if len(certs) > 0 {
   658  			rootCAs.AddCert(certs[len(certs)-1])
   659  		}
   660  	}
   661  
   662  	opts := x509.VerifyOptions{
   663  		Roots:         rootCAs,
   664  		DNSName:       verifyServerName,
   665  		Intermediates: x509.NewCertPool(),
   666  	}
   667  
   668  	for i, cert := range certs {
   669  		if i == 0 {
   670  			continue
   671  		}
   672  		opts.Intermediates.AddCert(cert)
   673  	}
   674  
   675  	verifiedChains, err := certs[0].Verify(opts)
   676  	if err != nil {
   677  		return nil, errors.Trace(err)
   678  	}
   679  
   680  	return verifiedChains, nil
   681  }
   682  
   683  func verifyCertificatePins(pins []string, verifiedChains [][]*x509.Certificate) error {
   684  	for _, chain := range verifiedChains {
   685  		for _, cert := range chain {
   686  			publicKeyDigest := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
   687  			expectedPin := base64.StdEncoding.EncodeToString(publicKeyDigest[:])
   688  			if common.Contains(pins, expectedPin) {
   689  				// Return success on the first match of any certificate public key to any
   690  				// pin.
   691  				return nil
   692  			}
   693  		}
   694  	}
   695  	return errors.TraceNew("no pin found")
   696  }
   697  
   698  func IsTLSConnUsingHTTP2(conn net.Conn) bool {
   699  	if c, ok := conn.(*utls.UConn); ok {
   700  		state := c.ConnectionState()
   701  		return state.NegotiatedProtocolIsMutual &&
   702  			state.NegotiatedProtocol == "h2"
   703  	}
   704  	return false
   705  }
   706  
   707  // SelectTLSProfile picks and returns a TLS profile at random from the
   708  // available candidates along with its version and a newly generated PRNG seed
   709  // if the profile is randomized, i.e. protocol.TLSProfileIsRandomized is true,
   710  // which should be used when generating a randomized TLS ClientHello.
   711  func SelectTLSProfile(
   712  	requireTLS12SessionTickets bool,
   713  	requireTLS13Support bool,
   714  	isFronted bool,
   715  	frontingProviderID string,
   716  	p parameters.ParametersAccessor) (tlsProfile, tlsVersion string, randomizedTLSProfileSeed *prng.Seed, err error) {
   717  
   718  	for {
   719  		tlsProfile, tlsVersion, randomizedTLSProfileSeed, err = selectTLSProfile(requireTLS12SessionTickets, isFronted, frontingProviderID, p)
   720  		if err != nil {
   721  			return "", "", nil, errors.Trace(err)
   722  		}
   723  
   724  		if requireTLS13Support && tlsVersion != protocol.TLS_VERSION_13 {
   725  			// Continue picking profiles at random until an eligible one is
   726  			// chosen. It is okay to loop in this way because the probability of
   727  			// selecting a TLS 1.3 profile is high enough that it should not
   728  			// take too many iterations until one is chosen.
   729  			continue
   730  		}
   731  
   732  		return
   733  	}
   734  }
   735  
   736  // selectTLSProfile is a helper that picks and returns a TLS profile at random
   737  // from the available candidates along with its version and a newly generated
   738  // PRNG seed if the profile is randomized, i.e. protocol.TLSProfileIsRandomized
   739  // is true.
   740  func selectTLSProfile(
   741  	requireTLS12SessionTickets bool,
   742  	isFronted bool,
   743  	frontingProviderID string,
   744  	p parameters.ParametersAccessor) (tlsProfile string, tlsVersion string, randomizedTLSProfileSeed *prng.Seed, err error) {
   745  
   746  	// Two TLS profile lists are constructed, subject to limit constraints:
   747  	// stock, fixed parrots (non-randomized SupportedTLSProfiles) and custom
   748  	// parrots (CustomTLSProfileNames); and randomized. If one list is empty, the
   749  	// non-empty list is used. Otherwise SelectRandomizedTLSProfileProbability
   750  	// determines which list is used.
   751  	//
   752  	// Note that LimitTLSProfiles is not applied to CustomTLSProfiles; the
   753  	// presence of a candidate in CustomTLSProfiles is treated as explicit
   754  	// enabling.
   755  	//
   756  	// UseOnlyCustomTLSProfiles may be used to disable all stock TLS profiles and
   757  	// use only CustomTLSProfiles; UseOnlyCustomTLSProfiles is ignored if
   758  	// CustomTLSProfiles is empty.
   759  	//
   760  	// For fronted servers, DisableFrontingProviderTLSProfiles may be used
   761  	// to disable TLS profiles which are incompatible with the TLS stack used
   762  	// by the front. For example, if a utls parrot doesn't fully support all
   763  	// of the capabilities in the ClientHello. Unlike the LimitTLSProfiles case,
   764  	// DisableFrontingProviderTLSProfiles may disable CustomTLSProfiles.
   765  
   766  	limitTLSProfiles := p.TLSProfiles(parameters.LimitTLSProfiles)
   767  	var disableTLSProfiles protocol.TLSProfiles
   768  
   769  	if isFronted && frontingProviderID != "" {
   770  		disableTLSProfiles = p.LabeledTLSProfiles(
   771  			parameters.DisableFrontingProviderTLSProfiles, frontingProviderID)
   772  	}
   773  
   774  	randomizedTLSProfiles := make([]string, 0)
   775  	parrotTLSProfiles := make([]string, 0)
   776  
   777  	for _, tlsProfile := range p.CustomTLSProfileNames() {
   778  		if !common.Contains(disableTLSProfiles, tlsProfile) {
   779  			parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
   780  		}
   781  	}
   782  
   783  	useOnlyCustomTLSProfiles := p.Bool(parameters.UseOnlyCustomTLSProfiles)
   784  	if useOnlyCustomTLSProfiles && len(parrotTLSProfiles) == 0 {
   785  		useOnlyCustomTLSProfiles = false
   786  	}
   787  
   788  	if !useOnlyCustomTLSProfiles {
   789  		for _, tlsProfile := range protocol.SupportedTLSProfiles {
   790  
   791  			if len(limitTLSProfiles) > 0 &&
   792  				!common.Contains(limitTLSProfiles, tlsProfile) {
   793  				continue
   794  			}
   795  
   796  			if common.Contains(disableTLSProfiles, tlsProfile) {
   797  				continue
   798  			}
   799  
   800  			// requireTLS12SessionTickets is specified for
   801  			// UNFRONTED-MEEK-SESSION-TICKET-OSSH, a protocol which depends on using
   802  			// obfuscated session tickets to ensure that the server doesn't send its
   803  			// certificate in the TLS handshake. TLS 1.2 profiles which omit session
   804  			// tickets should not be selected. As TLS 1.3 encrypts the server
   805  			// certificate message, there's no exclusion for TLS 1.3.
   806  
   807  			if requireTLS12SessionTickets &&
   808  				protocol.TLS12ProfileOmitsSessionTickets(tlsProfile) {
   809  				continue
   810  			}
   811  
   812  			if protocol.TLSProfileIsRandomized(tlsProfile) {
   813  				randomizedTLSProfiles = append(randomizedTLSProfiles, tlsProfile)
   814  			} else {
   815  				parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
   816  			}
   817  		}
   818  	}
   819  
   820  	if len(randomizedTLSProfiles) > 0 &&
   821  		(len(parrotTLSProfiles) == 0 ||
   822  			p.WeightedCoinFlip(parameters.SelectRandomizedTLSProfileProbability)) {
   823  
   824  		tlsProfile = randomizedTLSProfiles[prng.Intn(len(randomizedTLSProfiles))]
   825  	}
   826  
   827  	if tlsProfile == "" {
   828  		if len(parrotTLSProfiles) == 0 {
   829  			return "", "", nil, nil
   830  		} else {
   831  			tlsProfile = parrotTLSProfiles[prng.Intn(len(parrotTLSProfiles))]
   832  		}
   833  	}
   834  
   835  	utlsClientHelloID, utlsClientHelloSpec, err := getUTLSClientHelloID(
   836  		p, tlsProfile)
   837  	if err != nil {
   838  		return "", "", nil, errors.Trace(err)
   839  	}
   840  
   841  	if protocol.TLSProfileIsRandomized(tlsProfile) {
   842  		randomizedTLSProfileSeed, err = prng.NewSeed()
   843  		if err != nil {
   844  			return "", "", nil, errors.Trace(err)
   845  		}
   846  		utlsClientHelloID.Seed = new(utls.PRNGSeed)
   847  		*utlsClientHelloID.Seed = [32]byte(*randomizedTLSProfileSeed)
   848  	}
   849  
   850  	tlsVersion, err = getClientHelloVersion(
   851  		utlsClientHelloID, utlsClientHelloSpec)
   852  	if err != nil {
   853  		return "", "", nil, errors.Trace(err)
   854  	}
   855  
   856  	return tlsProfile, tlsVersion, randomizedTLSProfileSeed, nil
   857  }
   858  
   859  func getUTLSClientHelloID(
   860  	p parameters.ParametersAccessor,
   861  	tlsProfile string) (utls.ClientHelloID, *utls.ClientHelloSpec, error) {
   862  
   863  	switch tlsProfile {
   864  
   865  	// IMPORTANT: when adding new cases here, also add to
   866  	// getClientHelloVersion below.
   867  
   868  	case protocol.TLS_PROFILE_IOS_111:
   869  		return utls.HelloIOS_11_1, nil, nil
   870  	case protocol.TLS_PROFILE_IOS_121:
   871  		return utls.HelloIOS_12_1, nil, nil
   872  	case protocol.TLS_PROFILE_IOS_13:
   873  		return utls.HelloIOS_13, nil, nil
   874  	case protocol.TLS_PROFILE_IOS_14:
   875  		return utls.HelloIOS_14, nil, nil
   876  	case protocol.TLS_PROFILE_SAFARI_16:
   877  		return utls.HelloSafari_16_0, nil, nil
   878  	case protocol.TLS_PROFILE_CHROME_58:
   879  		return utls.HelloChrome_58, nil, nil
   880  	case protocol.TLS_PROFILE_CHROME_62:
   881  		return utls.HelloChrome_62, nil, nil
   882  	case protocol.TLS_PROFILE_CHROME_70:
   883  		return utls.HelloChrome_70, nil, nil
   884  	case protocol.TLS_PROFILE_CHROME_72:
   885  		return utls.HelloChrome_72, nil, nil
   886  	case protocol.TLS_PROFILE_CHROME_83:
   887  		return utls.HelloChrome_83, nil, nil
   888  	case protocol.TLS_PROFILE_CHROME_96:
   889  		return utls.HelloChrome_96, nil, nil
   890  	case protocol.TLS_PROFILE_CHROME_102:
   891  		return utls.HelloChrome_102, nil, nil
   892  	case protocol.TLS_PROFILE_CHROME_106:
   893  		return utls.HelloChrome_106_Shuffle, nil, nil
   894  	case protocol.TLS_PROFILE_CHROME_112_PSK:
   895  		preset, err := utls.UTLSIdToSpec(utls.HelloChrome_112_PSK_Shuf)
   896  		if err != nil {
   897  			return utls.ClientHelloID{}, nil, err
   898  		}
   899  
   900  		// Generates typical PSK extension values.
   901  		labelLengths := []int{192, 208, 224, 226, 235, 240, 273, 421, 429, 441}
   902  		label := prng.Bytes(labelLengths[prng.Intn(len(labelLengths))])
   903  		obfuscatedTicketAge := prng.RangeUint32(13029567, math.MaxUint32)
   904  
   905  		binder := prng.Bytes(33)
   906  		binder[0] = 0x20 // Binder's length
   907  
   908  		if pskExt, ok := preset.Extensions[len(preset.Extensions)-1].(*utls.FakePreSharedKeyExtension); ok {
   909  			pskExt.PskIdentities = []utls.PskIdentity{
   910  				{
   911  					Label:               label,
   912  					ObfuscatedTicketAge: obfuscatedTicketAge,
   913  				},
   914  			}
   915  			pskExt.PskBinders = [][]byte{binder}
   916  		}
   917  		return utls.HelloCustom, &preset, nil
   918  	case protocol.TLS_PROFILE_FIREFOX_55:
   919  		return utls.HelloFirefox_55, nil, nil
   920  	case protocol.TLS_PROFILE_FIREFOX_56:
   921  		return utls.HelloFirefox_56, nil, nil
   922  	case protocol.TLS_PROFILE_FIREFOX_65:
   923  		return utls.HelloFirefox_65, nil, nil
   924  	case protocol.TLS_PROFILE_FIREFOX_99:
   925  		return utls.HelloFirefox_99, nil, nil
   926  	case protocol.TLS_PROFILE_FIREFOX_105:
   927  		return utls.HelloFirefox_105, nil, nil
   928  	case protocol.TLS_PROFILE_RANDOMIZED:
   929  		return utls.HelloRandomized, nil, nil
   930  	}
   931  
   932  	// utls.HelloCustom with a utls.ClientHelloSpec is used for
   933  	// CustomTLSProfiles.
   934  
   935  	customTLSProfile := p.CustomTLSProfile(tlsProfile)
   936  	if customTLSProfile == nil {
   937  		return utls.ClientHelloID{},
   938  			nil,
   939  			errors.Tracef("unknown TLS profile: %s", tlsProfile)
   940  	}
   941  
   942  	utlsClientHelloSpec, err := customTLSProfile.GetClientHelloSpec()
   943  	if err != nil {
   944  		return utls.ClientHelloID{}, nil, errors.Trace(err)
   945  	}
   946  
   947  	return utls.HelloCustom, utlsClientHelloSpec, nil
   948  }
   949  
   950  func getClientHelloVersion(
   951  	utlsClientHelloID utls.ClientHelloID,
   952  	utlsClientHelloSpec *utls.ClientHelloSpec) (string, error) {
   953  
   954  	switch utlsClientHelloID {
   955  
   956  	case utls.HelloIOS_11_1, utls.HelloIOS_12_1,
   957  		utls.HelloChrome_58, utls.HelloChrome_62,
   958  		utls.HelloFirefox_55, utls.HelloFirefox_56:
   959  		return protocol.TLS_VERSION_12, nil
   960  
   961  	case utls.HelloChrome_70, utls.HelloChrome_72,
   962  		utls.HelloChrome_83, utls.HelloChrome_96,
   963  		utls.HelloChrome_102, utls.HelloFirefox_65,
   964  		utls.HelloFirefox_99, utls.HelloFirefox_105,
   965  		utls.HelloChrome_106_Shuffle, utls.HelloGolang,
   966  		utls.HelloSafari_16_0:
   967  		return protocol.TLS_VERSION_13, nil
   968  	}
   969  
   970  	// As utls.HelloRandomized/Custom may be either TLS 1.2 or TLS 1.3, we cannot
   971  	// perform a simple ClientHello ID check. BuildHandshakeState is run, which
   972  	// constructs the entire ClientHello.
   973  	//
   974  	// Assumes utlsClientHelloID.Seed has been set; otherwise the result is
   975  	// ephemeral.
   976  	//
   977  	// BenchmarkRandomizedGetClientHelloVersion indicates that this operation
   978  	// takes on the order of 0.05ms and allocates ~8KB for randomized client
   979  	// hellos.
   980  
   981  	conn := utls.UClient(
   982  		nil,
   983  		&utls.Config{InsecureSkipVerify: true},
   984  		utlsClientHelloID)
   985  
   986  	if utlsClientHelloSpec != nil {
   987  		err := conn.ApplyPreset(utlsClientHelloSpec)
   988  		if err != nil {
   989  			return "", errors.Trace(err)
   990  		}
   991  	}
   992  
   993  	err := conn.BuildHandshakeState()
   994  	if err != nil {
   995  		return "", errors.Trace(err)
   996  	}
   997  
   998  	for _, v := range conn.HandshakeState.Hello.SupportedVersions {
   999  		if v == utls.VersionTLS13 {
  1000  			return protocol.TLS_VERSION_13, nil
  1001  		}
  1002  	}
  1003  
  1004  	return protocol.TLS_VERSION_12, nil
  1005  }
  1006  
  1007  func init() {
  1008  	// Favor compatibility over security. CustomTLSDial is used as an obfuscation
  1009  	// layer; users of CustomTLSDial, including meek and remote server list
  1010  	// downloads, don't depend on this TLS for its security properties.
  1011  	utls.EnableWeakCiphers()
  1012  }