Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new ClientHellos #122

Merged
merged 2 commits into from Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion common.go
Expand Up @@ -96,7 +96,6 @@ const (
extensionSignatureAlgorithmsCert uint16 = 50
extensionKeyShare uint16 = 51
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionALPS uint16 = 17513
gaukas marked this conversation as resolved.
Show resolved Hide resolved
extensionRenegotiationInfo uint16 = 0xff01
)

Expand Down
38 changes: 35 additions & 3 deletions u_common.go
Expand Up @@ -23,7 +23,11 @@ const (
utlsExtensionCompressCertificate uint16 = 27

// extensions with 'fake' prefix break connection, if server echoes them back
fakeExtensionChannelID uint16 = 30032 // not IANA assigned
fakeExtensionTokenBinding uint16 = 24
fakeExtensionChannelIDOld uint16 = 30031 // not IANA assigned
fakeExtensionChannelID uint16 = 30032 // not IANA assigned
fakeExtensionALPS uint16 = 17513 // not IANA assigned
fakeExtensionDelegatedCredentials uint16 = 34

fakeRecordSizeLimit uint16 = 0x001c

Expand All @@ -44,16 +48,25 @@ const (

FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = uint16(0x0033)
FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = uint16(0x0039)
FAKE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = uint16(0x009f)
FAKE_TLS_RSA_WITH_RC4_128_MD5 = uint16(0x0004)
FAKE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = uint16(0x009f)
FAKE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = uint16(0x0032)
FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = uint16(0x006b)
FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = uint16(0x0067)
FAKE_TLS_EMPTY_RENEGOTIATION_INFO_SCSV = uint16(0x00ff)

// https://docs.microsoft.com/en-us/dotnet/api/system.net.security.tlsciphersuite?view=netcore-3.1
FAKE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = uint16(0xc008)
)

// newest signatures
var (
FakePKCS1WithSHA224 SignatureScheme = 0x0301
FakeECDSAWithSHA224 SignatureScheme = 0x0303

FakeSHA1WithDSA SignatureScheme = 0x0202
FakeSHA256WithDSA SignatureScheme = 0x0402

// fakeEd25519 = SignatureAndHash{0x08, 0x07}
// fakeEd448 = SignatureAndHash{0x08, 0x08}
)
Expand Down Expand Up @@ -109,6 +122,10 @@ const (
helloChrome = "Chrome"
helloIOS = "iOS"
helloAndroid = "Android"
helloEdge = "Edge"
helloSafari = "Safari"
hello360 = "360Browser"
helloQQ = "QQBrowser"

// versions
helloAutoVers = "0"
Expand Down Expand Up @@ -146,13 +163,14 @@ var (
HelloRandomizedNoALPN = ClientHelloID{helloRandomizedNoALPN, helloAutoVers, nil}

// The rest will will parrot given browser.
HelloFirefox_Auto = HelloFirefox_102
HelloFirefox_Auto = HelloFirefox_105
HelloFirefox_55 = ClientHelloID{helloFirefox, "55", nil}
HelloFirefox_56 = ClientHelloID{helloFirefox, "56", nil}
HelloFirefox_63 = ClientHelloID{helloFirefox, "63", nil}
HelloFirefox_65 = ClientHelloID{helloFirefox, "65", nil}
HelloFirefox_99 = ClientHelloID{helloFirefox, "99", nil}
HelloFirefox_102 = ClientHelloID{helloFirefox, "102", nil}
HelloFirefox_105 = ClientHelloID{helloFirefox, "105", nil}

HelloChrome_Auto = HelloChrome_102
HelloChrome_58 = ClientHelloID{helloChrome, "58", nil}
Expand All @@ -172,6 +190,20 @@ var (
HelloIOS_14 = ClientHelloID{helloIOS, "14", nil}

HelloAndroid_11_OkHttp = ClientHelloID{helloAndroid, "11", nil}

HelloEdge_Auto = HelloEdge_85 // HelloEdge_106 seems to be incompatible with this library
HelloEdge_85 = ClientHelloID{helloEdge, "85", nil}
HelloEdge_106 = ClientHelloID{helloEdge, "106", nil}

HelloSafari_Auto = HelloSafari_16_0
HelloSafari_16_0 = ClientHelloID{helloSafari, "16.0", nil}

Hello360_Auto = Hello360_7_5 // Hello360_11_0 seems to be incompatible with this library
Hello360_7_5 = ClientHelloID{hello360, "7.5", nil}
Hello360_11_0 = ClientHelloID{hello360, "11.0", nil}

HelloQQ_Auto = HelloQQ_11_1
HelloQQ_11_1 = ClientHelloID{helloQQ, "11.1", nil}
)

// based on spec's GreaseStyle, GREASE_PLACEHOLDER may be replaced by another GREASE value
Expand Down
61 changes: 58 additions & 3 deletions u_fingerprinter.go
Expand Up @@ -318,8 +318,63 @@ func (f *Fingerprinter) FingerprintClientHello(data []byte) (*ClientHelloSpec, e
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &UtlsCompressCertExtension{methods})

case fakeExtensionChannelID, fakeRecordSizeLimit:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &GenericExtension{extension, extData})
case fakeExtensionChannelID:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeChannelIDExtension{})

case fakeExtensionChannelIDOld:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeChannelIDExtension{true})

case fakeExtensionTokenBinding:
var tokenBindingExt FakeTokenBindingExtension
var keyParameters cryptobyte.String
if !extData.ReadUint8(&tokenBindingExt.MajorVersion) ||
!extData.ReadUint8(&tokenBindingExt.MinorVersion) ||
!extData.ReadUint8LengthPrefixed(&keyParameters) {
return nil, errors.New("unable to read token binding extension data")
}
tokenBindingExt.KeyParameters = keyParameters
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &tokenBindingExt)

case fakeExtensionALPS:
// Similar to ALPN (RFC 7301, Section 3.1):
// https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps#section-3
var protoList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
return nil, errors.New("unable to read ALPS extension data")
}
supportedProtocols := []string{}
for !protoList.Empty() {
var proto cryptobyte.String
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
return nil, errors.New("unable to read ALPS extension data")
}
supportedProtocols = append(supportedProtocols, string(proto))
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &ApplicationSettingsExtension{supportedProtocols})

case fakeRecordSizeLimit:
recordSizeExt := new(FakeRecordSizeLimitExtension)
if !extData.ReadUint16(&recordSizeExt.Limit) {
return nil, errors.New("unable to read record size limit extension data")
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, recordSizeExt)

case fakeExtensionDelegatedCredentials:
//https://datatracker.ietf.org/doc/html/draft-ietf-tls-subcerts-15#section-4.1.1
var supportedAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&supportedAlgs) || supportedAlgs.Empty() {
return nil, errors.New("unable to read signature algorithms extension data")
}
supportedSignatureAlgorithms := []SignatureScheme{}
for !supportedAlgs.Empty() {
var sigAndAlg uint16
if !supportedAlgs.ReadUint16(&sigAndAlg) {
return nil, errors.New("unable to read signature algorithms extension data")
}
supportedSignatureAlgorithms = append(
supportedSignatureAlgorithms, SignatureScheme(sigAndAlg))
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeDelegatedCredentialsExtension{supportedSignatureAlgorithms})

case extensionPreSharedKey:
// RFC 8446, Section 4.2.11
Expand Down Expand Up @@ -351,7 +406,7 @@ func (f *Fingerprinter) FingerprintClientHello(data []byte) (*ClientHelloSpec, e
} else if f.AllowBluntMimicry {
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &GenericExtension{extension, extData})
} else {
return nil, fmt.Errorf("unsupported extension %#x", extension)
return nil, fmt.Errorf("unsupported extension %d", extension)
gaukas marked this conversation as resolved.
Show resolved Hide resolved
}

continue
Expand Down