Post

JA4 TLS Fingerprinting: TLS 핸드셰이크로 봇 트래픽을 식별하는 방법

JA4 TLS Fingerprinting: TLS 핸드셰이크로 봇 트래픽을 식별하는 방법

WAF에서 IP 기반 rate limit, managed rules, JavaScript Challenge를 차례로 배치했는데도 curl이나 Python requests로 만든 단순 스크래핑 봇이 계속 들어온다면, TLS 핸드셰이크 단계에서 클라이언트의 정체를 식별하는 방법을 검토할 시점이다. JA4는 TLS Client Hello 패킷을 기반으로 클라이언트 소프트웨어의 핑거프린트를 생성하는 기법으로, IP 주소나 User-Agent 없이도 클라이언트가 어떤 TLS 라이브러리를 사용하는지 구별할 수 있다.

AWS WAF는 2025년 3월부터 JA4 fingerprint를 request component로 지원하며, rate-based rule의 aggregation key로도 사용할 수 있다. Cloudflare, CloudFront, Google Cloud Armor 등 주요 플랫폼에서도 JA4를 지원한다. 이 글에서는 JA4가 어떻게 핑거프린트를 생성하고, 기존 봇 완화 기법과 어떻게 조합하는지를 공식 문서와 실제 설정 기준으로 정리한다.


1. JA3에서 JA4로: 왜 새로운 핑거프린팅이 필요했는가

TLS 클라이언트 핑거프린팅은 Client Hello 패킷에 포함된 cipher suite, extension, TLS 버전 등의 조합으로 클라이언트를 식별하는 기법이다. 최초의 널리 쓰인 구현체는 JA3로, 2017년 Salesforce의 John Althouse가 개발했다. JA3는 Client Hello의 cipher, extension, elliptic curve, elliptic curve point format을 나타나는 순서대로 이어 붙이고 MD5 해시를 생성했다.

JA3가 동작하던 시절에는 브라우저와 TLS 라이브러리가 Client Hello 필드를 일관된 순서로 배치했다. 하지만 2023년 Google Chrome은 Client Hello의 extension 순서를 난수화하는 변경을 적용했다. 이 변경으로 동일한 Chrome 브라우저가 연결할 때마다 다른 JA3 해시를 생성하게 됐고, JA3 기반의 핑거프린트 데이터베이스와 WAF 규칙이 무력화됐다. Cipher suite 순서를 의도적으로 섞는 cipher stunting 기법도 같은 문제를 일으켰다.

JA4는 같은 원작자가 FoxIO에서 2023년 9월에 발표한 후속 표준이다. 핵심 차이는 cipher와 extension을 Client Hello에 나타나는 순서가 아닌 hex 값 기준으로 정렬한 뒤 해시를 생성한다는 점이다. Chrome이 extension 순서를 난수화하더라도 정렬 후 해시하면 동일한 핑거프린트가 나온다. 해시 알고리즘도 MD5에서 SHA-256으로 변경하고, 해시 결과를 12자리로 truncate한다.

구분JA3JA4
발표2017 (Salesforce)2023-09 (FoxIO)
정렬Client Hello 순서 보존cipher, extension hex 기준 정렬
해시MD5SHA-256 (truncate 12 chars)
포맷단일 해시 문자열human-readable prefix + 두 해시 segment
유지보수archived (중단)활발 (2026-07 기준 2,038 stars)
Chrome extension 랜덤화우회 불가정렬로 우회

JA3 저장소는 현재 “no longer being actively maintained”로 표시되어 있으며, 원작자가 FoxIO에서 JA4로 개발을 이어가고 있다.


2. JA4 핑거프린트 구조

JA4 핑거프린트는 사람이 읽을 수 있는 prefix와 두 개의 해시 segment로 구성된다. 다음은 실제 핑거프린트의 예시다.

1
t13d1516h2_8daaf6152771_b186095e22b6

이 문자열을 분해하면 각 부분이 의미를 갖는다.

2.1. Prefix: t13d1516h2

위치의미
첫 글자t프로토콜 (q=QUIC, d=DTLS, t=TLS over TCP)
두 번째13TLS 버전 (10=1.0, 11=1.1, 12=1.2, 13=1.3)
세 번째dSNI 있음 (d=domain present, i=IP absent)
네 번째15cipher 개수 (GREASE 제외)
다섯 번째16extension 개수 (GREASE, SNI, ALPN 제외)
여섯 번째h2첫 번째 ALPN 값 (h2, http/1.1, spdy/3.1 등)

2.2. Cipher hash: 8daaf6152771

cipher suite 목록을 hex 값 기준으로 정렬한 뒤 연결하고, SHA-256 해시의 앞 12자리를 취한다. GREASE 값은 제거한다.

2.3. Extension hash: b186095e22b6

extension 목록에서 SNI(0x0000)와 ALPN(0x0010)을 제거한 뒤 hex 기준으로 정렬한다. 여기에 정렬하지 않은 signature algorithms extension 목록을 그대로 append한 후 SHA-256 해시의 앞 12자리를 취한다.

SNI와 ALPN을 extension 해시에서 제외하는 이유는, 같은 애플리케이션이 다른 도메인이나 IP로 연결할 때 핑거프린트가 변하지 않도록 하기 위해서다. 핑거프린트는 클라이언트 소프트웨어의 정체를 식별하는 것이 목적이지, 연결 대상을 식별하는 것이 아니기 때문이다.


3. JA4+ 제품군: TLS 너머의 핑거프린팅

FoxIO는 JA4(TLS Client) 외에도 TLS 이외의 계층을 핑거프린팅하는 JA4+ 제품군을 제공한다.

핑거프린트대상설명
JA4TLS Client Hello클라이언트 TLS 핑거프린트
JA4STLS Server Hello서버 응답 핑거프린트, session 특성 식별
JA4HHTTP ClientHTTP 요청 헤더 기반 핑거프린트 (Cookie, Referer 제외)
JA4LLatency클라이언트-서버 간 지연 시간 측정, VPN/Proxy 탐지
JA4XX.509 CertificateTLS 인증서 핑거프린팅
JA4SSHSSH TrafficSSH 세션 핑거프린팅
JA4TTCP ClientTCP 특성 기반 OS 핑거프린팅

라이선스는 JA4(TLS Client)만 BSD 3-Clause 오픈소스이며, JA4+ 제품군(JA4S, JA4H, JA4L, JA4X, JA4SSH, JA4T, JA4D)은 FoxIO License 1.1을 따른다. 상업적 OEM 사용은 별도 라이선스가 필요하며, detection logic은 patent pending이다.


4. AWS WAF에서 JA4 활용하기

AWS WAF는 2023년 9월에 JA3 fingerprint match를 지원한 데 이어, 2025년 3월에 JA4 fingerprinting을 추가했다. 같은 업데이트에서 rate-based rule의 aggregation key로 JA3와 JA4 fingerprint를 사용할 수 있게 됐다.

4.1. fingerprint request component

AWS WAF rule statement에서 JA3 fingerprint와 JA4 fingerprint를 request component로 사용할 수 있다. fingerprint 값은 byte match statement의 match inspect 대상으로 지정한다.

1
2
3
4
5
Match statement:
  Inspect: JA4 fingerprint
  Match type: Starts with string
  Match string: t13d
  Text transformation: None

위 예시는 TLS 1.3 Client Hello를 보내는 클라이언트를 매칭한다. 핑거프린트의 prefix는 사람이 읽을 수 있으므로, 특정 TLS 버전이나 프로토콜을 가진 클라이언트를 조건으로 사용할 수 있다.

4.2. rate-based rule aggregation key

rate-based rule에서 aggregation key를 IP가 아닌 JA4 fingerprint로 지정하면, 동일한 TLS 핑거프린트를 가진 요청을 하나의 그룹으로 묶어 rate limit을 적용할 수 있다. NAT나 프로xy 뒤에서 여러 IP로 분산되는 봇 팜을 IP 기반 rate limit로 잡기 어려울 때 특히 유용하다.

IP 기반 rate limit가 “하나의 IP에서 100 req/min”을 감지한다면, JA4 기반 aggregation은 “알려진 봇 도구 핑거프린트에서 오는 모든 요청이 100 req/min”을 감지한다. 봇이 IP를 순환하더라도 핑거프린트가 같으면 같은 그룹으로 집계된다.

4.3. CloudFront에서 JA4 헤더 받기

Amazon CloudFront는 2024년 10월부터 JA4 fingerprinting을 지원한다. CloudFront 로그의 tls_client_ja4 필드에서 핑거프린트를 확인할 수 있으며, origin으로 전달하는 HTTP 헤더에도 포함된다.

CloudFront 앞에 AWS WAF를 배치한 구조라면, WAF rule에서 JA4 fingerprint를 직접 inspect할 수 있다. CloudFront에서 WAF로 전달되는 요청에 fingerprint가 이미 계산되어 있기 때문에 별도 전처리가 필요 없다.


5. 다른 플랫폼에서의 JA4 지원

플랫폼지원 범위비고
AWS WAFJA3, JA4 request component + rate aggregation2025-03 추가
Amazon CloudFrontJA4 로그 필드, HTTP 헤더2024-10 추가
CloudflareJA3/JA4 + JA4 SignalsEnterprise + Bot Management 필요
Google Cloud ArmorJA4 기반 allow/deny rule 
Azure Front DoorJA4 HTTP 헤더 
VercelJA4 fingerprint 
FastlyVCL 변수 tls.client.ja4요청 시 활성화 필요
AkamaiJA4 설정 API 
NGINXFoxIO 공식 모듈 (개발 중단)known bugs, 프로덕션 비권장
HAProxy커뮤니티 Lua 플러그인HAProxy 3.1+ 필요

Cloudflare의 경우 JA4를 Enterprise 플랜과 Bot Management 구독자에게만 제공한다. Free, Pro, Business 플랜에서는 JA3/JA4 fingerprint 필드를 사용할 수 없다. Cloudflare Workers 환경에서는 JA4 Signals라는 inter-request 통계 배열을 통해 핑거프린트 기반 분석이 가능하다.

NGINX 모듈은 FoxIO 공식 저장소에 있으나 README에 “Development for JA4 on Nginx has been on pause”라고 명시되어 있으며, known bugs가 존재해 프로덕션 환경에서 사용하기 어렵다.


6. 기존 봇 완화 기법과 JA4의 관계

이 블로그의 WAF 연재에서 다룬 JavaScript Challenge, CAPTCHA, managed rules와 JA4는 서로 다른 계층에서 클라이언트를 검증한다. JA4는 이 계층 구조에서 TLS 레이어의 신호를 추가한다.

기법검증 계층JA4와의 관계
IP rate limitL3/L4 (요청 빈도)JA4 aggregation이 IP 순환 봇에 더 정확
Managed RulesL7 (시그니처)JA4는 managed rules가 탐지하지 못하는 미확인 도구 식별
JavaScript ChallengeL7 (실행 검증)보완적. JS Challenge를 통과한 봇도 TLS 핑거프린트로 추가 식별
CAPTCHAL7 (사람 검증)JA4는 사전 필터. 의심 핑거프린트에만 CAPTCHA를 제시해 UX 개선

실제 다층 방어 배치를 구성한다면 다음 순서를 고려할 수 있다.

1
2
IP rate limit -> Managed Rules -> JA4 fingerprint filter -> JS Challenge -> CAPTCHA
(L3/L4)         (L7 signature)   (L7 TLS signal)           (L7 execution)  (L7 human)

JA4 fingerprint filter가 앞단에서 알려진 봇 도구의 핑거프린트를 rate limit이나 차단하고, 통과한 요청은 JS Challenge와 CAPTCHA로 추가 검증한다. 각 계층이 서로 다른 신호를 사용하므로 한 계층을 우회해도 다른 계층이 보완한다.


7. 한계와 운영 주의사항

JA4 핑거프린팅은 봇 완화 도구 중 하나의 신호일 뿐, 단독으로 사용하면 안 된다. 운영에서 반드시 고려해야 할 한계가 있다.

핑거프린트 가변성: 클라이언트의 TLS 라이브러리가 업데이트되면 핑거프린트가 변한다. Chrome, Firefox 등 주요 브라우저는 대략 연 1회 TLS 스택을 업데이트하며, 이때 cipher나 extension 구성이 바뀌어 새 핑거프린트가 생성된다. 핑거프린트를 정적 블록리스트로 관리한다면 주기적인 갱신이 필요하다.

Session Resumption: TLS 세션 재개(session resumption, session ticket)를 사용하는 연결에서는 두 번째 요청부터 Client Hello가 생략된다. 이 경우 핑거프린트가 계산되지 않아 WAF rule에서 빈 값으로 처리된다. Cloudflare 문서에서도 session resumption 시 fingerprint가 absent됨을 명시하고 있다.

비암호화 트래픽: HTTP(평문) 연결에서는 TLS 핸드셰이크 자체가 없으므로 핑거프린트가 존재하지 않는다. HTTPS 리다이렉트 전의 첫 요청이나 HTTP-to-HTTPS 업그레이드 시나리오에서는 주의가 필요하다.

정상 트래픽과의 중복: cURL, Python requests, Go net/http 같은 정상적인 프로그래밍 도구와 봇 도구가 같은 TLS 라이브러리를 사용하면 동일한 핑거프린트를 갖는다. 핑거프린트가 같다고 해서 무조건 봇으로 차단하면 정상 사용자의 API 클라이언트나 모니터링 도구도 차단된다.

uTLS 등 위조 기법: 정교한 봇은 실제 브라우저의 Client Hello를 모방하는 uTLS 라이브러리를 사용해 핑거프린트를 위조할 수 있다. 이 경우 브라우저와 동일한 핑거프린트를 가지므로 JA4만으로 구별이 불가능하다.

이러한 한계 때문에 JA4는 rate limit, JS Challenge, behavioral 분석과 조합해 사용해야 한다. 핑거프린트는 하나의 신호(signal)이며, 단독으로 봇 여부를 판단하는 판정 기준이 아니다.


8. 분석 도구

JA4 핑거프린트를 직접 관찰하려면 다음 도구를 사용할 수 있다.

도구지원 범위설치
WiresharkJA4+ 전체 (JA4, JA4S, JA4H, JA4L, JA4X, JA4SSH, JA4T)Wireshark 4.4.0+, FoxIO plugin
ZeekJA4+ 전체Zeek 5+ (zkg install zeek/foxio/ja4), QUIC은 6+
ArkimeJA4+기본 지원
tsharkJA4+Wireshark CLI, tshark -T fields -e tls.handshake.ja4
GreyNoiseJA4+threat intelligence 플랫폼
CensysJA4+인터넷 스캔 데이터

FoxIO는 앱별 핑거프린트 데이터베이스인 JA4DB(ja4db.com)를 운영한다. 관측한 핑거프린트가 어떤 클라이언트 소프트웨어에 해당하는지 조회할 수 있다.


9. 정리: 다층 봇 완화 전략에서 JA4의 위치

봇 완화는 단일 기법으로 완료되는 문제가 아니다. IP rate limit, managed rules, JA4 fingerprint, JavaScript Challenge, CAPTCHA 각각이 서로 다른 계층에서 서로 다른 신호를 사용한다. JA4는 그중 TLS 핸드셰이크를 기반으로 클라이언트 소프트웨어의 정체를 식별하는 계층이다.

AWS WAF에서 JA4를 도입할 때 권장하는 접근은 차단부터 시작하지 않고 관찰부터 하는 것이다. WAF rule action을 Count로 설정해 며칠간 JA4 fingerprint 로그를 수집하고, 정상 트래픽의 핑거프린트 분포를 파악한 뒤 이상 패턴을 식별한다. 그 후 의심 핑거프린트에 대해서만 rate-based rule이나 challenge action을 적용한다.

핑거프린트는 클라이언트 소프트웨어가 업데이트되면 변하므로, 블록리스트를 만들었다면 정기적으로 갱신해야 한다. Session resumption, HTTP 평문 트래픽, uTLS 위조 등 핑거프린트가 계산되지 않거나 위조되는 시나리오를 WAF rule에 명시적으로 처리하는 것도 잊지 않아야 한다.


10. Reference

궁금하신 점이나 추가해야 할 부분은 댓글이나 아래의 링크를 통해 문의해주세요.
Written with KKamJi

This post is licensed under CC BY 4.0 by the author.