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 }