Explorar el Código

Provisional support for iOS 12.1 and Chrome 72

Rod Hynes hace 7 años
padre
commit
e0d427040a

+ 6 - 2
psiphon/common/protocol/protocol.go

@@ -195,23 +195,27 @@ const (
 	TLS_VERSION_13 = "TLSv1.3"
 
 	TLS_PROFILE_IOS_111    = "iOS-11.1"
+	TLS_PROFILE_IOS_121    = "iOS-12.1"
 	TLS_PROFILE_CHROME_58  = "Chrome-58"
 	TLS_PROFILE_CHROME_62  = "Chrome-62"
 	TLS_PROFILE_CHROME_70  = "Chrome-70"
+	TLS_PROFILE_CHROME_72  = "Chrome-72"
 	TLS_PROFILE_FIREFOX_55 = "Firefox-55"
 	TLS_PROFILE_FIREFOX_56 = "Firefox-56"
-	TLS_PROFILE_FIREFOX_63 = "Firefox-63"
+	TLS_PROFILE_FIREFOX_65 = "Firefox-65"
 	TLS_PROFILE_RANDOMIZED = "Randomized-v2"
 )
 
 var SupportedTLSProfiles = TLSProfiles{
 	TLS_PROFILE_IOS_111,
+	TLS_PROFILE_IOS_121,
 	TLS_PROFILE_CHROME_58,
 	TLS_PROFILE_CHROME_62,
 	TLS_PROFILE_CHROME_70,
+	TLS_PROFILE_CHROME_72,
 	TLS_PROFILE_FIREFOX_55,
 	TLS_PROFILE_FIREFOX_56,
-	TLS_PROFILE_FIREFOX_63,
+	TLS_PROFILE_FIREFOX_65,
 	TLS_PROFILE_RANDOMIZED,
 }
 

+ 6 - 2
psiphon/tlsDialer.go

@@ -174,18 +174,22 @@ func getUTLSClientHelloID(tlsProfile string) utls.ClientHelloID {
 	switch tlsProfile {
 	case protocol.TLS_PROFILE_IOS_111:
 		return utls.HelloIOS_11_1
+	case protocol.TLS_PROFILE_IOS_121:
+		return utls.HelloIOS_12_1
 	case protocol.TLS_PROFILE_CHROME_58:
 		return utls.HelloChrome_58
 	case protocol.TLS_PROFILE_CHROME_62:
 		return utls.HelloChrome_62
 	case protocol.TLS_PROFILE_CHROME_70:
 		return utls.HelloChrome_70
+	case protocol.TLS_PROFILE_CHROME_72:
+		return utls.HelloChrome_72
 	case protocol.TLS_PROFILE_FIREFOX_55:
 		return utls.HelloFirefox_55
 	case protocol.TLS_PROFILE_FIREFOX_56:
 		return utls.HelloFirefox_56
-	case protocol.TLS_PROFILE_FIREFOX_63:
-		return utls.HelloFirefox_63
+	case protocol.TLS_PROFILE_FIREFOX_65:
+		return utls.HelloFirefox_65
 	case protocol.TLS_PROFILE_RANDOMIZED:
 		return utls.HelloRandomized
 	default:

+ 3 - 1
vendor/github.com/refraction-networking/utls/README.md

@@ -65,9 +65,11 @@ This is not a problem, if you fully control the server and turn unsupported thin
 | ------------- | -------- | ---------- | ---------------------- | --------------------------------------------- |
 | Chrome 62     | no       | no         | ChannelID              | [0a4a74aeebd1bb66](https://tlsfingerprint.io/id/0a4a74aeebd1bb66) |
 | Chrome 70     | no       | no         | ChannelID, Encrypted Certs | [bc4c7e42f4961cd7](https://tlsfingerprint.io/id/bc4c7e42f4961cd7) |
+| Chrome 72     | no       | no         | ChannelID, Encrypted Certs | [bbf04e5f1881f506](https://tlsfingerprint.io/id/bbf04e5f1881f506) |
 | Firefox 56    | very low | no         | None                   | [c884bad7f40bee56](https://tlsfingerprint.io/id/c884bad7f40bee56) |
-| Firefox 63    | very low | no         | MaxRecordSize                   | [6bfedc5d5c740d58](https://tlsfingerprint.io/id/6bfedc5d5c740d58) |
+| Firefox 65    | very low | no         | MaxRecordSize                   | [6bfedc5d5c740d58](https://tlsfingerprint.io/id/6bfedc5d5c740d58) |
 | iOS 11.1      | low** | no         | None                   | [71a81bafd58e1301](https://tlsfingerprint.io/id/71a81bafd58e1301) |
+| iOS 12.1      | low** | no         | None                   | [ec55e5b4136c7949](https://tlsfingerprint.io/id/ec55e5b4136c7949) |
 
 \* Denotes very rough guesstimate of likelihood that unsupported things will get echoed back by the server in the wild,
 *visibly breaking the connection*.  

+ 23 - 7
vendor/github.com/refraction-networking/utls/u_common.go

@@ -58,8 +58,21 @@ var (
 	FakeFFDHE3072 = uint16(0x0101)
 )
 
+// https://tools.ietf.org/html/draft-ietf-tls-certificate-compression-04
+type CertCompressionAlgo uint16
+
+const (
+	CertCompressionZlib   CertCompressionAlgo = 0x0001
+	CertCompressionBrotli CertCompressionAlgo = 0x0002
+)
+
+const (
+	PskModePlain uint8 = pskModePlain
+	PskModeDHE   uint8 = pskModeDHE
+)
+
 type ClientHelloID struct {
-	Client  string
+	Client string
 
 	// Version specifies version of a mimicked clients (e.g. browsers).
 	// Not used in randomized, custom handshake, and default Go.
@@ -99,8 +112,8 @@ type ClientHelloSpec struct {
 	CompressionMethods []uint8        // nil => no compression
 	Extensions         []TLSExtension // nil => no extensions
 
-	TLSVersMin uint16 // [1.0-1.3]
-	TLSVersMax uint16 // [1.2-1.3]
+	TLSVersMin uint16 // [1.0-1.3] default: parse from .Extensions, if SupportedVersions ext is not present => 1.0
+	TLSVersMax uint16 // [1.2-1.3] default: parse from .Extensions, if SupportedVersions ext is not present => 1.2
 
 	// GreaseStyle: currently only random
 	// sessionID may or may not depend on ticket; nil => random
@@ -126,18 +139,21 @@ var (
 	HelloRandomizedNoALPN = ClientHelloID{helloRandomizedNoALPN, helloAutoVers, nil}
 
 	// The rest will will parrot given browser.
-	HelloFirefox_Auto = HelloFirefox_63
+	HelloFirefox_Auto = HelloFirefox_65
 	HelloFirefox_55   = ClientHelloID{helloFirefox, "55", nil}
 	HelloFirefox_56   = ClientHelloID{helloFirefox, "56", nil}
 	HelloFirefox_63   = ClientHelloID{helloFirefox, "63", nil}
+	HelloFirefox_65   = ClientHelloID{helloFirefox, "65", nil}
 
-	HelloChrome_Auto = HelloChrome_70
+	HelloChrome_Auto = HelloChrome_72
 	HelloChrome_58   = ClientHelloID{helloChrome, "58", nil}
 	HelloChrome_62   = ClientHelloID{helloChrome, "62", nil}
 	HelloChrome_70   = ClientHelloID{helloChrome, "70", nil}
+	HelloChrome_72   = ClientHelloID{helloChrome, "72", nil}
 
-	HelloIOS_Auto = HelloIOS_11_1
-	HelloIOS_11_1 = ClientHelloID{helloIOS, "111", nil}
+	HelloIOS_Auto = HelloIOS_12_1
+	HelloIOS_11_1 = ClientHelloID{helloIOS, "111", nil} // legacy "111" means 11.1
+	HelloIOS_12_1 = ClientHelloID{helloIOS, "12.1", nil}
 )
 
 // based on spec's GreaseStyle, GREASE_PLACEHOLDER may be replaced by another GREASE value

+ 45 - 1
vendor/github.com/refraction-networking/utls/u_conn.go

@@ -481,7 +481,51 @@ func (uconn *UConn) GetOutKeystream(length int) ([]byte, error) {
 }
 
 // SetVersCreateState set min and max TLS version in all appropriate places.
-func (uconn *UConn) SetTLSVers(minTLSVers, maxTLSVers uint16) error {
+// If minTLSVers == 0 && minTLSVers == 0,
+// SetTLSVers() will try to parse to parse the version from extensions.
+func (uconn *UConn) SetTLSVers(minTLSVers, maxTLSVers uint16, extensions []TLSExtension) error {
+	if minTLSVers == 0 && maxTLSVers == 0 {
+		// if version is not set explicitly in the ClientHelloSpec, check the SupportedVersions extension
+		supportedVersionsExtensionsPresent := 0
+		for _, e := range extensions {
+			switch ext := e.(type) {
+			case *SupportedVersionsExtension:
+				supportedVersionsExtensionsPresent += 1
+				findVersionsInSupportedVersionsExtensions := func(versions []uint16) (uint16, uint16) {
+					// returns (minVers, maxVers)
+					minVers := uint16(0)
+					maxVers := uint16(0)
+					for _, vers := range versions {
+						if vers == GREASE_PLACEHOLDER {
+							continue
+						}
+						if maxVers < vers || maxVers == 0 {
+							maxVers = vers
+						}
+						if minVers > vers || minVers == 0 {
+							minVers = vers
+						}
+					}
+					return minVers, maxVers
+				}
+				minTLSVers, maxTLSVers = findVersionsInSupportedVersionsExtensions(ext.Versions)
+				if minTLSVers == 0 && maxTLSVers == 0 {
+					return fmt.Errorf("SupportedVersions extension has invalid Versions field")
+				} // else: proceed
+			}
+		}
+		switch supportedVersionsExtensionsPresent {
+		case 0:
+			// just default to 1.2, if extension, that is mandatory for 1.3 is not present
+			minTLSVers = VersionTLS10
+			maxTLSVers = VersionTLS12
+		case 1:
+		default:
+			return fmt.Errorf("uconn.Extensions contains %v separate SupportedVersions extensions",
+				supportedVersionsExtensionsPresent)
+		}
+	}
+
 	if minTLSVers < VersionTLS10 || minTLSVers > VersionTLS12 {
 		return fmt.Errorf("uTLS does not support 0x%X as min version", minTLSVers)
 	}

+ 141 - 8
vendor/github.com/refraction-networking/utls/u_parrots.go

@@ -133,7 +133,81 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
 					CurveP256,
 					CurveP384,
 				}},
-				&GenericExtension{id: fakeCertCompressionAlgs, data: []byte{02, 00, 02}},
+				&FakeCertCompressionAlgsExtension{[]CertCompressionAlgo{CertCompressionBrotli}},
+				&UtlsGREASEExtension{},
+				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
+			},
+		}, nil
+	case HelloChrome_72:
+		return ClientHelloSpec{
+			CipherSuites: []uint16{
+				GREASE_PLACEHOLDER,
+				TLS_AES_128_GCM_SHA256,
+				TLS_AES_256_GCM_SHA384,
+				TLS_CHACHA20_POLY1305_SHA256,
+				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+				TLS_RSA_WITH_AES_256_CBC_SHA,
+				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+			},
+			CompressionMethods: []byte{
+				0x00, // compressionNone
+			},
+			Extensions: []TLSExtension{
+				&UtlsGREASEExtension{},
+				&SNIExtension{},
+				&UtlsExtendedMasterSecretExtension{},
+				&RenegotiationInfoExtension{renegotiation: RenegotiateOnceAsClient},
+				&SupportedCurvesExtension{[]CurveID{
+					CurveID(GREASE_PLACEHOLDER),
+					X25519,
+					CurveP256,
+					CurveP384,
+				}},
+				&SupportedPointsExtension{SupportedPoints: []byte{
+					0x00, // pointFormatUncompressed
+				}},
+				&SessionTicketExtension{},
+				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
+				&StatusRequestExtension{},
+				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
+					ECDSAWithP256AndSHA256,
+					PSSWithSHA256,
+					PKCS1WithSHA256,
+					ECDSAWithP384AndSHA384,
+					PSSWithSHA384,
+					PKCS1WithSHA384,
+					PSSWithSHA512,
+					PKCS1WithSHA512,
+					PKCS1WithSHA1,
+				}},
+				&SCTExtension{},
+				&KeyShareExtension{[]KeyShare{
+					{Group: CurveID(GREASE_PLACEHOLDER), Data: []byte{0}},
+					{Group: X25519},
+				}},
+				&PSKKeyExchangeModesExtension{[]uint8{
+					PskModeDHE,
+				}},
+				&SupportedVersionsExtension{[]uint16{
+					GREASE_PLACEHOLDER,
+					VersionTLS13,
+					VersionTLS12,
+					VersionTLS11,
+					VersionTLS10,
+				}},
+				&FakeCertCompressionAlgsExtension{[]CertCompressionAlgo{
+					CertCompressionBrotli,
+				}},
 				&UtlsGREASEExtension{},
 				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
 			},
@@ -186,7 +260,7 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
 			},
 			GetSessionID: nil,
 		}, nil
-	case HelloFirefox_63:
+	case HelloFirefox_63, HelloFirefox_65:
 		return ClientHelloSpec{
 			TLSVersMin: VersionTLS10,
 			TLSVersMax: VersionTLS13,
@@ -254,7 +328,7 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
 					PKCS1WithSHA1,
 				}},
 				&PSKKeyExchangeModesExtension{[]uint8{pskModeDHE}},
-				&GenericExtension{id: fakeRecordSizeLimit, data: []byte{0x40, 0x01}},
+				&FakeRecordSizeLimitExtension{0x4001},
 				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
 			}}, nil
 	case HelloIOS_11_1:
@@ -316,6 +390,68 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
 				}},
 			},
 		}, nil
+	case HelloIOS_12_1:
+		return ClientHelloSpec{
+			CipherSuites: []uint16{
+				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+				DISABLED_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+				TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				DISABLED_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+				DISABLED_TLS_RSA_WITH_AES_256_CBC_SHA256,
+				TLS_RSA_WITH_AES_128_CBC_SHA256,
+				TLS_RSA_WITH_AES_256_CBC_SHA,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+				0xc008,
+				TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+			},
+			CompressionMethods: []byte{
+				compressionNone,
+			},
+			Extensions: []TLSExtension{
+				&RenegotiationInfoExtension{renegotiation: RenegotiateOnceAsClient},
+				&SNIExtension{},
+				&UtlsExtendedMasterSecretExtension{},
+				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
+					ECDSAWithP256AndSHA256,
+					PSSWithSHA256,
+					PKCS1WithSHA256,
+					ECDSAWithP384AndSHA384,
+					ECDSAWithSHA1,
+					PSSWithSHA384,
+					PSSWithSHA384,
+					PKCS1WithSHA384,
+					PSSWithSHA512,
+					PKCS1WithSHA512,
+					PKCS1WithSHA1,
+				}},
+				&StatusRequestExtension{},
+				&NPNExtension{},
+				&SCTExtension{},
+				&ALPNExtension{AlpnProtocols: []string{"h2", "h2-16", "h2-15", "h2-14", "spdy/3.1", "spdy/3", "http/1.1"}},
+				&SupportedPointsExtension{SupportedPoints: []byte{
+					pointFormatUncompressed,
+				}},
+				&SupportedCurvesExtension{[]CurveID{
+					X25519,
+					CurveP256,
+					CurveP384,
+					CurveP521,
+				}},
+			},
+		}, nil
 	default:
 		return ClientHelloSpec{}, errors.New("ClientHello ID " + id.Str() + " is unknown")
 	}
@@ -349,7 +485,8 @@ func (uconn *UConn) applyPresetByID(id ClientHelloID) (err error) {
 // same ClientHelloSpec. It is advised to use different specs and avoid any shared state.
 func (uconn *UConn) ApplyPreset(p *ClientHelloSpec) error {
 	var err error
-	err = uconn.SetTLSVers(p.TLSVersMin, p.TLSVersMax)
+
+	err = uconn.SetTLSVers(p.TLSVersMin, p.TLSVersMax, p.Extensions)
 	if err != nil {
 		return err
 	}
@@ -640,10 +777,6 @@ func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
 	r.rand.Shuffle(len(p.Extensions), func(i, j int) {
 		p.Extensions[i], p.Extensions[j] = p.Extensions[j], p.Extensions[i]
 	})
-	err = uconn.SetTLSVers(p.TLSVersMin, p.TLSVersMax)
-	if err != nil {
-		return p, err
-	}
 
 	return p, nil
 }

+ 91 - 28
vendor/github.com/refraction-networking/utls/u_tls_extensions.go

@@ -392,32 +392,6 @@ func (e *GenericExtension) Read(b []byte) (int, error) {
 	return e.Len(), io.EOF
 }
 
-/*
-FAKE EXTENSIONS
-*/
-
-type FakeChannelIDExtension struct {
-}
-
-func (e *FakeChannelIDExtension) writeToUConn(uc *UConn) error {
-	return nil
-}
-
-func (e *FakeChannelIDExtension) Len() int {
-	return 4
-}
-
-func (e *FakeChannelIDExtension) Read(b []byte) (int, error) {
-	if len(b) < e.Len() {
-		return 0, io.ErrShortBuffer
-	}
-	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
-	b[0] = byte(fakeExtensionChannelID >> 8)
-	b[1] = byte(fakeExtensionChannelID & 0xff)
-	// The length is 0
-	return e.Len(), io.EOF
-}
-
 type UtlsExtendedMasterSecretExtension struct {
 }
 
@@ -712,5 +686,94 @@ func (e *CookieExtension) Read(b []byte) (int, error) {
 	return e.Len(), io.EOF
 }
 
-// TODO: FakeCertificateCompressionAlgorithmsExtension
-// TODO: FakeRecordSizeLimitExtension
+/*
+FAKE EXTENSIONS
+*/
+
+type FakeChannelIDExtension struct {
+}
+
+func (e *FakeChannelIDExtension) writeToUConn(uc *UConn) error {
+	return nil
+}
+
+func (e *FakeChannelIDExtension) Len() int {
+	return 4
+}
+
+func (e *FakeChannelIDExtension) Read(b []byte) (int, error) {
+	if len(b) < e.Len() {
+		return 0, io.ErrShortBuffer
+	}
+	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
+	b[0] = byte(fakeExtensionChannelID >> 8)
+	b[1] = byte(fakeExtensionChannelID & 0xff)
+	// The length is 0
+	return e.Len(), io.EOF
+}
+
+type FakeCertCompressionAlgsExtension struct {
+	Methods []CertCompressionAlgo
+}
+
+func (e *FakeCertCompressionAlgsExtension) writeToUConn(uc *UConn) error {
+	return nil
+}
+
+func (e *FakeCertCompressionAlgsExtension) Len() int {
+	return 4 + 1 + (2 * len(e.Methods))
+}
+
+func (e *FakeCertCompressionAlgsExtension) Read(b []byte) (int, error) {
+	if len(b) < e.Len() {
+		return 0, io.ErrShortBuffer
+	}
+	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
+	b[0] = byte(fakeCertCompressionAlgs >> 8)
+	b[1] = byte(fakeCertCompressionAlgs & 0xff)
+
+	extLen := 2 * len(e.Methods)
+	if extLen > 255 {
+		return 0, errors.New("too many certificate compression methods")
+	}
+
+	b[2] = byte((extLen + 1) >> 8)
+	b[3] = byte((extLen + 1) & 0xff)
+	b[4] = byte(extLen)
+
+	i := 5
+	for _, compMethod := range e.Methods {
+		b[i] = byte(compMethod >> 8)
+		b[i+1] = byte(compMethod)
+		i += 2
+	}
+	return e.Len(), io.EOF
+}
+
+type FakeRecordSizeLimitExtension struct {
+	Limit uint16
+}
+
+func (e *FakeRecordSizeLimitExtension) writeToUConn(uc *UConn) error {
+	return nil
+}
+
+func (e *FakeRecordSizeLimitExtension) Len() int {
+	return 6
+}
+
+func (e *FakeRecordSizeLimitExtension) Read(b []byte) (int, error) {
+	if len(b) < e.Len() {
+		return 0, io.ErrShortBuffer
+	}
+	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
+	b[0] = byte(fakeRecordSizeLimit >> 8)
+	b[1] = byte(fakeRecordSizeLimit & 0xff)
+
+	b[2] = byte(0)
+	b[3] = byte(2)
+
+	b[4] = byte(e.Limit >> 8)
+	b[5] = byte(e.Limit & 0xff)
+	return e.Len(), io.EOF
+}