模拟 TLS 指纹实现反反爬

简介: 模拟 TLS 指纹实现反反爬

相信大家在做爬虫的时候,都有过被反爬的经历,一旦网站识别是爬虫,就会拒绝请求。反爬机制有很多,最常见的便是通过请求头里的 User-Agent,举个例子。

import requests
import httpx
response = requests.get("http://www.baidu.com")
print(response.request.headers["User-Agent"])
"""
python-requests/2.28.0
"""
response = httpx.get("http://www.baidu.com")
print(response.request.headers["User-Agent"])
"""
python-httpx/0.23.3
"""

如果 User-Agent 不符合浏览器的格式,那么一定不是浏览器发出的,于是网站便可认定这属于爬虫。当然通过 User-Agent 识别属于最低级的方式,因为爬虫可以伪造自己的 User-Agent。

import requests
import httpx
response = requests.get("http://www.baidu.com",
                        headers={"User-Agent": "Chrome User-Agent"})
print(response.request.headers["User-Agent"])
"""
Chrome User-Agent
"""
response = httpx.get("http://www.baidu.com",
                     headers={"User-Agent": "IE User-Agent"})
print(response.request.headers["User-Agent"])
"""
IE User-Agent
"""

除了 User-Agent 之外,还可以通过请求头中的 Refer 字段判断是否为爬虫。比如你在 A 页面点击某个标签跳转到 B 页面,那么 Refer 就是 A 页面的地址。如果你直接访问的 B 页面,那么 Refer 就是空。

如果 B 页面必须通过点击 A 页面的标签才能跳转,那么网站便可以通过 Refer 来判断是否为爬虫。

当然啦,反爬机制还有很多,不同网站使用的策略不一样。但现在大部分的网站都使用了 HTTPS,在建立 HTTPS 连接的时候要先进行 TLS 握手,在握手的过程中会协商加密算法、交换密钥和验证双方的身份。

而将 TLS 握手产生的信息收集起来,并使用 JA3 算法生成一个哈希值,便得到了 TLS 指纹,基于该指纹可以标识、分类和跟踪使用特定 TLS 配置的客户端。

因此通过 JA3 哈希生成指纹便可以确定哪些是恶意流量,从而将其拒绝掉。换句话说,通过 TLS 指纹可以识别哪些是浏览器发出的正常请求,哪些是爬虫。

那么 TLS 指纹如何查看呢?可以通过以下几个网站。

https://tls.browserleaks.com/json

https://tls.peet.ws/ 

https://kawayiyi.com/tls

9a47873f1796c3ae569a27c21e531bcf.png

这是我基于浏览器访问的,它的字段都不是空,我们使用 Python 访问一下。

import requests
import httpx
user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " \
             "AppleWebKit/537.36 (KHTML, like Gecko) " \
             "Chrome/118.0.0.0 Safari/537.36"
response = requests.get("https://tls.browserleaks.com/json",
                        headers={"User-Agent": user_agent})
print(response.json())
"""
{'ja3_hash': '8d9f7747675e24454cd9b7ed35c58707', 
 'ja3_text': '771,4866-4867-4865-49196-49200-49195...', 
 'ja3n_hash': 'a790a1e311289ac1543f411f6ffceddf', 
 'ja3n_text': '771,4866-4867-4865-49196-49200-49195...', 
 'akamai_hash': '', 
 'akamai_text': ''}
"""
response = httpx.get("https://tls.browserleaks.com/json",
                     headers={"User-Agent": user_agent})
print(response.json())
"""
{'ja3_hash': '76f01df912881a05228c70b7f61bcbaa', 
 'ja3_text': '771,4866-4867-4865-49196-49200-49195...', 
 'ja3n_hash': '80a9bea1db8ce3a18047816ba1ee07e5', 
 'ja3n_text': '771,4866-4867-4865-49196-49200-49195...', 
 'akamai_hash': '', 
 'akamai_text': ''}
"""

如果使用爬虫,那么多次请求时的 ja3_hash 是不变的,并且 akamai_hash 和 akamai_text 均是空,基于该特征很容易识别是不是爬虫。即使我们更换代理,设置请求头,也无法改变这一点。

于是为了完美模拟浏览器,国外大佬开发出了 curl-impersonate,将 curl 底层依赖的库全部换成了浏览器使用的库,并且版本也是一致的,这样生成的指纹就和浏览器完全一样了。

而 curl_cffi 正是 curl-impersonate 的 Python binding,我们直接使用 pip 安装即可。

# 和 requests 接口是一致的
from curl_cffi import requests
# 但是多了一个 impersonate 参数,用于指定模拟哪个浏览器
response = requests.get("https://tls.browserleaks.com/json",
                        impersonate="chrome101")
print(response.json())
"""
{'ja3_hash': 'cd08e31494f9531f560d64c695473da9', 
 'ja3_text': '771,4865-4866-4867-49195-49199-49196...', 
 'ja3n_hash': 'aa56c057ad164ec4fdcb7a5a283be9fc', 
 'ja3n_text': '771,4865-4866-4867-49195-49199-49196...', 
 'akamai_hash': '8a32ff5cb625ed4ae2d092e76beb6d99', 
 'akamai_text': '1:65536;3:1000;4:6291456;6:262144|15663105||m,a,s,p'}
"""
# 当然也可以先创建 session
session = requests.Session()
# 然后基于 session 发请求

总共支持如下版本的浏览器:

我们选择 chrome110 即可,然后 curl_cffi 还支持异步发请求,可以和 asyncio 轻松集成。

import asyncio
from curl_cffi import requests
async def send_req():
    async with requests.AsyncSession() as session:
        response = await session.get(
            "https://tls.browserleaks.com/json",
            impersonate="chrome101"
        )
    print(response.json())
    
asyncio.run(send_req())
"""
{'ja3_hash': 'cd08e31494f9531f560d64c695473da9', 
 'ja3_text': '771,4865-4866-4867-49195-49199-49196...', 
 'ja3n_hash': 'aa56c057ad164ec4fdcb7a5a283be9fc', 
 'ja3n_text': '771,4865-4866-4867-49195-49199-49196...', 
 'akamai_hash': '8a32ff5cb625ed4ae2d092e76beb6d99', 
 'akamai_text': '1:65536;3:1000;4:6291456;6:262144|15663105||m,a,s,p'}
"""

由于指纹特征很难更改,因此通过指纹可以防御一大批爬虫,而通过 curl_cffi 模拟指纹则可以绕过这道防线。


本文参考自:

相关文章
|
网络协议 Linux 应用服务中间件
Emby 客户端破解
前言 对于各路资源大佬们来说,Emby 的大名肯定不陌生了
|
3月前
|
存储 安全 数据安全/隐私保护
解锁Python安全新姿势!AES加密:让你的数据穿上防弹衣,无惧黑客窥探?
【8月更文挑战第1天】在数字化时代,确保数据安全至关重要。AES(高级加密标准)作为一种强大的对称密钥加密算法,能有效保护数据免遭非法获取。AES支持128/192/256位密钥,通过多轮复杂的加密过程提高安全性。在Python中,利用`pycryptodome`库可轻松实现AES加密:生成密钥、定义IV,使用CBC模式进行加密与解密。需要注意的是,要妥善管理密钥并确保每次加密使用不同的IV。掌握AES加密技术,为数据安全提供坚实保障。
189 2
|
4月前
|
算法 数据安全/隐私保护 Python
数字签名是一种用于验证数据完整性和来源身份的技术。它基于公钥密码学,允许数据的发送方使用其私钥对数据进行签名,而接收方则可以使用发送方的公钥来验证签名的有效性。
数字签名是一种用于验证数据完整性和来源身份的技术。它基于公钥密码学,允许数据的发送方使用其私钥对数据进行签名,而接收方则可以使用发送方的公钥来验证签名的有效性。
|
4月前
|
算法 安全 数据安全/隐私保护
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
|
6月前
|
安全 算法 数据安全/隐私保护
HTTPS 加密工作过程
HTTPS 加密工作过程
|
安全 网络协议 算法
HTTPS行为大赏(三分钟了解加密过程)
了解HTTPS的加密过程这一篇文章就够了,HTTPS的加密过程详细介绍。
80 1
|
6月前
|
安全 数据安全/隐私保护
详解HTTPS加密工作过程
详解HTTPS加密工作过程
353 1
|
安全 算法 网络协议
一篇文章读懂HTTPS及其背后的加密原理
HTTPS(全称: Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。本文,就来深入介绍下其原理。
|
传感器 存储 机器学习/深度学习
指纹登录是怎么跑起来的1
指纹登录是怎么跑起来的1
147 0
|
存储 安全 前端开发
指纹登录是怎么跑起来的2
指纹登录是怎么跑起来的2
238 0