BOSh
文章321
标签521
分类135
315晚会 36氪 80后 ADB AI AI Agent AI PC AI 代理 AI 助手 AI 网关 AI 评测 AI代理 AI助手 AI处理器 AI大模型 AI安全 AI应用 AI智能体 AI网关 AMD API API 集成 AWS Agent Agentic AI AionUi Alwaysdata Android Apple Arch Linux Argo Tunnel Automation Backup Bash Bosh Bot Bot-hosting C++ CDN CEO CI/CD CLI CLI Proxy API CLIProxyAPI COMPUTEX CRM Chrome 插件 Claude Claude Opus 4.6 Cloudflare Code ConnectBot Credential Manager Ct8.pl CurrentEvents DNS Debian DeepSeek DenchClaw DevOps Devil Docker Elon Musk FreeLLMAPI GCP GEO GPL GPS GPU Gemini Gemini 3.1 Pro Ghostty Git GitHub GitHub Actions Gmail Go Gog Golang Google Google AI Pro Google API Google Gemini Google Photos Google Pixel HKUDS Hardware Hermes Hermes Agent Hexo HidenCloud Hugo Hyprland IPV6 Intel JavaScript Jetpack Compose John Turnus KDE KOSPI Karpathy Kimi-K2.5 Kotlin LINUX LLM LTS LaTeX Linux LiveUSB MW4L Markdow Markdown Matrix MemU Bot Mesh-Network MiniMax Musk NAT64 NIX NODE NVIDIA NVIDIA Build NanoClaw Netcatty Netlify Newsletter Node.js Nvidia Open WebUI OpenAI OpenAI 兼容接口 OpenAI兼容 OpenCLI OpenClaw P2P PDF 编译 Pacman PicoClaw Pixel Pixel 1 Pixel 12 Pixel11 Plasma Prismer Productivity Pura90 Python QClaw QQ机器人 Qualcomm Quickshell RAG RTX Spark Railway Reddit Rust SFTP SSH SeleniumBase Serv00 Serverless Skills SoC Subagent SuperCall Synapse Syncthing TPU TSMC Tailscale Telegram Telegram Bot Tensor Tensor G7 Tim Cook Tunnel Turnstile Ubuntu VLESS VPN VPS Vercel Wayland WeChat Web3 WebSSH WebSocket WebTransport Web开发 Windows WireGuard WorkBuddy X XChat XHTTP X热榜 YouTube ZeroClaw arXiv arch c++ cc-switch cloudflared ct8.pl email git hugo hyprmod i3wm iMessage iOS n8n nanobot node js ntfs pacman podman zz.ac 东海 两性关系 个人助理 中东 中东冲突 中东局势 中关村论坛 中南大学 中国 中美 乌克兰 习惯养成 云同步 云服务器 亚洲 人性 人教版 代理 代金券 以色列 任务管理 伊朗 伊朗危机 伊朗战争 伦理 体育 使用 俄乌战争 俄罗斯 保护主义 信息流 信息管理 停火 健康管理 光通信 免费VPS 免费主机 免费试用 全球动态 六年级 共和党 关系 养老金 内容工厂 内容生产 内容筛选 内网穿透 军事冲突 军事动态 军民融合 农村 分享 分配 创业 制裁 办公自动化 加密 加密货币 加沙 北斗 北韩 医学生 半导体 华为 协议分析 博客 博客助手 博客发布 博客部署成功 卫星 即时通讯 厄尔尼诺 原生 JS 去中心化 反向代理 反思 反爬虫 反重力 台海局势 台湾 命令 命令行 喷嚏网 国产 国产化 国产替代 国际 国际关系 国际局势 国际新闻 图卦 图说 地缘政治 域名邮箱 基础设施 多代理 多模态AI 大学分析 大模型 孙少平 学习 安全 安装 实时监控 家庭助理 家庭服务器 家装设计 小学 工业策略 工作总结 工作效率 工作流编排 工具 工具链 平凡的世界 平台责任 庞氏骗局 开发 开发实录 开源 开源软件 开源项目 张雪峰 微信 心理健康 快捷键 情感 慈善 战争 房地产 手机 技术分享 投资工具 指标看板 提示词工程 播客 收件箱清理 效率 效率工具 教程 教育制度 数学 数据分析 数据投毒 文件管理 文献管理 新能源汽车 新闻汇总 日历聚合 时事 时事总结 显卡 晨报 智能体 智能体生态 智能手机 服务器部署 朝鲜 极端天气 架构 架构实践 核协议 核武器 桌面Cowork 桌面环境 模型接入 模型配置 欧洲安全 每日图说 比亚迪 气候 油价 法律 活动运营 浏览器自动化 消息通道 消费者权益 深度学习 渔船 游戏开发 湘雅医院 潘石屹 热点新闻 熔断 版本更新 特朗普 生态系统 生活 生活自动化 生物识别 用例 甲骨文云 电池技术 症状追踪 白嫖 白嫖攻略 白山云 皮皮虾 监管 目标管理 知识库 社交媒体 社会保障 社会公平 社会百态 社会观察 科技 科普 科研助手 窗口管理 笔记 第一财经 算法 算法推荐 系统管理 纽森 组网 经济 经济观察 经验分享 编程 网关 网络 网络安全 网络摘录 网络穿透 美伊冲突 美伊谈判 美国 美国制裁 美国大选 美国政治 股灾 能源安全 脚本 腾讯 腾讯,龙虾,OpenClaw 腾讯云 自动化 自动化创作 自动化协作 自动化提醒 自动化流水线 自动化脚本 自动化运维 自建服务 自律教练 自托管 自由软件 芯片 草榴 行为改变 视频摘要 解锁 计算摄影 记录 许可证 论文写作 论文阅读 语义搜索 语音代理 读书 读书笔记 读后感 谷歌云 财报季 路遥 身份验证 轻量级 迁移 运维 进化论 远程访问 远程运维 选车 邀请确认 部署 部署指南 部署教程 量子计算 销售自动化 阅读感悟 随笔 隐私 霍尔木兹 霍尔木兹海峡 青蛙机 韩国股市 韩红 韬定律 项目管理 风险管理 飞书 高中生活 高可用 高考 高考志愿 鸽巢原理 麒麟 麒麟9050 黄仁勋 黎巴嫩 龙虾

一言

文章归档

Turnstile 验证绕过 — 处理 Cloudflare 机器人检测

Turnstile 验证绕过 — 处理 Cloudflare 机器人检测

Cloudflare 的 Turnstile 是目前网站防机器人的主流方案之一。很多免费托管平台、注册页面、续费页面都套了这个。这篇文章拿 eooce/Auto-Renew-Bothosting 这个开源项目开刀,把它怎么绕 Turnstile 这件事,从头到尾讲清楚。


Turnstile 是什么?先搞明白你在对抗什么

Turnstile 是 Cloudflare 2022 年推出的 CAPTCHA 替代方案。和老式的图片验证码(点消防栓、识别红绿灯)不同,Turnstile 大多数时候对用户"无感"——你看到的就是一个转几圈的小圆圈,然后自动通过。

它怎么判断你是不是机器人?靠的是一套"客户端信号":

  • 浏览器指纹:UA、语言、屏幕分辨率、插件列表……
  • 行为特征:鼠标轨迹、点击习惯、页面停留时间
  • 网络特征:IP 信誉、ASN、是否走了代理或 VPN
  • JavaScript 执行环境:有没有 WebDriver 痕迹、有没有被自动化框架劫持

正常浏览器 + 正常用户的信号组合,Turnstile 直接放行。你用 requests 发个 HTTP 请求,什么信号都没有,直接被拦。


项目架构:这个脚本干的是什么

Auto-Renew-Bothosting 是一个自动续期脚本,目标是 bot-hosting.net 这个免费 Discord Bot 托管平台。免费账户需要定期手动点续期按钮,否则到期自动下线。这个脚本就是用来替你自动做这件事的。

整体流程如下:

1
注入 Cookie → 打开账单页 → 找到续期按钮 → 触发 Turnstile → 绕过验证 → 点击确认续期

工具链:SeleniumBase(UC 模式)+ Python


核心绕过:uc_gui_click_captcha() 是关键

先看这段代码:

1
2
3
sb_kwargs = {"uc": True, "headless": HEADLESS}
with SB(**sb_kwargs) as sb:
...

注意 uc=True。这里的 uc 是 SeleniumBase 的 Undetected-Chromedriver 模式,缩写自 undetected_chromedriver

普通 Selenium 启动的 Chrome 有明显的 WebDriver 特征,Cloudflare 一眼就能识别出来:navigator.webdriver === true、Chrome 的自动化扩展 ID、DevTools 端口开放……Turnstile 全都会检测到,然后给你上 Challenge。

UC 模式干了什么:

  1. 对 ChromeDriver 二进制做 patch,移除可被检测的特征字符串
  2. 启动时注入 JS,把 navigator.webdriver 改成 undefined
  3. 伪装浏览器指纹,让 Chrome 看起来像正常用户手动打开的

这样 Turnstile 拿到的信号,就是一个"看起来正常"的浏览器环境。


Turnstile 检测循环:三次重试机制

1
2
3
4
5
6
7
8
9
10
11
12
13
turnstile_passed = False
for attempt in range(1, 4):
try:
sb.uc_gui_click_captcha()
time.sleep(8)
except Exception as e:
print(f"⚠️ 点击 Turnstile 出错: {e}")

if wait_for_turnstile_pass(sb, timeout=20):
turnstile_passed = True
break
else:
print(f"⏳ 第 {attempt} 次未通过,重试点击...")

uc_gui_click_captcha() 是 SeleniumBase 封装的方法,底层用 PyAutoGUI 模拟鼠标点击——不是 Selenium 的 click(),而是操作系统级别的 GUI 点击。

为什么要用 GUI 点击?因为 Turnstile 的 iframe 是跨域的,Selenium 的 JavaScript click() 无法穿透跨域 iframe 去触发它。操作系统级别的鼠标事件不受这个限制,直接落到屏幕坐标上,Turnstile 收到的就是一个"真实"的点击。

time.sleep(8) 是给 Turnstile 的判断逻辑留时间。它不是即时的,需要几秒钟跑完客户端信号采集和服务端校验。

三次重试是经验值:网络抖动、页面加载延迟都可能导致第一次失败,多试几次成功率明显提升。


wait_for_turnstile_pass:怎么判断是否通过

1
2
3
4
5
6
7
8
9
10
11
def wait_for_turnstile_pass(sb, timeout=30):
start = time.time()
cf_indicators = ["verify you are human", "确认您是真人", "troubleshoot", "just a moment"]
while time.time() - start < timeout:
page_lower = sb.get_page_source().lower()
if not any(x in page_lower for x in cf_indicators):
print("✅ Turnstile 验证已通过")
return True
sb.sleep(1)
print("❌ Turnstile 验证超时未通过")
return False

思路很朴实:轮询页面源码,只要不包含这些 Cloudflare 特征文字,就认为通过了。

这里有个值得注意的点:它检测的是"不包含"而不是"包含某个成功标志"。因为 Cloudflare Challenge 页面有固定的文本,正常页面不会有。这种方式比找成功标志更通用——不管目标网站长什么样,只要 CF 的拦截页消失了,就说明通过了。


1
2
3
4
5
6
7
8
9
COOKIES = {
"session_token": SESSION_TOKEN,
"login": "true",
"theme": "system",
}

for name, value in COOKIES.items():
if value:
sb.add_cookie({"name": name, "value": value, "domain": "bot-hosting.net"})

脚本不走正常登录——不输用户名密码,直接注入已有的 session_token Cookie。

好处:

  • 避开了登录页可能存在的额外 Turnstile 验证
  • 速度快,减少被检测的窗口期
  • 账号密码不需要写进脚本,更安全

session_token 从环境变量读取,配合 GitHub Actions Secrets 使用。Token 过期时,脚本会自动通过 gh CLI 更新 Secret:

1
2
3
4
5
proc = subprocess.run(
["gh", "secret", "set", secret_name, "--body", new_value],
capture_output=True, text=True, timeout=30, check=False,
env=env
)

这个设计挺聪明——自动化续期本身顺便维护了自己的凭据。


到期日期提取:正则硬核匹配

1
2
3
4
5
6
patterns = [
r"[Ee]xpires\s*[:\-]?\s*(\d{4}/\d{2}/\d{2})", # Expires 2026/07/07
r"[Ee]xpires\s*[:\-]?\s*(\d{2}/\d{2}/\d{4})", # MM/DD/YYYY
r"(\d{4}/\d{2}/\d{2})\s*[\-–]\s*renew",
r"(\d{2}/\d{2}/\d{4})\s*[\-–]\s*renew",
]

写了四个 pattern,处理了日期格式不统一的问题(YYYY/MM/DD 和 MM/DD/YYYY 两种)。遇到 MM/DD/YYYY 还做了格式转换,统一成 YYYY/MM/DD 输出。

这种写法的问题是:一旦目标网站改了页面结构或日期格式,就失效了。但对于稳定运行的小工具来说,够用。


代理支持:应对 IP 封禁

1
2
3
4
5
IS_PROXY = os.environ.get("IS_PROXY", "false").lower() == "true"
PROXY_SERVER = os.environ.get("PROXY_SERVER", "").strip() or "http://127.0.0.1:1080"

if IS_PROXY:
sb_kwargs["proxy"] = PROXY_SERVER

如果你的服务器 IP 被 Cloudflare 判定为高风险(数据中心 IP、共享 IP、有历史恶意记录),Turnstile 会直接上 Challenge 甚至直接拒绝。这时候挂个住宅代理或低风险代理,成功率会高很多。


局限性和注意事项

这套方案不是银弹:

  1. Headless 模式成功率低HEADLESS=true 时,Cloudflare 更容易识别出无头浏览器。脚本默认 headless=false,在有桌面环境(或 VNC)的机器上运行。
  2. IP 质量影响极大:GitHub Actions 的公共 runner IP 是常见的数据中心 IP,Cloudflare 对这类 IP 的验证门槛更高。
  3. 不适合高频调用:这个脚本是每天跑一次的续期工具,不是高并发爬虫。高频使用 UC 模式容易触发更严格的检测。
  4. 目标网站随时可能加固:Cloudflare 在持续更新检测逻辑,今天能过不代表下个月还能过。

小结

整个 Turnstile 绕过模块的核心就三个东西:

  • SeleniumBase UC 模式:伪装成正常浏览器,移除 WebDriver 特征
  • uc_gui_click_captcha():操作系统级鼠标点击,穿透跨域 iframe
  • 轮询页面源码:用 CF 拦截页特征文字判断是否通过

思路不复杂,工程细节是难点。适合用来理解"自动化脚本为什么能过 Cloudflare"这个问题——当然,也适合你自己搭类似工具时参考。

至于用于商业爬虫或绕过有明确禁止条款的网站?那不在本文讨论范围。


本文由 BOSH 的博客助手 HerMes 整理 🤖

原文链接:https://github.com/eooce/Auto-Renew-Bothosting/blob/main/app.py

本文作者:BOSh
本文链接:http://bosh.zz.ac/posts/107189741.html
版权声明:本文由BoSh发布,部分内容来源于网络。