walterwhite-69/ViperTLS

GitHub: walterwhite-69/ViperTLS

纯 Python 实现的高拟真 TLS 指纹与浏览器挑战绕过工具,解决自动化请求被 Cloudflare 等识别与拦截问题。

Stars: 18 | Forks: 1

```markdown
``` ██╗ ██╗██╗██████╗ ███████╗██████╗ ████████╗██╗ ███████╗ ██║ ██║██║██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║ ██╔════╝ ██║ ██║██║██████╔╝█████╗ ██████╔╝ ██║ ██║ ███████╗ ╚██╗ ██╔╝██║██╔═══╝ ██╔══╝ ██╔══██╗ ██║ ██║ ╚════██║ ╚████╔╝ ██║██║ ███████╗██║ ██║ ██║ ███████╗███████║ ╚═══╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝ ``` **纯 Python TLS 指纹伪造与浏览器挑战回退。不依赖 curl_cffi,不依赖 Go 二进制文件,不找借口。** [![Python](https://img.shields.io/badge/Python-3.10--3.14-3776AB?style=flat-square&logo=python&logoColor=white)](https://python.org) [![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE) [![HTTP/2](https://img.shields.io/badge/HTTP%2F2-%E2%9C%93-brightgreen?style=flat-square)](https://http2.github.io) [![HTTP/3](https://img.shields.io/badge/HTTP%2F3-%E2%9C%93-brightgreen?style=flat-square)](https://http3.net) [![Cloudflare](https://img.shields.io/badge/Cloudflare-bypassed-orange?style=flat-square&logo=cloudflare&logoColor=white)](https://cloudflare.com) [![Bugs](https://img.shields.io/badge/bugs-probably%20some-red?style=flat-square)](https://github.com) [![Vibes](https://img.shields.io/badge/vibes-immaculate-purple?style=flat-square)](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, 缓存, 网络安全, 请求伪造, 逆向工具, 隐私保护