walterwhite-69/ViperTLS
GitHub: walterwhite-69/ViperTLS
纯 Python 实现的高拟真 TLS 指纹与浏览器挑战绕过工具,解决自动化请求被 Cloudflare 等识别与拦截问题。
Stars: 18 | Forks: 1
```markdown
```
██╗ ██╗██╗██████╗ ███████╗██████╗ ████████╗██╗ ███████╗
██║ ██║██║██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║ ██╔════╝
██║ ██║██║██████╔╝█████╗ ██████╔╝ ██║ ██║ ███████╗
╚██╗ ██╔╝██║██╔═══╝ ██╔══╝ ██╔══██╗ ██║ ██║ ╚════██║
╚████╔╝ ██║██║ ███████╗██║ ██║ ██║ ███████╗███████║
╚═══╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝
```
**纯 Python TLS 指纹伪造与浏览器挑战回退。不依赖 curl_cffi,不依赖 Go 二进制文件,不找借口。**
[](https://python.org)
[](LICENSE)
[](https://http2.github.io)
[](https://http3.net)
[](https://cloudflare.com)
[](https://github.com)
[](https://github.com)
## 这是什么?
ViperTLS 是一个**纯 Python HTTP 客户端**,让你的请求在 TLS 层面看起来像是来自真实浏览器。它伪造:
- **JA3 / JA4 系列** — 完整的 TLS ClientHello 指纹套件:JA4、JA4_r、JA4H、JA4S、JA4L
- **HTTP/2 SETTINGS 帧** — 实际浏览器协商的窗口大小、头部表大小和帧顺序
- **HTTP/2 伪头顺序** — Chrome 发送 `:method :authority :scheme :path`,Firefox 发送 `:method :path :authority :scheme`
- **HTTP 头部顺序** — 因为 Cloudflare 像保安一样逐字检查你的头部
- **HTTP/3 / QUIC** — 通过 aioquic 为每个浏览器系列提供准确的 QUIC 传输参数
结果是:你的 Python 脚本以 Chrome 的姿态走向 Cloudflare 的 velvet 绳口,并直接获得通行。
当 TLS 指纹不足且站点仍抛出浏览器挑战时,ViperTLS 会升级为真实的浏览器求解,获取有用的 Cookie 并在后续请求中复用。因此实际请求流程为:
- **TLS**:站点使用隐形 Cloudflare 或仅指纹检查时
- **浏览器**:站点需要完整 JS 挑战求解时
- **缓存**:站点已求解且通行 Cookie 仍有效时
可以把它看作 [CycleTLS](https://github.com/Danny-Dasilva/CycleTLS) —— 但纯 Python 实现,不生成 Go 子进程,不依赖 curl_cffi,也不涉及任何编译二进制文件。
## 工作原理
Cloudflare 和其他机器人检测系统不仅看 User-Agent,它们分析你的 TLS 握手和 HTTP/2 连接建立过程中的**实际字节**。每个库都有其指纹:
```
python-requests → JA3: 3b5074b1b5d032e5620f69f9159c1ab7 → BLOCKED
urllib3 → JA3: b32309a26951912be7dba376398abc3b → BLOCKED
Chrome → JA3: browser-like → ALLOWED
ViperTLS → JA3: looks like a real browser → ALLOWED
```
ViperTLS 通过以下方式到达那里:
1. 使用 **pyOpenSSL** (`OpenSSL.SSL.Context`) 与 cffi,设置 TLS 1.2 加密顺序、TLS 1.3 加密套件和椭圆曲线组 —— 不触碰 CPython 内部结构,兼容 Python 3.10 到 3.14
2. 使用 [`h2`](https://python-hyper.org/projects/h2/) 库并注入自定义 SETTINGS 与 Chromium 风格行为
3. 按照浏览器实际发送顺序发送 HTTP 头部
4. 在每个响应中计算并暴露完整的 **JA4 指纹系列**,以便验证实际发送内容
5. 当需要时回退到真实的 Chromium 实例以解决 JS 挑战
没有二进制桥接,没有子进程包装器,没有 ctypes。只有 Python、pyOpenSSL,以及一些有争议的人生选择。
## 安装
```
pip install vipertls
vipertls install-browsers
```
`vipertls install-browsers` 会下载 ViperTLS 使用的 Playwright Chromium 二进制文件。当站点需要完整浏览器挑战求解时,该二进制文件由 Playwright 完全管理 —— 但 Chromium 本身仍需要某些**系统级库**(Linux 上的 `.so` 文件)才能运行。
对于源码检出:
```
git clone https://github.com/walterwhite-69/ViperTLS
cd ViperTLS
pip install -e .
python install_browsers.py
```
**快速命令:**
```
vipertls --help
vipertls
vipertls paths
vipertls serve --host 127.0.0.1 --port 5000
```
ViperTLS 将 Playwright 浏览器、求解 Cookie 和其他可写运行时文件统一存放在一个 ViperTLS 管理的目录中。在源码检出中该目录为仓库根;在 pip 安装中则回退到用户可写的 `vipertls` 目录。
如果求解器找不到本地 Chrome 或 Edge 安装,它会在首次浏览器求解时自动引导 Playwright Chromium。你也可以通过 `vipertls install-browsers` 显式执行。
当你将 ViperTLS 作为模块使用时,它会优先使用脚本旁边的 `vipertls` 文件夹,使求解器 Cookie 和浏览器资源与爬虫项目捆绑,而非混入全局缓存。
**Python 3.10 到 3.14 均受支持。** TLS 层使用 pyOpenSSL 与 cffi —— 无 ctypes、无 CPython 指针提取、无版本相关 hack。每个二进制依赖都为所有支持版本提供兼容的 wheel。
## 浏览器回退的系统要求
浏览器挑战回退会运行真实的 Chromium 实例。Chromium 需要一组共享库(Linux 上的 `.so` 文件)存在于你的操作系统中。如果缺失,你会得到 `browser_failed` 并提示 `missing browser dependency`。
### Windows
无需额外步骤。Chromium 自行携带 DLL。
### macOS
Playwright 已处理一切 —— `vipertls install-browsers` 后无需额外操作。若 Chromium 仍崩溃,请安装 XQuartz:
```
brew install --cask xquartz
```
### Ubuntu / Debian / Kali / Pop!_OS
最简路径 —— Playwright 为你安装所有依赖:
```
pip install playwright
playwright install --with-deps chromium
```
`--with-deps` 会在后台调用 `apt` 并自动安装所需库。只需执行一次。
若你更倾向于手动安装库:
```
sudo apt-get install -y \
libglib2.0-0 libnss3 libnspr4 libatk1.0-0 \
libatk-bridge2.0-0 libcups2 libdrm2 libdbus-1-3 \
libxcb1 libxkbcommon0 libx11-6 libxcomposite1 \
libxdamage1 libxext6 libxfixes3 libxrandr2 \
libgbm1 libasound2 libpango-1.0-0 libcairo2 \
libexpat1 libudev1
```
### Arch Linux / Manjaro
```
sudo pacman -S --needed \
glib2 nss nspr atk at-spi2-atk at-spi2-core \
cups libdrm dbus libxcb libxkbcommon \
libx11 libxcomposite libxdamage libxext libxfixes libxrandr \
mesa libgbm alsa-lib pango cairo expat systemd-libs
```
### Fedora / RHEL / CentOS
```
sudo dnf install -y \
glib2 nss nspr atk at-spi2-atk at-spi2-core \
cups-libs libdrm dbus-libs libxcb libxkbcommon \
libX11 libXcomposite libXdamage libXext libXfixes libXrandr \
mesa-libgbm alsa-lib pango cairo expat systemd-libs
```
### NixOS / Replit
NixOS 不使用标准 FHS 文件系统,因此无法使用 `apt` 或 `pacman`。请在 `replit.nix`(或 `shell.nix` / `flake.nix`)中添加以下内容:
```
{pkgs}: {
deps = [
pkgs.glib
pkgs.nss
pkgs.nspr
pkgs.atk
pkgs.at-spi2-atk
pkgs.at-spi2-core
pkgs.dbus
pkgs.cups
pkgs.libdrm
pkgs.mesa
pkgs.libgbm
pkgs.libxkbcommon
pkgs.alsa-lib
pkgs.expat
pkgs.udev
pkgs.pango
pkgs.cairo
pkgs.gtk3
pkgs.xorg.libX11
pkgs.xorg.libXcomposite
pkgs.xorg.libXdamage
pkgs.xorg.libXext
pkgs.xorg.libXfixes
pkgs.xorg.libXrandr
pkgs.xorg.libxcb
pkgs.xorg.libXcursor
pkgs.xorg.libXi
];
}
```
## 验证你的环境
安装库并运行 `vipertls install-browsers` 后:
```
python3 -c "
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
page = b.new_page()
page.goto('https://example.com')
print('OK:', page.title())
b.close()
"
```
若输出 `OK: Example Domain`,说明环境正常。若在 Linux 上抛出库错误,请使用 `ldd` 检查 Chromium 二进制文件以定位缺失库:
```
python3 -c "
from playwright._impl._driver import compute_driver_executable
import pathlib
print(pathlib.Path(compute_driver_executable()).parent.parent)
"
# 然后:
ldd ~/.cache/ms-playwright/chromium-*/chrome-linux64/chrome | grep "not found"
```
任何 `not found` 条目均为缺失库 —— 为对应发行版安装相应包即可。
## 快速开始
```
import asyncio
import vipertls
async def main():
async with vipertls.AsyncClient(impersonate="chrome_145", debug_messages=True) as client:
response = await client.get("https://www.crunchyroll.com/")
print(response.status_code)
print(response.solved_by)
print(response.solve_info)
asyncio.run(main())
```
## 使用 ViperTLS 的方式
### 1. 作为 Python 模块
最适合直接控制 Python 代码并获得最简洁 API 的场景。
```
import asyncio
import vipertls
async def main():
async with vipertls.AsyncClient(impersonate="edge_133") as client:
response = await client.get("https://example.com")
print(response.status_code)
print(response.solved_by)
print(response.solve_info)
asyncio.run(main())
```
### 2. 作为本地代理服务器
适合无法直接导入 Python 代码、但能向 `localhost` 发送 HTTP 请求的工具。
```
vipertls serve --host 127.0.0.1 --port 8080
```
然后:
```
curl http://127.0.0.1:8080 \
-H "X-Viper-URL: https://example.com" \
-H "X-Viper-Impersonate: edge_133"
```
### 3. 作为独立的浏览器求解 API
仅需要浏览器挑战求解作为服务时的最佳选择。
```
python -m vipertls.solver --port 8081
```
然后:
```
curl -X POST http://127.0.0.1:8081/solve \
-H "content-type: application/json" \
-d "{\"url\":\"https://example.com\",\"preset\":\"edge_133\",\"timeout\":30}"
```
### 你应该使用哪一种?
- 已在 Python 中 → **Python 模块**
- 其他工具只能发 HTTP 请求 → **本地代理服务器**
- 仅需挑战求解服务 → **独立求解 API**
## 用法
### 异步客户端
```
import asyncio
import vipertls
async def main():
async with vipertls.AsyncClient(
impersonate="edge_133",
proxy="socks5://user:pass@host:1080",
timeout=30,
verify=True,
follow_redirects=True,
debug_messages=True,
) as client:
r = await client.get("https://example.com/")
print(r.status_code, r.http_version, len(r.content))
print(r.solved_by, r.from_cache)
print(r.cookies_received)
print(r.cookies_used)
asyncio.run(main())
```
### HTTP/3
```
async with vipertls.AsyncClient(impersonate="chrome_145", http3=True) as client:
r = await client.get("https://example.com/")
print(r.http_version)
```
传入 `http3=True` 会强制从首个请求使用 QUIC。未设置时,ViperTLS 仍会检测 `alt-svc: h3=` 并在后续请求中自动升级。
### 同步客户端
```
import vipertls
client = vipertls.Client(impersonate="firefox_136", timeout=30)
r = client.get("https://www.tempmail.la/")
print(r.status_code)
print(r.text[:500])
```
### 求解器状态
检查响应时,`r.solved_by` 表示 ViperTLS 的通过方式:
- `tls` — 直接请求成功,TLS 指纹足够
- `browser` — 直接请求遇到挑战,由浏览器求解器解决
- `cache` — 已有之前的浏览器求解结果,Cookie 仍有效,直接复用
```
print(r.solved_by)
print(r.from_cache)
print(r.cookies_received)
print(r.cookies_used)
print(r.solve_info)
```
### 响应对象
```
r.status_code
r.ok
r.solved_by
r.from_cache
r.headers
r.content
r.text
r.json()
r.http_version
r.url
r.cookies_received
r.cookies_used
r.solve_info
r.raise_for_status()
```
### JA4 指纹家族
每个响应暴露完整的 JA4 指纹套件,以便验证请求在服务器端的实际外观:
```
r.ja4 # TLS ClientHello fingerprint
r.ja4_r # JA4 raw (unsorted, full values)
r.ja4h # HTTP header fingerprint
r.ja4s # Server hello fingerprint
r.ja4l # Latency fingerprint (connect_ms_handshake_ms)
```
来自 Chrome 145 的实时请求示例:
CODE_BLOCK_25/>
这些数据也通过 `r.solve_info` 以字典形式提供。
### 运行时辅助工具
```
import vipertls
print(vipertls.get_runtime_paths())
vipertls.clear_solver_cache()
vipertls.clear_solver_cache(domain="1337x.to")
vipertls.clear_solver_cache(domain="1337x.to", preset="edge_133")
```
## 实时仪表盘(TUI)
基于 [`rich`](https://github.com/Textualize/rich) 构建的真实请求监控。
```
import asyncio
from vipertls import ViperDashboard
async def main():
async with ViperDashboard(impersonate="chrome_145", timeout=30) as dash:
await asyncio.gather(
dash.get("https://www.crunchyroll.com/"),
dash.get("https://tls.peet.ws/api/all", headers={"accept": "application/json"}),
)
asyncio.run(main())
```
仪表盘展示实时请求旋转器、带颜色标记的状态码、HTTP 版本、响应大小、延迟和预设。
## 服务模式
以本地 HTTP 代理服务器运行 ViperTLS。向 `localhost` 发送请求并携带 `X-Viper-*` 控制头。
```
vipertls serve --host 127.0.0.1 --port 8080
vipertls serve --host 0.0.0.0 --port 8080 --workers 4
```
然后:
```
curl -s http://localhost:8080 \
-H "X-Viper-URL: https://www.crunchyroll.com/" \
-H "X-Viper-Impersonate: chrome_145"
```
### 控制头
| 头名称 | 描述 | 示例 |
|--------|------|------|
| `X-Viper-URL` | 目标 URL | `https://www.crunchyroll.com/api/...` |
| `X-Viper-Method` | HTTP 方法 | `POST` |
| `X-Viper-Impersonate` | 浏览器预设名称 | `chrome_145`, `firefox_136`, `safari_18` |
| `X-Viper-Proxy` | 代理 URL | `socks5://user:pass@host:1080` |
| `X-Viper-Timeout` | 请求超时(秒) | `30` |
| `X-Viper-JA3` | 覆盖 JA3 指纹字符串 | `771,4865-4866-4867,...` |
| `X-Viper-No-Redirect` | 禁用重定向跟随 | `true` |
| `X-Viper-Skip-Verify` | 跳过 TLS 证书验证 | `true` |
| `X-Viper-Force-HTTP1` | 强制使用 HTTP/1.1 | `true` |
| `X-Viper-Body` | 请求体(字符串) | `{"key":"value"}` |
| `X-Viper-Headers` | 额外头部(JSON 字符串) | `{"authorization":"Bearer ..."}` |
代理响应还包含 ViperTLS 专用辅助头:
- `X-ViperTLS-Solved-By`
- `X-Viper-HTTP-Version`
- `X-Viper-Received-Cookies`
- `X-ViperTLS-Used-Cookies`
- `X-ViperTLS-JA4`
- `X-ViperTLS-JA4H`
- `X-ViperTLS-JA4S`
- `X-ViperTLS-JA4L`
## 独立求解 API
```
python -m vipertls.solver --host 127.0.0.1 --port 8081
```
可用端点:
- `POST /solve`
- `DELETE /cookies/{domain}`
- `DELETE /cookies`
- `GET /health`
示例:
```
curl -X POST http://127.0.0.1:8081/solve \
-H "content-type: application/json" \
-d "{\"url\":\"https://nopecha.com/demo/cloudflare\",\"preset\":\"edge_133\",\"timeout\":30}"
```
## 浏览器预设
| 预设 | 别名 | JA4 |
|------|------|-----|
| `chrome_145` | `chrome` | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_140` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_136` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_133` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_131` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_124` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `chrome_120` | — | `t13d1515h2_dea800f94266_daa8e4778a3e` |
| `firefox_136` | `firefox` | `t13d1814h2_f3ddd0d8df11_3bed559cf7b0` |
| `firefox_133` | — | `t13d1814h2_f3ddd0d8df11_3bed559cf7b0` |
| `firefox_127` | — | `t13d1814h2_f3ddd0d8df11_3bed559cf7b0` |
| `firefox_120` | — | `t13d1814h2_f3ddd0d8df11_3bed559cf7b0` |
| `safari_18` | `safari` | `t13d2214h2_bb4723730337_030652283baa` |
| `safari_17` | — | `t13d2214h2_bb4723730337_030652283baa` |
| `edge_136` | `edge` | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `edge_133` | — | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `brave_136` | `brave` | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
| `opera_117` | `opera` | `t13d1516h2_dea800f94266_0cba2f92bfc0` |
推荐预设:
- `chrome_145` — 默认首选隐形 Cloudflare 和纯 TLS 目标,快速且无需启动浏览器
- `edge_133` — 浏览器挑战回退的首选默认,与服务端浏览器路径匹配良好
- `firefox_136` — 需要特定 Firefox TLS 与 HTTP/2 行为时使用
- `safari_18` — 针对检查 Safari 指纹的目标
## 代理支持
```
AsyncClient(proxy="socks5://username:password@proxy.host:1080")
AsyncClient(proxy="socks5h://username:password@proxy.host:1080")
AsyncClient(proxy="socks4://proxy.host:1080")
AsyncClient(proxy="http://username:password@proxy.host:8080")
AsyncClient(proxy="127.0.0.1:8080")
AsyncClient(proxy="127.0.0.1:8080:user:pass")
```
若传入 `ip:port` 或 `ip:port:user:pass`,ViperTLS 会自动将其视为 HTTP CONNECT 代理。
## 错误处理
```
from vipertls import AsyncClient, ViperHTTPError, ViperConnectionError, ViperTimeoutError
```
## 架构
```
AsyncClient.get("https://target.com/")
│
▼
resolve_preset("chrome_145") ← ja4, ja4_r, quic_params auto-computed
│
▼
parse_ja3(preset.ja3) → JA3Spec
│
├── [proxy?] open_tunnel(host, 443, proxy_url)
│
▼
open_tls_connection(preset, ja3)
├─ pyOpenSSL SSL.Context (cffi, not ctypes)
├─ SSL_CTX_set_ciphersuites() ← TLS 1.3 cipher order
├─ SSL_CTX_set1_groups_list() ← elliptic curve order
├─ socket.setblocking(True) before handshake → fast, no retry loop
└─ ctx.set_alpn_protos(preset.alpn)
│
▼
selected_alpn_protocol()
├── "h2" → HTTP2Connection (custom SETTINGS + pseudo-header order)
├── "http/1.1" → http1_request()
└── [http3=True or alt-svc] → HTTP3Connection (aioquic, QUIC params per browser)
│
▼
ViperResponse
├── .ja4 / .ja4_r ← from preset
├── .ja4h ← computed from request headers
├── .ja4s ← computed from server hello
├── .ja4l ← connect_ms _ handshake_ms
└── .solved_by ← "tls" | "browser" | "cache"
│
▼
[403/503 + challenge markers?]
└── CloudflareSolver → Playwright Chromium → cookies → retry
```
## 托管
是的,它可以托管。它是一个 FastAPI 服务。
### Railway / Render
包含 `Procfile`:
```
web: python -m vipertls serve --host 0.0.0.0 --port $PORT
```
### Docker
```
docker build -t vipertls .
docker run -p 8080:8080 vipertls
```
### VPS / 裸金属
```
git clone https://github.com/walterwhite-69/ViperTLS && cd ViperTLS
pip install -r requirements.txt
python -m vipertls serve --host 0.0.0.0 --port 8080 --workers 4
```
### 重要托管说明
- 需要 Python 3.10+;Python 3.12 或 3.13 是最经过验证的托管运行时
- 浏览器回退需要 Playwright 系统依赖(参见系统要求)
- 在 Replit / NixOS 上:添加 NixOS 章节中的 Nix 包,然后运行 `vipertls install-browsers` —— NixOS 自动检测会跳过 `--with-deps`
- 若平台阻止系统包安装,浏览器求解可能失败,但 TLS 模式仍可工作
## 已知限制
- **无连接池** — 每个请求都会建立新的 TLS 连接
- **不支持 WebSocket**
- **不支持 SSE**
- **Cloudflare 行为持续变化** — 预设可能需要随检测更新
- **浏览器求解首次较慢**(约 20–30 秒) — 后续请求使用缓存,速度极快
## 路线图
- [x] JA4 指纹家族(JA4、JA4_r、JA4H、JA4S、JA4L)
- [x] 通过 aioquic 的 HTTP/3 / QUIC(带每个浏览器 QUIC 传输参数)
- [x] Python 3.10–3.14 支持(通过 pyOpenSSL,无 ctypes、无 CPython 版本依赖)
- [x] NixOS / Replit 自动检测(浏览器安装器)
- [ ] 连接池与长连接
- [ ] 原生 Cookie 罐 / 会话管理
- [ ] WebSocket 支持
- [ ] SSE 支持
- [ ] 更多浏览器预设(Opera GX、三星、移动版 Chrome/Safari)
## 许可证
MIT。随意使用。
**一如既往,由 Walter 制作。**
**使用 Python、pyOpenSSL、可疑的人生选择,以及对被 403 拒绝的深切厌恶。**
```标签:Cloudflare绕过, HTTP/2, HTTP/3, Python, Radare2, TLS-first, TLS指纹, TLS指纹识别, 免curl_cffi, 免Go二进制, 反反爬, 开源客户端, 指纹混淆, 无后门, 浏览器挑战, 特征检测, 纯Python, 缓存, 网络安全, 请求伪造, 逆向工具, 隐私保护