diff --git a/record_detect.go b/record_detect.go index 32ab88c..e9f72c2 100644 --- a/record_detect.go +++ b/record_detect.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "slices" "sync" "time" @@ -108,6 +109,35 @@ func (c *DetectConn) Read(b []byte) (n int, err error) { return 0, io.EOF } +func IdentifyModernFingerprint(ch *clientHelloMsg) string { + if slices.Contains(ch.supportedVersions, VersionTLS10) && slices.Contains(ch.supportedVersions, VersionTLS11) { + if slices.Contains(ch.extensions, utlsExtensionApplicationSettings) { + return "hellochrome_96" + } + return "hellochrome_87" // also hellochrome_83 + } + if slices.Contains(ch.supportedCurves, X25519MLKEM768) { + if slices.Contains(ch.extensions, utlsExtensionApplicationSettingsNew) { + return "hellochrome_133" + } + return "hellochrome_131" + } + if slices.Contains(ch.extensions, utlsExtensionECH) { + return "hellochrome_120" + } + if slices.Contains(ch.extensions, utlsExtensionPadding) { + return "hellochrome_106_shuffle" // also HelloChrome_100, HelloChrome_102 + } + return "Custom" +} + +const ( + utlsExtensionPadding uint16 = 21 + utlsExtensionApplicationSettings uint16 = 17513 // not IANA assigned + utlsExtensionApplicationSettingsNew uint16 = 17613 // not IANA assigned + utlsExtensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-17 +) + var ModernFingerprints = map[string]*utls.ClientHelloID{ // One of these will be chosen as `random` at startup "hellofirefox_99": &utls.HelloFirefox_99, diff --git a/tls.go b/tls.go index 44c9ab8..2960c96 100644 --- a/tls.go +++ b/tls.go @@ -162,8 +162,6 @@ func Value(vals ...byte) (value int) { // The configuration config must be non-nil and must include // at least one certificate or else set GetCertificate. func Server(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { - postHandshakeRecordsLens := DetectPostHandshakeRecordsLens(config, "hellochrome_131") - remoteAddr := conn.RemoteAddr().String() if config.Show { fmt.Printf("REALITY remoteAddr: %v\n", remoteAddr) @@ -374,6 +372,12 @@ func Server(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { if err != nil { break } + var fingerprint = IdentifyModernFingerprint(hs.clientHello) + fmt.Printf("REALITY remoteAddr: %v\tidentified fingerprint: %v\n", remoteAddr, fingerprint) + if fingerprint == "Custom" { + fingerprint = "hellochrome_131" + } + postHandshakeRecordsLens := DetectPostHandshakeRecordsLens(config, fingerprint) for _, length := range postHandshakeRecordsLens[hs.clientHello.serverName] { if length == 0 { break;