// Engineering Log

HTTP, HTTPS и TLS: Часть 8 — Что такое JA3 и JA4: отпечатки TLS-клиента

Опубликовано 12.10.2026

// Быстрый маршрут

Эта статья относится к теме Безопасность и защита.

JA3 и JA4 — способы получить короткий отпечаток (fingerprint) TLS-клиента по его первому сообщению ClientHello. Разные программы — Chrome, Firefox, curl, библиотека Python requests, Go-клиент, вредоносная программа — формируют ClientHello по-своему: предлагают разный набор шифров, расширений, групп обмена ключами в разном порядке. Из этих полей складывается строка, строка хешируется, и получается идентификатор, одинаковый для всех копий одной программы и разный для разных программ. Отпечаток вычисляется до расшифровки трафика и без участия клиента, поэтому его используют для защиты от ботов, поиска вредоносных программ в сети и в системах DPI.

Главное отличие от заголовка User-Agent: User-Agent пишет сам клиент, и скрипт легко представится браузером Chrome. Отпечаток TLS определяется библиотекой, которая устанавливает соединение, и если скрипт на Python называет себя Chrome, а ClientHello у него от OpenSSL, это несоответствие видно сразу.

Что попадает в ClientHello

ClientHello отправляется открытым текстом (если не используется ECH) и содержит:

  • версию протокола и список поддерживаемых версий;
  • список шифронаборов в порядке предпочтения;
  • список расширений: SNI, ALPN, supported_groups, signature_algorithms, key_share, session_ticket и десяток других;
  • группы обмена ключами (эллиптические кривые): x25519, secp256r1, X25519MLKEM768;
  • алгоритмы подписи;
  • протоколы ALPN: h2, http/1.1.

Всё это задаёт TLS-библиотека (BoringSSL в Chrome, NSS в Firefox, OpenSSL в curl и Python, crypto/tls в Go) и её настройки в приложении.

JA3

JA3 предложили в 2017 году исследователи Salesforce (Джон Альтхаус, Джефф Аткинсон, Джош Аткинс — по первым буквам имён). Строка JA3 состоит из пяти полей ClientHello, записанных десятичными числами через запятую, а значения внутри поля — через дефис:

Версия,Шифры,Расширения,Группы,Форматы_точек
771,4865-4866-4867-49195-49199-...,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0

Отпечаток — MD5 от этой строки: 32 шестнадцатеричных символа, например 375c6162a492dfbf2795909110ce8424. Значения GREASE (специальные «пустышки», которые браузеры вставляют, чтобы серверы не ломались на незнакомых значениях) при подсчёте отбрасываются.

Для ответа сервера существует JA3S — по полям ServerHello. Пара JA3 + JA3S хорошо выделяет конкретные вредоносные программы и их управляющие серверы: одна и та же программа, подключающаяся к одному и тому же серверному ПО, всегда даёт одну пару.

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

JA4

JA4 предложил в 2023 году Джон Альтхаус, уже в компании FoxIO. Отпечаток читается человеком, устойчив к перемешиванию расширений и учитывает QUIC.

Пример для Chrome:

t13d1516h2_8daaf6152771_e5627efa2ab1

Три части через подчёркивание.

Часть a — описание, читается без расшифровки:

СимволыЗначениеПример
1транспорт: t — TLS поверх TCP, q — QUIC, d — DTLSt
2–3версия TLS: максимальная из supported_versions13 — TLS 1.3
4d — есть SNI (подключение по имени), i — SNI нет (по IP)d
5–6число шифронаборов без GREASE15
7–8число расширений без GREASE16
9–10первая и последняя буква первого протокола ALPN, 00 — ALPN нетh2

Часть b — первые 12 символов SHA-256 от списка шифров, отсортированных по значению. Порядок, в котором клиент их прислал, не важен.

Часть c — первые 12 символов SHA-256 от отсортированного списка расширений (без SNI и ALPN — они уже учтены в части a) и списка алгоритмов подписи в исходном порядке.

Сортировка решает проблему Chrome: перемешивание расширений отпечаток не меняет. А раздельные части позволяют искать частичные совпадения: например, все клиенты с тем же набором шифров (одинаковая часть b), но другими расширениями.

Для отладки есть «сырые» варианты: JA4_r — те же списки без хеширования, JA4_o — в исходном порядке, без сортировки.

Семейство JA4+. Кроме JA4 для клиента TLS, FoxIO описали:

  • JA4S — ответ сервера (ServerHello);
  • JA4H — HTTP-клиент: метод, версия, наличие cookie и Referer, число заголовков, их порядок, язык;
  • JA4X — способ, которым сгенерирован сертификат X.509;
  • JA4L — задержка и расстояние до клиента;
  • JA4T, JA4TS — параметры TCP (размер окна, опции);
  • JA4SSH — сессии SSH.

Лицензия. Сам JA4 распространяется по лицензии BSD 3-Clause, как и JA3. Остальные методы JA4+ — под лицензией FoxIO License 1.1: их можно бесплатно использовать для защиты собственной компании и в исследованиях, но производителю, который продаёт продукт с этими отпечатками, нужна коммерческая лицензия.

Где используются отпечатки

Защита от ботов. Cloudflare, Akamai, AWS WAF и другие системы защиты сверяют отпечаток с заявленным User-Agent и с базой известных клиентов. Скрипт на Python с User-Agent браузера получает капчу или 403. Cloudflare даёт использовать поля cf.bot_management.ja3_hash и cf.bot_management.ja4 в правилах WAF на тарифах с Bot Management.

Отпечаток HTTP/2. Помимо TLS, клиентов различают по параметрам HTTP/2: значениям в кадре SETTINGS, размеру окна, приоритетам и порядку псевдозаголовков. Такой отпечаток называют «отпечатком Akamai» по имени компании, опубликовавшей метод.

Обнаружение вредоносных программ. Системы обнаружения вторжений (Suricata, Zeek) вычисляют JA3/JA4 для каждого соединения, и аналитик ищет отпечатки известных вредоносных программ и инструментов вроде Cobalt Strike, не расшифровывая трафик.

DPI и блокировки. Оборудование фильтрации по отпечатку ClientHello отличает браузер от VPN-клиента или прокси, которые используют TLS для маскировки. Поэтому современные инструменты обхода блокировок (Xray с протоколом REALITY, sing-box) не формируют ClientHello сами, а копируют отпечаток браузера через библиотеку uTLS.

Инвентаризация. В корпоративной сети по отпечаткам видно, какие программы выходят в интернет: устаревшие библиотеки TLS, неожиданные клиенты, самописные скрипты.

Подмена отпечатка

Отпечаток определяется библиотекой TLS, поэтому подменить его можно только другой библиотекой или её настройками:

  • uTLS — библиотека для Go, которая формирует ClientHello байт в байт как у выбранного браузера;
  • curl-impersonate — сборка curl с BoringSSL и настройками, повторяющими Chrome, и с NSS — повторяющими Firefox, включая отпечаток HTTP/2 и порядок заголовков;
  • curl_cffi — обёртка над curl-impersonate для Python.

Смена User-Agent, заголовков или прокси отпечаток не меняет. И наоборот: полное совпадение с браузером по TLS при несовпадении по HTTP/2, порядку заголовков или поведению JavaScript тоже обнаруживается. Отпечатки — один из признаков, а не окончательный вердикт: за одним JA4 стоят миллионы одинаковых браузеров, и отличить по нему конкретного пользователя нельзя.

Как узнать свой отпечаток

Через сервис. Откройте в браузере или запросите curl’ом https://tls.peet.ws/api/all — сервис вернёт JSON с отпечатками вашего клиента: tls.ja3, tls.ja3_hash, tls.ja4, tls.ja4_r и отпечаток HTTP/2 http2.akamai_fingerprint_hash.

bash
curl -s https://tls.peet.ws/api/all | python3 -c \
  'import json,sys; d=json.load(sys.stdin); print(d["tls"]["ja3_hash"], d["tls"]["ja4"], d["http_version"])'

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

КлиентJA3JA4Протокол
curl 8.7.1, macOS (LibreSSL)375c6162…t13d497h2_0d8feac7bc37_7395dae3b2f3h2
curl 8.22, Alpine (OpenSSL 3.5)446fb8bd…t13d3012h2_1d37bd780c83_882d495ac381h2
Python urllib, macOS (OpenSSL 3)4bdac5ab…t13d1713h1_ab0a1bf427ad_89ab6efea773HTTP/1.1
Python requests, Debian (OpenSSL 3)86dab210…t13d1713h1_ab0a1bf427ad_8537cf56674eHTTP/1.1
Node.js 26, fetch98384658…t13d5212h1_b262b3658495_8e6e362c5each2
Go 1.27, net/http03117a8e…t13d1312h2_f57a46bbacb6_f50d94e863ebh2
curl-impersonate, профиль Chrome 116меняется: 0ea31aef…, 97ca64e9…t13d1516h2_8daaf6152771_e5627efa2ab1h2

Что видно из таблицы:

  • у каждого клиента свой отпечаток, и User-Agent на него не влияет. Скрипт на Python, который назовётся Chrome, всё равно покажет t13d1713h1_…;
  • часть a читается без справочника: Python предлагает 17 шифров и 13 расширений и первым в ALPN ставит http/1.1 (h1), Go — 13 шифров и 12 расширений и h2; curl на macOS с LibreSSL предлагает 49 шифров, включая устаревшие;
  • одинаковая часть b у Python urllib и requests (ab0a1bf427ad) — один и тот же набор шифров OpenSSL; различие в части c — разные расширения и алгоритмы подписи в разных сборках;
  • JA3 у профиля Chrome меняется при каждом запросе, а JA4 остаётся тем же t13d1516h2_8daaf6152771_e5627efa2ab1, что приведён в спецификации JA4 как пример отпечатка Chrome. Так и выглядит перемешивание расширений;
  • сервис считает не идеально: у curl на macOS в части a стоит 497 вместо 4907 — число расширений не дополнено нулём до двух знаков. Сравнивая отпечатки из разных источников, проверяйте, одинаково ли они их считают.

Откройте ту же страницу в своём браузере несколько раз подряд — JA3 будет меняться, JA4 нет.

В Wireshark. Начиная с версии 4.2, Wireshark вычисляет отпечатки сам. В разобранном ClientHello есть поля tls.handshake.ja3, tls.handshake.ja3_full и tls.handshake.ja4; их можно добавить как колонку и фильтровать:

tls.handshake.ja4 == "t13d1516h2_8daaf6152771_e5627efa2ab1"

Из командной строки:

bash
tshark -r capture.pcap -Y 'tls.handshake.type == 1' \
  -T fields -e ip.src -e tls.handshake.extensions_server_name -e tls.handshake.ja4

На своём сервере. Nginx отпечатки не вычисляет, для этого есть сторонние модули и отдельные прокси (например, fingerproxy — обратный прокси на Go, передающий JA3, JA4 и отпечаток HTTP/2 приложению в заголовках). На сайтах за Cloudflare отпечатки доступны в правилах WAF и журналах на тарифах с Bot Management.

Когда использовать и когда нет

Отпечатки полезны:

  • в правилах WAF против автоматизированных запросов, когда User-Agent заявляет браузер, а отпечаток — библиотеку;
  • в расследованиях инцидентов: поиск всех соединений одного инструмента по сети;
  • для разрешения доступа к API только определённым клиентам внутри компании (как дополнительный признак, а не единственный).

Не стоит на них полагаться:

  • как на аутентификацию — отпечаток подделывается;
  • для блокировки по «чёрному списку» отпечатков без проверки: у популярной библиотеки один JA4 на миллионы легитимных клиентов, и вместе с ботом вы заблокируете, например, всех пользователей мобильного приложения на этой библиотеке;
  • для слежения за конкретным пользователем — отпечаток описывает программу, а не человека.

Типичные ошибки

  • Правила на JA3 для браузеров после 2023 года — отпечаток Chrome и Firefox меняется при каждом соединении.
  • Отпечатки считаются на сервере за CDN или балансировщиком, который сам принимает TLS, — вы видите отпечаток балансировщика, а не клиента.
  • Блокировка по отпечатку после обновления клиентской библиотеки у ваших же пользователей — новые версии OpenSSL и браузеров меняют набор расширений (например, с появлением X25519MLKEM768).

// Похожая задача

Если у вас похожая ситуация

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

Тема статьи

Безопасность и защита

SSL, hardening, доступы, защита сервисов и безопасные конфигурации.

Часто с этим приходят

  • Настроить SSL, сертификаты и безопасные подключения
  • Ограничить доступы и закрыть лишние точки входа
  • Усилить конфигурацию сервера и сервисов

// Следующий шаг

Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.

Открыть услуги

// Contact

Нужна помощь?

Свяжись со мной и я помогу решить проблему

Написать в Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Подтвердите, что вы не бот.

Написать и получить быстрый ответ