本文章只做技术探讨, 请勿用于非法用途。
引言
爬虫工作的又一大阻碍, tls 指纹校验。最近正好也遇到了, 大概去了解了一下, 顺便跟大家聊聊这个东西。
原理
定义方面的东西就不去细说了, 我做个大概的解释吧。
简单来说, 不同的浏览器都有自己不同的 加密套件、扩展工具、椭圆曲线 等信息, 这些信息共同构建起了一个 tls 指纹。在请求发起之后, tls 握手阶段服务端通过对第一个数据包(client hello)所携带的指纹进行识别, 就可以判断对象是否为一个合法的浏览器环境。
展示
这里用一个网站来向大家做一个直观的展示。
这个网站可以看到当前请求所携带的加密套件、扩展工具等信息, 即 tls 指纹。
网站内容示例
多次请求示例
需要我们关注的主要是 JA3 这个加密参数, 他是通过 tls 指纹的内容做 md5 加密后生成。

AI 提供的加密套件编号映射表
加密结果示例
根据映射表, 我们可以清晰的看到 JA3 密文的由来。
简单提一下, 明文最前方的 771 部分也是十六进制值, 代表最高支持 TLS1.3 版本。
总结一下, 将 TLS版本、加密套件、扩展工具、椭圆曲线 这四个部分转为对应的十六进制数字, 按照一定的顺序排列, 进行 md5 加密, 最终可以得到 tls 指纹的值, 且多次请求结果有以下规律。
- 加密套件、扩展工具、椭圆曲线 三个部分都包含 TLS_GREASE, 且每次结果都不同。
- 加密套件 和 椭圆曲线 部分, 除了 TLS_GREASE 以外, 其他部分都不会变化, 顺序相同。
- 扩展工具 每次顺序都会变化。
- 因顺序变化 及 TLS_GREASE 变化, 每次请求 JA3 的值都不相同。
对比
看过了浏览器的值, 我们拿 Python 的 requests 库请求来做一个对比, 来了解我们的请求是怎么被 "抓到" 的。
代码请求示例
使用 requests 库发起请求, 将结果写入文件, 将文件用浏览器进行渲染。
requests 指纹示例
requests 多次请求指纹示例
我进行了两次请求, 分别保存文件 123.html 和 124.html, 他们的指纹如上图所示, 可以发现 requests 请求中没有 TLS_GREASE , 携带的 加密套件、扩展工具、椭圆曲线 都和浏览器有很大差异, 同时每次请求的结果都是相同的。 基于此, 很容易就会被甄别出来。
处理
那么有办法解决这个问题吗?
包有的!
方案一
首先就是一些 Python 库, 这里推荐两个吧, curl_cffi 和 tls_client。
我个人觉得 curl_cffi 用起来很方便, 这里就用它来举例。
curl_cffi 请求代码示例
curl_cffi 指纹示例
curl_cffi 多次请求指纹示例
和之前一样, 进行了两次请求, 分别保存文件 125.html 和 126.html, 指纹如上图所示, 我们可以发现他的内容已经和浏览器的一致了, 且每次请求也都有了该有的变化。
方案二
我们可以自行使用 urllib 库根据浏览器的内容来进行一个模拟, 但是不推荐, 麻烦不说, 有更方便的工具为什么不去用呢。如果就喜欢麻烦的, 也不是不行, 下边我放出由 AI 提供的模拟代码。
AI 提供自行模拟代码
方案三
如果第三方库因为一些原因实在无法解决问题, 也不想要自己去模拟, 可以考虑使用 Python 来调用 curl 或是调用浏览器来去做。
这里只对调用 curl 做展示, 浏览器的话或许可以通过 selenium 之类的来做通信。
Python 调用 curl 示例
确定 curl 请求可行再去使用。
拓展
再多聊一下 wireshark 吧, 一个抓包工具, 能清晰的看到不同请求携带的内容。
wireshark 抓包示例
curl_cffi 库请求抓包示例
和浏览器网址上看到的内容是对照的, 提一下, 有兴趣可以自行了解。
总结
分享一下, 也是最近才稍微认真的去了解了下原理, 能帮到大家最好, 有错误希望能指出。
请洒潘江,各倾陆海云尔。