Назад к блогу

TLS-фингерпринтинг: как работают JA3 и JA4 и почему прокси их не меняет

TLS-фингерпринтинг: как работают JA3 и JA4 и почему прокси их не меняет

TLS-отпечаток позволяет серверу понять, какая программа открыла HTTPS-сессию, — по одному лишь первому ходу. Ещё до начала шифрования клиент сообщает, что он умеет: версии протокола, списки шифров, номера расширений, предпочтительные группы для обмена ключами. Chrome, Firefox, curl и скрипт на Python делают это каждый по-своему, узнаваемо. JA3 сворачивает эти поля в MD5-хеш, а JA4 — его преемник, которому не мешает перемешивание расширений в браузерах. Обычный прокси лишь передаёт зашифрованный поток, поэтому сайт видит отпечаток вашего клиента, а не прокси.

Разберём, что содержит ClientHello, как считаются JA3 и JA4, почему перемешивание расширений «сломало» JA3 для Chrome, как сайты используют эти значения вместе с репутацией IP и что из этого следует для тех, кто работает с HTTP-клиентами через прокси.

Резидентные прокси

Резидентные IP с точной геолокацией для доступа к региональному контенту

Попробовать

Что выдаёт ClientHello

Любое TLS-соединение начинается с того, что клиент отправляет ClientHello открытым текстом (часть данных скрывает только более новый механизм Encrypted Client Hello). Его поля определяет TLS-библиотека и её настройки, а не пользователь:

  • Версии протокола — например, TLS 1.2 в устаревшем поле и TLS 1.3 в расширении supported_versions.
  • Наборы шифров — какие именно и в какой последовательности, зависит от криптобиблиотеки: в Chrome это BoringSSL, в Firefox — NSS, а Python и большинство консольных утилит опираются на OpenSSL.
  • Расширения — имя сервера (SNI), ALPN, поддерживаемые группы, алгоритмы подписи, обмен ключами, сессионные билеты и другие.
  • Группы и форматы точек — кривые для обмена ключами вроде X25519, на которые клиент согласен.
  • Значения GREASE — случайные «заглушки» по RFC 8701, которые Chrome вставляет, чтобы серверы спокойно относились к неизвестным записям.

Два клиента, которые оба представляются свежим Chrome в User-Agent, но построены на разных библиотеках, отправляют заметно разные ClientHello. На этом разрыве и держится TLS-фингерпринтинг.

Как считается JA3

JA3 опубликовали в 2017 году трое инженеров Salesforce. Метод берёт пять полей ClientHello, записывает каждое десятичными числами через дефис, разделяет поля запятыми и хеширует результат MD5:

TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats

Значения GREASE перед хешированием выбрасываются, чтобы случайные заглушки не меняли результат. Небольшой скрипт ниже показывает идею на вымышленных значениях:

import hashlib

GREASE_SET = {0x0a0a + 0x1010 * n for n in range(16)}

def build_ja3(version, cipher_ids, ext_ids, curve_ids, point_fmts):
    def joined(values):
        return "-".join(str(v) for v in values if v not in GREASE_SET)
    raw_text = ",".join([
        str(version),
        joined(cipher_ids),
        joined(ext_ids),
        joined(curve_ids),
        joined(point_fmts),
    ])
    return raw_text, hashlib.md5(raw_text.encode()).hexdigest()

sample_hello = dict(
    version=771,
    cipher_ids=[0x2a2a, 4865, 4866, 4867, 49195, 49199],
    ext_ids=[0x3a3a, 0, 23, 65281, 10, 11, 35, 16, 13, 51, 45, 43],
    curve_ids=[29, 23, 24],
    point_fmts=[0],
)
text_form, ja3_digest = build_ja3(**sample_hello)
print(text_form)
print(ja3_digest)

Парный показатель JA3S снимает отпечаток ответа сервера (ServerHello). Вместе они помогают защитникам находить, например, вредоносные программы, которые связываются со своим управляющим сервером, — ради этого метод изначально и придумали.

Почему JA3 потерял точность: перемешивание расширений

JA3 учитывает расширения в том порядке, в котором их прислали. С выходом Chrome 110 в начале 2023 года браузеры на движке Chromium тасуют список расширений при каждом новом рукопожатии — чтобы серверы перестали опираться на одну неизменную раскладку. В итоге одна установка Chrome даёт множество разных хешей JA3: для опознания браузеров метод стал гораздо менее полезен, хотя для инструментов с фиксированным порядком — многих скриптов и библиотек — по-прежнему работает.

JA4 и семейство JA4+

В 2023 году Джон Олтхаус, один из авторов JA3, представил через свою компанию FoxIO метод JA4. В его основе два решения: списки упорядочиваются по номерам до хеширования, и перемешивание ничего не меняет, а первый сегмент остаётся понятным человеку. Значение выглядит как t13d1714h2_4f0c1a9d27be_93b2d6e1a0c4 (пример вымышленный), подчёркивания делят его на три сегмента:

ЧастьЧто внутриПример расшифровки
aЧитаемый заголовок: буква транспорта, версия протокола, передаётся ли имя хоста, двузначные счётчики шифров и расширений, метка ALPNВ t13d1714h2: t — TCP, 13 — поколение протокола, d — указан домен, далее 17 наборов шифров, 14 расширений и h2 первым в ALPN
bУкороченный до 12 знаков SHA-256 от идентификаторов шифров после сортировкиОдинаков при любом порядке, в котором клиент их перечислил
cУкороченный SHA-256 от отсортированных номеров расширений вместе со списком алгоритмов подписиНе сдвигается, когда браузер тасует расширения

Начальный фрагмент записан открытым текстом, поэтому по логам сразу понятно, что клиент работает по TLS 1.3 поверх QUIC (q) или TCP (t) либо не отправляет SNI. Семейство JA4+ добавляет отпечатки ответа сервера (JA4S), заголовков HTTP-запроса (JA4H), сертификатов (JA4X), TCP-рукопожатия (JA4T) и другие. Сам JA4 опубликован под свободной лицензией, а остальные методы JA4+ — под собственной лицензией FoxIO, поэтому перед коммерческим использованием её стоит прочитать.

Стопка прозрачных слоёв над ноутбуком: слой сетевых пакетов, слой защищённого рукопожатия и слой запроса приложения, каждый оставляет свой маленький опознавательный штамп
TLS — лишь один из слоёв, по которым снимают отпечаток; серверы сравнивают их между собой

Другие слои: HTTP/2 и TCP

TLS редко проверяют в одиночку. Рядом обычно смотрят ещё два сигнала:

  • Отпечаток HTTP/2. Значения SETTINGS, размер WINDOW_UPDATE, данные о приоритетах и порядок псевдозаголовков у браузеров и библиотек различаются. Метод, популяризированный Akamai, кодирует их в короткую строку.
  • Отпечаток TCP/IP. Начальный размер окна, TTL и опции TCP выдают операционную систему. Если IP принадлежит прокси, эти значения описывают ОС прокси-сервера, а не вашу, — одна из причин, по которой сайты сравнивают слои, а не доверяют одному.

Эти слои — родственники браузерных сигналов вроде canvas и WebGL; о них подробно в материале о фингерпринтинге браузера.

Почему прокси не меняет TLS-отпечаток

Большинство прокси пропускают TLS, не вмешиваясь в него:

  • HTTP-прокси с методом CONNECT открывает до сайта «сырой» TCP-туннель, а рукопожатие TLS через него выполняет ваш клиент.
  • SOCKS5-прокси делает то же на более низком уровне — разница объяснена в статье SOCKS5 или HTTP.

В обоих случаях до сайта доходит тот ClientHello, который сформировала ваша программа. Сайт видит IP прокси вместе с TLS-отпечатком вашего клиента. Исключение — перехватывающий прокси, который завершает TLS у себя и открывает новое соединение: корпоративные шлюзы инспекции трафика или отладочные инструменты. Тогда сайт видит отпечаток программы прокси. Разница между туннелированием и перехватом разобрана в материале об SSL/HTTPS-прокси.

Устройство клиента отправляет запечатанный конверт через посредника, который меняет только внешний адресный ярлык, а печать и содержимое доходят до сервера нетронутыми
Туннелирующий прокси меняет видимый адрес, но не рукопожатие: сервер по-прежнему видит отпечаток исходного клиента

Как сайты используют TLS-отпечатки

Системы защиты от ботов и CDN, включая Bot Management от Cloudflare, передают значения JA3 и JA4 в свои правила и модели. Типичные сценарии:

  • Проверка согласованности. Запрос, который в User-Agent называет себя Chrome, а приходит с отпечатком Python-библиотеки или curl, противоречив, и это расхождение весит больше, чем каждое значение по отдельности.
  • Каталоги известных инструментов. Отпечатки популярных HTTP-библиотек, сканеров и семейств вредоносного ПО собраны в базы и получают оценку риска.
  • Белые списки. Партнёров и сервисы мониторинга с известным отпечатком можно пропускать мимо лимитов.
  • Кластеризация. Множество IP с одним редким отпечатком и одинаковым поведением указывают на одного оператора — поэтому одна лишь ротация адресов автоматизацию не скрывает.

Полная картина уровней защиты, от репутации IP до поведения, — в обзоре о том, как сайты распознают ботов.

Что это значит для автоматизации через прокси

TLS-отпечатки — ещё один довод в пользу того, что ответственный сбор данных начинается с разрешения, а не с маскировки:

  • Сначала официальные API и выгрузки. Они рассчитаны на программных клиентов, и отпечатки там роли не играют.
  • Уважайте блокировки и проверки. Если защита сайта останавливает ваш клиент, это сигнал снизить темп, запросить доступ или взять другой источник. О темпе, кешировании и других вежливых практиках — в статье о том, как снизить риск блокировок при парсинге.
  • Свои сервисы тестируйте настоящими браузерами. Для мониторинга и QA собственных сайтов фреймворки, управляющие полноценным браузером, дают подлинное браузерное рукопожатие. Существуют и библиотеки, воспроизводящие рукопожатие браузеров, их применяют в тестировании, но использование их для обхода защиты чужого сайта может нарушать его условия.
  • Прокси — для маршрута и локации. Прокси определяет, откуда выходит трафик, что важно для геозависимого контента; выдавать себя за другой клиент он не должен и не умеет. Наши резидентные прокси созданы для доступа с точной геолокацией, а не для подмены программы, которой вы пользуетесь.

Как посмотреть собственный отпечаток

  1. Wireshark. Запишите трафик, отфильтруйте по tls.handshake.type == 1 и откройте ClientHello. Свежие версии показывают значения JA3 и JA4 в деталях рукопожатия.
  2. Тестовые страницы-эхо. Некоторые публичные страницы просто показывают посетителю хеши его рукопожатия и параметры HTTP/2. Загрузите такую страницу один раз обычным браузером, второй — своей программой и положите результаты рядом.
  3. Журналы на своей инфраструктуре. Пограничные серверы и сети доставки контента способны записывать JA3 или JA4 для каждого запроса, и по ним видно, какие клиентские стеки заходят на ваш сайт.
Wireshark: TLS Client Hello по фильтру tls.handshake.ja3, выделены отпечатки JA3 и JA4
Wireshark показывает строки JA3 и JA4 у Client Hello

Частые вопросы о TLS-фингерпринтинге

Что такое отпечаток JA3?

JA3 — это 32-символьная MD5-строка, собранная из пяти значений рукопожатия: версии протокола, шифров, номеров расширений, групп и форматов точек. По ней узнают программный стек и его настройки, но не отдельного пользователя.

Чем JA3 отличается от JA4?

JA4 упорядочивает шифры и расширения до хеширования, так что значение остаётся прежним у браузеров, тасующих расширения, а начинается оно с фрагмента, понятного без расшифровки. У FoxIO есть и родственные методы — для HTTP-заголовков, ответов сервера, сертификатов и TCP.

Меняет ли прокси или VPN TLS-отпечаток?

Туннелирующие прокси и VPN — нет: они меняют IP, а рукопожатие формирует ваша программа. Собственный отпечаток показывают только перехватывающие прокси, которые завершают TLS у себя.

Могут ли сайты блокировать по TLS-отпечатку?

Да, многие системы защиты от ботов используют JA3 или JA4 как один из сигналов, особенно если он противоречит User-Agent. Обычно его сочетают с репутацией IP, данными HTTP/2 и поведением.

Законен ли TLS-фингерпринтинг?

Метод анализирует технические параметры, которые клиент открыто отправляет при рукопожатии, и широко применяется для безопасности и борьбы с мошенничеством. Законность конкретного применения зависит от местных правил о персональных данных и от того, с какой информацией эти данные сопоставляют.