How_to_align_with_TLS_fingerprinting

새로운 보안 과제는 안티봇 조치의 발전을 이끌며, 때로는 정당한 스크래퍼도 그 여파에 휘말립니다. 그중 하나인 TLS 핑거프린팅은 서버에 연결하려는 기기를 식별하는 교묘하고 아직 널리 알려지지 않았지만 상당히 효과적인 방법입니다. 왜 이 방법은 쉽게 우회하기 어렵고, 필요한 데이터를 성공적으로 스크래핑하려면 무엇을 해야 하는지 이 글에서 모두 알려드립니다.

TLS란 무엇인가요?

TLS 핑거프린팅을 이해하려면 먼저 TLS 자체를 살펴보아야 합니다. TLS 또는 전송 계층 보안(이전 명칭은 SSL, Secure Sockets Layer)은 표준 HTTP 연결 위에서 작동하며 온라인 활동을 보호하는 프로토콜입니다. URL 옆에 자물쇠 표시가 있거나 웹사이트 주소가 https로 시작한다면 TLS가 활성화되어 있다는 뜻입니다. 실제로 TLS를 사용하지 않는 웹사이트를 찾기는 이제 어렵습니다. 단순히 “http”(“s” 제외)로 시작하는 웹사이트에 접속하려 하면, 브라우저는 웹페이지로 리디렉션하는 대신 안전하지 않은 연결이라는 경고를 표시합니다.

TLS는 데이터를 대상 서버로 보내기 전에 암호화합니다. 즉 9823h4brjhvbi처럼 무작위 기호 문자열로 바꾸므로, 악의적인 행위자가 정보를 가로채더라도 이를 사용할 수 없습니다. 하지만 데이터를 보내기 전에 TLS는 정보를 정당한 서버로 보내는지 확인해야 하며, 서버는 이를 해독해야 합니다. 따라서 TLS는 데이터를 전송하기 전에 먼저 연결을 수립합니다. 대상 서버와 일련의 메시지를 교환하여 서버를 검증하고, 암호화 방식을 합의하며, 통신 중 데이터를 보호하고 해독하는 데 도움이 될 공유 세션 키를 생성합니다.

이 전체 과정을 TLS 핸드셰이크라고 하며, “ClientHello” 메시지로 시작합니다. TLS 핑거프린팅 관점에서 중요한 것은 바로 이 메시지입니다. 서버가 이후 사용자를 식별하는 데 쓰는 데이터의 출처이기 때문입니다.

“ClientHello” 메시지는 무엇으로 구성되나요?

“ClientHello” 메시지에는 자격 증명과 같은 민감한 데이터가 없고 암호화되지 않은 형식으로 전송되므로, Wireshark 같은 네트워크 분석 도구로 쉽게 캡처하고 내용을 확인할 수 있습니다. 여기에는 많은 데이터가 담겨 있습니다.

  • TLS 버전: 클라이언트가 지원하는 가장 높은 버전입니다.
  • 무작위 값: 클라이언트가 생성한 무작위 숫자입니다.
  • 세션 ID: 재개된 세션에 사용되므로 첫 번째 핸드셰이크에서는 비어 있습니다.
  • 암호화 스위트: 클라이언트가 지원하는 암호화 알고리즘으로, 선호 순서대로 나열됩니다.
  • 압축 방식: 오늘날에는 거의 항상 0입니다.
  • 지원 확장 기능: 클라이언트가 사용하려 할 수 있는 추가 기능입니다. 예시는 다음과 같습니다.
  • Server Name Indication(SNI): 클라이언트가 요청하는 호스트 이름을 지정합니다.
  • Application-Layer Protocol Negotiation(ALPN) 프로토콜: TLS를 통해 처리할 프로토콜을 협상하는 확장 기능입니다. 애플리케이션 계층에 독립적이어서 효과적입니다. 일반적으로 웹 서버용 TLS 확장은 HTTP/1.1 또는 HTTP/2입니다.
  • TLS 라이브러리: 클라이언트마다 서로 다른 라이브러리를 사용하므로, 클라이언트가 사용하는 라이브러리 범위입니다.
  • 서명 알고리즘: 서버 신원을 검증하기 위해 지원되는 알고리즘 목록입니다.
  • 타원 곡선: 암호화 통신은 유한체 위의 곡선 방정식을 사용하므로, 이 부분은 사용할 곡선을 나타냅니다.
  • 타원 곡선 점 형식: 점을 인코딩하는 방식을 알려줍니다.

다른 확장 기능도 있습니다. 이 모든 정보를 통해 웹사이트는 “ClientHello” 메시지에서 브라우저 계열, 기기 유형, 보안 상태 등의 소프트웨어 스택을 비롯한 상당한 양의 데이터를 추론할 수 있습니다.

JA3 핑거프린팅 방법

서버가 “ClientHello” 메시지를 받았습니다. 다음은 무엇일까요? 여기서 JA3 기법이 사용됩니다. Salesforce가 관리하는 이 방식은 가장 널리 사용되는 핑거프린팅 솔루션입니다. 메시지의 다섯 가지 핵심 구성 요소, 즉 TLS 버전, 암호화 스위트, 확장 ID, 지원 그룹(타원 곡선), 타원 곡선 점 형식에 중점을 둡니다. 각 부분은 십진수 형식으로 변환되어 쉼표와 하이픈으로 연결됩니다. 다만 실제 핑거프린트 데이터는 긴 문자열이므로 편의를 위해 암호학적 해시 함수인 MD5를 사용합니다. MD5는 고정된 128비트 해시를 생성합니다. 이후 브라우저는 이 결과를 다른 핑거프린트 후보, 흔히 내부 데이터베이스의 후보와 비교합니다. 때로는 공개 데이터베이스도 사용합니다.

목표는 차이를 찾아내는 것입니다. 이 클라이언트가 일반적인 웹 브라우저처럼 보이는지, 아니면 의심스러운 점이 있는지를 판단합니다. 문제는 Chrome 같은 일반 웹 브라우저 또는 웹 스크래핑에 쓰이는 프로그래밍 라이브러리가 생성하는 해시는 각각의 ClientHello 메시지가 다르기 때문에 서로 다르다는 점입니다. JA3 알고리즘은 소수의 변수만 고려하므로 고유한 핑거프린트 옵션이 많지 않아 일반 사용자와 스크래핑 봇을 비교적 쉽게 구별할 수 있습니다.

이로써 TLS 핑거프린팅이 스크래퍼를 막는 데 효과적이며 웹 스크래핑에 의존하는 사람들에게 큰 골칫거리임을 알 수 있습니다.

JA3 핑거프린트 후보를 수집하는 안티 웹 스크래핑 데이터베이스가 있습니다. 원활한 접근을 보장하기 위해 자신의 핑거프린트를 계산하고 화이트리스트에 있는지 확인할 수 있습니다.

하지만 JA3 핑거프린트만 연결 중인 클라이언트가 스크래퍼라는 사실을 드러내는 것은 아닙니다. ClientHello 메시지 자체의 값 차이도 안티봇 시스템을 작동시킬 수 있습니다. 예를 들면 다음과 같습니다.

  • 요청에는 일반적으로 SNI가 있어야 하므로, SNI가 없으면 위험 신호일 수 있습니다.
  • 최신 브라우저는 대개 HTTP/2를 지원하므로 오래된 ALPN 요청은 의심스러운 활동의 징후로 보일 수 있습니다.
  • Chrome 같은 브라우저가 지원하는 타원 곡선과 프로그래밍 스크립트가 지원하는 곡선은 달라 의심을 불러일으킬 수 있습니다.
  • 암호화 스위트 목록은 우선순위대로 정렬되며 순서를 포함해 일반적인 웹 브라우저의 목록과 일치해야 합니다. 확장 기능도 마찬가지입니다.

TLS 핑거프린팅에 맞추는 방법

TLS 핑거프린팅에서는 스크래퍼가 일반적인 웹 브라우저의 핑거프린트와 일치하도록 하는 것이 목표입니다. 쉬운 작업은 아니지만 시도해 볼 만한 방법이 몇 가지 있습니다. 그중 일부를 함께 사용해도 좋습니다.

Puppeteer, Playwright 또는 Selenium 같은 고품질 브라우저를 사용하면 실제 브라우저를 사용하게 되어 결과적으로 진짜 핑거프린트를 얻습니다. 이들은 TLS 핑거프린팅을 변경하지 않으므로, 웹사이트는 일반 브라우저와 헤드리스 브라우저 중 어느 쪽이 연결을 시도하는지 판단할 수 없습니다. 허점이 하나 줄어듭니다.

  • 여러 브라우저와 운영체제 버전 사용

이 방법은 연결을 여러 핑거프린트에 분산하는 데 도움이 되며, 대규모 웹 스크래핑 프로젝트를 운영하는 경우 유용합니다.

  • LibCurl 기반 HTTP 클라이언트 사용

이러한 클라이언트는 curl-impersonate를 사용하도록 업데이트할 수 있습니다. 이는 TLS 핑거프린트를 패치하여 일반 웹 브라우저의 핑거프린트처럼 보이게 하는 libcurl 라이브러리의 수정 버전입니다. libcurl을 지원하는 라이브러리에는 Typhoeus(Ruby), Guzzle(PHP), PyCurl(Python), curl default 및 crul community libraries(R)가 있습니다.

  • TLS 강화

Go 언어를 사용한다면 운이 좋습니다. Go는 TLS 스푸핑을 지원하는 언어 중 하나입니다. Refraction Networking의 utls, ja3transport, CycleTLS 같은 라이브러리가 필요합니다.

하지만 Java 또는 Python을 사용한다면 상황은 그리 쉽지 않습니다. Java에서는 sslconfig.enabledCipherSuites 메서드로 활성화된 암호화 스위트 목록을 재구성할 수 있습니다. Python에서는 requests와 httpx를 사용해 암호화 스위트 및 TLS 버전 변수를 구성할 수 있는 정도입니다. 이러한 변수를 스푸핑하면 접근 중단 문제를 해결하는 데 도움이 될 수 있지만, 핑거프린트가 여전히 진정한 것처럼 보이지는 않습니다.

  • 다른 요소 로테이팅

모든 트래픽의 TLS 핑거프린트가 동일하면, 진짜처럼 보이더라도 의심스러워 보일 수 있습니다. 쿠키, 사용자 에이전트, 헤더, IP 주소처럼 로테이팅할 수 있는 요소를 로테이팅해 보세요. 그러면 ClientHello 메시지가 조금 변경되고, 결과적으로 JA3 핑거프린트도 어느 정도 달라집니다. 멀티 계정 브라우저고품질 프록시가 이에 도움이 됩니다.

마무리

마지막으로 중요한 점은, 웹사이트마다 TLS 프로토콜을 조금씩 다르게 적용하고 접근을 허용하거나 거부하는 고유한 기준과 데이터베이스를 갖추고 있으므로 TLS 핑거프린팅에 맞춰 작동하는 일이 어려울 수 있다는 것입니다. TLS 핑거프린트를 성공적으로 스푸핑하려면 각 웹사이트에 구체적으로 집중하여 해당 사이트의 핑거프린팅 메커니즘을 작동시키는 요소와 표준 프로토콜을 맞춤화하는 방식을 파악하세요. 또한 오늘날 웹 소스는 JA3 핑거프린팅 같은 네트워크 수준 신호와 글꼴 및 화면 해상도 같은 애플리케이션 수준 신호를 결합하므로 TLS 스푸핑에만 의존해서는 충분하지 않습니다. 스크래퍼의 모든 세부 사항이 진짜처럼 보이도록 해야 합니다. 또한 모든 것을 주기적으로 검토하세요. 웹사이트는 정책과 탐지 방식을 자주 업데이트하고 새로운 안티봇 접근법이 등장하므로, 정확한 데이터를 얻으려면 여러분도 동일하게 해야 합니다. 물론 언제나 허용된 한도 내에서 작업하고, 이용 가능한 데이터만 스크래핑하며, 대상 웹사이트에 과부하를 주지 않고, 적법하게 확보한 프록시 같은 신뢰할 수 있는 도구를 사용해야 합니다. 마지막 부분에서는 DataImpulse가 확실히 도움을 드릴 수 있습니다. “지금 사용해 보기” 버튼을 누르거나 질문이 있으시면 [email protected]으로 문의하세요.

Share article: