文章目录
前言
有道是有反爬虫就有反反爬虫,这篇就从TLS指纹识别说起。
TLS指纹
什么是TLS指纹
TLS指纹是一种用于识别和验证TLS(传输层安全)通信的技术。
TLS指纹可以通过检查TLS握手过程中使用的密码套件、协议版本和加密算法等信息来确定TLS通信的特征。由于每个TLS实现使用的密码套件、协议版本和加密算法不同,因此可以通过比较TLS指纹来判断通信是否来自预期的源或目标。
TLS指纹可以用于检测网络欺骗、中间人攻击、间谍活动等安全威胁,也可以用于识别和管理设备和应用程序。
TLS指纹识别原理(ja3算法): https://github.com/salesforce/ja3
测试TLS指纹
测试一下不同客户端之间的指纹差异(ja3_hash)
测试网站: https://tls.browserleaks.com/json
-
ubuntu 20.04
-
centos
-
window10
-
chrome
-
python3.9
可见不同的客户端都存在区别,针对最后一个python的ja3_text做一个简单的说明
- 第一个值 771 :表示 JA3 版本,即用于生成指纹的 JA3 脚本的版本。
- 第二个值 4866-4867-4865-49196-49200-49195-49199-163-159-162-158-49327-49325-49188-- 49192-49162-49172-49315-49311-107-106-57-56-49326-49324-49187-49191-49161-49171-49314-49310-103-64-51-50-52393-52392-49245-49249-49244-49248-49267-49271-49266-49270-52394-49239-49235-49238-49234-196-195-190-189-136-135-69-68-157-156-49313-49309-49312-49308-61-60-53-47-49233-49232-192-186-132-65-255:表示加密套件,即客户端可以支持的加密算法。
- 第三个值 0-11-10-35-22-23-13-43-45-51-21:表示支持的压缩算法。
- 第四个值 29-23-30-25-24:表示支持的 TLS 扩展,如 SNI。
- 第五个值 0-1-2:表示支持的 elliptic curves,即椭圆曲线算法。
绕过TLS指纹
绕过就是伪造成合法客户端就行,简单来说,就是伪装ja3_text值,让其不被拦截即可,以修改支持的加密算法为主。
使用原生urllib
实现
import urllib.request
import ssl
url = 'https://tls.browserleaks.com/json'
req = urllib.request.Request(url)
resp = urllib.request.urlopen(req)
print(resp.read().decode())
# 伪造TLS指纹
context = ssl.create_default_context()
context.set_ciphers("ECDHE-RSA-AES128-GCM-SHA256+ECDHE+AESGCM")
url = 'https://tls.browserleaks.com/json'
req = urllib.request.Request(url)
resp = urllib.request.urlopen(req, context=context)
print(resp.read().decode())
效果
使用其他成熟库!!
可以试试curl_cffi这个库,他是基于requests,所以语法基本一样
Unlike other pure python http clients like httpx or requests, curl_cffi can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
也可以试试pyhttpx、pycurl这两个库
安装
pip install curl_cffi --upgrade
实现
from curl_cffi import requests
print("edge99:", requests.get("https://tls.browserleaks.com/json", impersonate="edge99").json().get("ja3_hash"))
print("chrome110:", requests.get("https://tls.browserleaks.com/json", impersonate="chrome110").json().get("ja3_hash"))
print("safari15_3:", requests.get("https://tls.browserleaks.com/json", impersonate="safari15_3").json().get("ja3_hash"))
# 支持代理
proxies = {"https": "http://localhost:7890"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="safari15_3", proxies=proxies)
print(r.json().get("ja3_hash"))
效果
**支持伪造的浏览器列表如下:**随便挑一个就行了
修改requests底层代码
requests 库的 SSL/TLS 认证是基于 urllib3 库实现的,所以改底层就是改urllib3的代码
修改相关SSL代码,文件地址一般为site-packages/urllib3/util/ssl_.py
# A secure default.
# Sources for more information on TLS ciphers:
#
# - https://wiki.mozilla.org/Security/Server_Side_TLS
# - https://www.ssllabs.com/projects/best-practices/index.html
# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
#
# The general intent is:
# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE),
# - prefer ECDHE over DHE for better performance,
# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and
# security,
# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
# - disable NULL authentication, MD5 MACs, DSS, and other
# insecure ciphers for security reasons.
# - NOTE: TLS 1.3 cipher suites are managed through a different interface
# not exposed by CPython (yet!) and are enabled by default if they're available.
修改这里的加密算法为你想要的,不嫌麻烦也可以去继承重写就不用改代码了
DEFAULT_CIPHERS = ":".join(
[
"ECDHE+AESGCM",
"ECDHE+CHACHA20",
"DHE+AESGCM",
"DHE+CHACHA20",
"ECDH+AESGCM",
"DH+AESGCM",
"ECDH+AES",
"DH+AES",
"RSA+AESGCM",
"RSA+AES",
"!aNULL",
"!eNULL",
"!MD5",
"!DSS",
]
)
修改前
修改后
Akamai指纹相关(HTTP/2指纹)
什么是Akamai指纹
Akamai Fingerprint是Akamai Technologies公司提供的一种防止恶意机器人和自动化攻击的技术,它基于浏览器指纹识别技术。
浏览器指纹是一种用于识别Web浏览器的技术,它通过收集并分析浏览器的各种属性和行为,如用户代理字符串、插件、字体、语言、屏幕分辨率等信息来识别浏览器。浏览器指纹在互联网安全领域得到了广泛应用,可以用于检测和识别恶意机器人、欺诈行为、网络钓鱼等。
Akamai Fingerprint利用了浏览器指纹技术,将其与其他安全技术结合起来,以识别和拦截自动化攻击。它可以在不影响用户体验的情况下,对访问网站的浏览器进行识别和验证,防止自动化攻击、账户滥用和数据泄露等安全问题。
可以在 https://tls.peet.ws/api/all 看到详细的指纹,主要有如下内容
指纹为:1:65536,2:0,3:1000,4:6291456,6:262144|15663105|0|m,a,s,p
-
1:65536
: HEADER_TABLE_SIZE,即头部表大小为64KB,指的是用于存储请求头和响应头的大小,它是可以调整的。这个字段指明了使用64KB的头部表大小。 -
2:0
: HTTP2_VERSION,指示此请求使用的HTTP/2版本。0表示H2,表示启用了HTTP/2协议。 -
3:1000
:== MAX_CONCURRENT_STREAMS==,即最大并发流数,指的是在任何给定时间内,客户端和服务器端可以并行发送的最大请求数量。这个字段指明了最大并发流数为1000。 -
4:6291456
: INITIAL_WINDOW_SIZE,即初始流窗口大小,指的是初始的流控窗口大小,即客户端可以发送的最大字节数量。这个字段指明了初始流窗口大小为6MB(即6291456字节)。 -
6:262144|15663105|0|m,a,s,p
: 以竖杠“|”分隔。具体含义如下:6:262144
: MAX_HEADER_LIST_SIZE,即动态表大小,指的是接收方可以接收的最大HTTP头部大小。这个字段指明了动态表大小为256KB(即262144字节)。15663105
: WINDOW_UPDATE,表示收到了WINDOW_UPDATE帧,并且窗口大小增加了15663105个字节。0
:no compression
,表示不启用头部压缩。- 以
:
开头的 header 的第一个字符参与编码,多个逗号隔开。如:method
、:authority
、:scheme
、:path
编码为m,a,s,p
可在 Passive Fingerprinting of HTTP/2 Clients中查看详细细节
测试Akamai指纹
测试网站: https://tls.browserleaks.com/json
-
window 10(不知道是不是curl版本问题导致不行, 参考上面的Ubuntu的curl是可以的)
-
centos(不知道是不是curl版本问题导致不行, 参考上面的Ubuntu的curl是可以的)
-
chrome
-
python
可以看到用python requests直接为空被拦截在外了
绕过Akamai指纹
伪造指纹中特定的字段即可。
使用其他成熟库
还是刚才的 curl_cffi这个库,因为这个库主打的就是模拟各种指纹
from curl_cffi import requests
print("edge99:", requests.get("https://tls.browserleaks.com/json", impersonate="edge99").json().get("akamai_hash"))
print("chrome110:", requests.get("https://tls.browserleaks.com/json", impersonate="chrome110").json().get("akamai_hash"))
print("safari15_3:", requests.get("https://tls.browserleaks.com/json", impersonate="safari15_3").json().get("akamai_hash"))
效果
可以看到已经获取到
实操
https://ascii2d.net 存在CloudFlare的指纹护盾,拒绝爬虫,测试一下。
直接请求title显示这个Just a moment…,这个明显是五秒盾了
尝试绕过一下
from curl_cffi import requests
print(requests.get("https://ascii2d.net", impersonate="chrome110").text)
效果,可以看得出正确获取到了