TLS-фингерпринтинг и хеши JA4: как это работает
Почему сообщения TLS Client Hello — золотая жила для идентификации устройств и как хеши JA4 дают стабильный отпечаток, переживающий обновления браузеров.
Каждое HTTPS-соединение начинается с TLS-рукопожатия, а оно, в свою очередь, — с сообщения Client Hello. Это сообщение содержит массу информации о клиенте — наборы шифров, расширения, поддерживаемые кривые, алгоритмы подписи, — которая заметно различается между браузерами, версиями и ОС. TLS-фингерпринтинг фиксирует эти данные и использует их как сигнал идентификации.
Что содержится в Client Hello?
Когда браузер подключается к HTTPS-серверу, он отправляет сообщение Client Hello, содержащее: поддерживаемую им версию TLS, список наборов шифров, которые он готов использовать, включённые TLS-расширения (такие как SNI, ALPN и key share), поддерживаемые эллиптические кривые, принимаемые алгоритмы подписи и предлагаемые методы сжатия.
У каждого семейства браузеров есть свой характерный отпечаток. Chrome, Firefox и Safari отправляют разный порядок наборов шифров, разные наборы расширений и разные предпочтения по кривым. Даже внутри одного семейства разные версии могут слегка различаться в Client Hello по мере добавления или устаревания наборов шифров.
От JA3 к JA4
JA3 был первым хешем TLS-фингерпринтинга, представленным Salesforce в 2017 году. Он объединяет версию TLS, наборы шифров, расширения, эллиптические кривые и форматы точек EC в строку и вычисляет MD5-хеш. Будучи новаторским, JA3 имеет ограничения: он выдаёт единственный непрозрачный хеш, который трудно анализировать, и малейшее изменение любого поля даёт совершенно другой хеш.
JA4, представленный FoxIO в 2023 году, улучшает JA3 сразу в нескольких аспектах. Он выдаёт структурированный отпечаток из трёх компонентов: человекочитаемый префикс (например, «t13d1715h2» — TLS 1.3, 17 наборов шифров, 15 расширений, HTTP/2), упорядоченный хеш наборов шифров и упорядоченный хеш расширений. Такая структура делает отпечатки JA4 читаемыми с первого взгляда, сохраняя точность, нужную для идентификации.
Почему TLS-отпечатки важны для device intelligence
TLS-отпечатки ценны тем, что собираются до того, как выполнится хоть какой-то JavaScript. Бот, который подделывает свой user agent, фальсифицирует рендеринг canvas и правит свойства navigator, всё равно отправляет подлинное сообщение Client Hello от той TLS-библиотеки, которую использует на самом деле. Если Client Hello говорит «библиотека crypto/tls в Go», а user agent — «Chrome 124», мы знаем, что что-то подделано.
Такая перекрёстная проверка крайне мощна для обнаружения ботов. Большинство фреймворков автоматизации — Selenium, Puppeteer, Playwright — используют нативный TLS-стек браузера, поэтому их отпечатки совпадают с браузером, которым они управляют. Но кастомные HTTP-клиенты, скраперы на Go и Python-скрипты, использующие библиотеку requests, имеют характерные TLS-отпечатки, которые мгновенно выдают в них небраузерных клиентов.
Стабильность TLS-отпечатка
Одна из проблем TLS-фингерпринтинга — стабильность при обновлениях браузера. Когда Chrome добавляет или удаляет набор шифров, TLS-отпечаток меняется. На практике это происходит реже, чем можно было бы ожидать. Список наборов шифров в Chrome относительно стабилен — крупные изменения случаются раз или два в год, а не с каждой версией.
Структурированный формат JA4 здесь помогает. Человекочитаемый префикс остаётся стабильным между минорными изменениями версий (количество наборов шифров и расширений меняется нечасто), поэтому даже когда детальный хеш меняется, префикс обеспечивает преемственность. В нашей многоуровневой системе идентификации данные TLS-отпечатка попадают на уровень Tier 2 — достаточно стабильные, чтобы вносить вклад в идентификацию, но обрабатываемые через межсессионное сопоставление для учёта ожидаемого дрейфа.
Сбор на стороне сервера
В отличие от клиентских сигналов, требующих выполнения JavaScript, TLS-отпечатки собираются полностью на стороне сервера. Наши edge-серверы инспектируют сырое TLS-рукопожатие и извлекают Client Hello до установления соединения. Это означает, что TLS-фингерпринтинг работает, даже когда JavaScript заблокирован, когда в браузере установлены расширения для приватности или когда клиент вообще не браузер.
Серверная природа также делает TLS-отпечатки устойчивыми к подмене. Теоретически можно сконструировать кастомный TLS Client Hello под конкретный браузер, но для этого нужно реализовать TLS на низком уровне — гораздо больше усилий, чем изменить строку user agent. Большинство инструментов подмены даже не пытаются это делать.
Интеграция с идентификацией устройств
В нашем движке идентификации устройств TLS-отпечаток служит одновременно и сигналом, и валидатором. Как сигнал, он вносит вклад в общий отпечаток устройства со своим весом идентификации. Как валидатор, он даёт перекрёстную проверку заявленной идентичности браузера. Если JavaScript-сигналы говорят «Chrome на macOS», а TLS-отпечаток — «Firefox на Linux», это расхождение поднимает флаг подделки в нашем анализе Smart Signals.