// 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 — DTLS | t |
| 2–3 | версия TLS: максимальная из supported_versions | 13 — TLS 1.3 |
| 4 | d — есть SNI (подключение по имени), i — SNI нет (по IP) | d |
| 5–6 | число шифронаборов без GREASE | 15 |
| 7–8 | число расширений без GREASE | 16 |
| 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.
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 года, по три запроса от каждого клиента:
| Клиент | JA3 | JA4 | Протокол |
|---|---|---|---|
| curl 8.7.1, macOS (LibreSSL) | 375c6162… | t13d497h2_0d8feac7bc37_7395dae3b2f3 | h2 |
| curl 8.22, Alpine (OpenSSL 3.5) | 446fb8bd… | t13d3012h2_1d37bd780c83_882d495ac381 | h2 |
| Python urllib, macOS (OpenSSL 3) | 4bdac5ab… | t13d1713h1_ab0a1bf427ad_89ab6efea773 | HTTP/1.1 |
| Python requests, Debian (OpenSSL 3) | 86dab210… | t13d1713h1_ab0a1bf427ad_8537cf56674e | HTTP/1.1 |
Node.js 26, fetch | 98384658… | t13d5212h1_b262b3658495_8e6e362c5eac | h2 |
Go 1.27, net/http | 03117a8e… | t13d1312h2_f57a46bbacb6_f50d94e863eb | h2 |
| curl-impersonate, профиль Chrome 116 | меняется: 0ea31aef…, 97ca64e9… | t13d1516h2_8daaf6152771_e5627efa2ab1 | h2 |
Что видно из таблицы:
- у каждого клиента свой отпечаток, и
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"Из командной строки:
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)
Или оставьте заявку здесь:
// Related