网站反爬加固 —— 5 套可落地方案
这个文件夹整理了 5 套「给个人站/小站做反爬与反自动化加固」的方案,用于以后自建站时直接取用。 每套方案对应防御纵深里的一层或几层,都是从 Cloudflare/OWASP 官方文档、公开反爬技术资料与真实站点防护行为整理而来,各附一份参考文档(讲透原理)和一份 Claude Code Skill(照着做)。
#一个核心认知(先读这句再看方案)
网页反爬的本质是经济成本博弈,不是造一座绝对攻不破的堡垒。 你每一层手段的真实作用是「抬高爬虫方的工程成本和金钱成本」,把抓你的站变得不划算,从而劝退绝大多数机会主义脚本。对有预算有决心的对手,几乎所有单一手段都有成熟的商业绕过方案。
所以正确策略是多层叠加、成本导向:用零成本手段挡掉 90% 的低质量脚本,用托管服务挡掉多数中等自动化工具,把有限预算留给真正有价值的核心数据/接口。
#5 套方案速览
| 01 托管墙 | 02 自建墙 | 03 前端风控 | 04 内容护盾 | 05 接口鉴权 | |
|---|---|---|---|---|---|
| 防御层 | 网络层+验证层 | 应用层+行为层 | 前端 JS 层 | 内容层 | HTTP+应用层 |
| 抓手 | Cloudflare 一键接入 | 限流+蜜罐+时序日志 | 指纹+无头检测 | 字体加密+结构混淆 | 签名+动态 Token |
| 开发成本 | 几乎为零 | 低(自建,0.5-2 人日) | 中 | 高 | 中 |
| 依赖第三方 | 是(Cloudflare) | 否 | 半(可用开源库) | 否 | 否 |
| 伤 SEO/体验 | 几乎不 | 不 | 轻微 | 严重(双刃剑) | 不 |
| 主要挡谁 | 通用爬虫/DDoS | 粗暴脚本/垃圾注册 | 刷单/薅羊毛/API 防刷 | 核心数据被复制 | 接口重放/批量调用 |
#怎么选
- 只想花最少力气拿到最大防护 → 直接上 01 托管墙,DNS 切到 Cloudflare 免费版,几分钟见效,个人站首选。
- 不想依赖第三方、想自己掌控 → 走 02 自建墙,Nginx + 应用层规则,零成本、零外部依赖。
- 有登录/下单/投票,怕被刷 → 加 03 前端风控,识别无头浏览器与异常设备。
- 有自己独家整理的数据不想被竞品扒走 → 谨慎评估 04 内容护盾,注意它会伤 SEO 和无障碍。
- 有开放 API 或移动端 → 用 05 接口鉴权,把接口和公开网页流量分开保护。
推荐组合(个人站现实防线):01 托管墙 + 02 自建墙 + Turnstile 无感验证。这一套零到极低成本,能挡掉绝大多数爬虫,是投入产出比最高的组合。04、05 属于按需加装的专项。
#零成本合规底座(每个站都该做,但它不拦爬虫)
robots.txt + 服务条款反爬条款不是技术屏障,恶意爬虫可完全无视。它们的价值是事后追责取证:法院会把「明知禁止仍强抓」作为认定恶意的证据。
robots.txt:声明禁止抓取的路径,零成本必做。- ToS 反爬条款:Clickwrap(主动勾选同意)效力远强于 Browsewrap(页脚放链接);登录场景下有实际法律效力,未登录访问公开页则约束力弱(参考 Meta v. Bright Data 2024)。
- 抓取公开数据在美国 Ninth Circuit 辖区(hiQ v. LinkedIn)CFAA 威慑力有限,但一旦绕过登录/付费墙/IP 封禁再继续访问,责任性质就变了。
#每个子文件夹里有什么
参考文档.md:讲清这套方案的完整原理、真实案例、破解难度与从零搭建的技术选型。SKILL.md:一份写给 Claude Code 的技能说明书,以后建站时可直接触发它照着施工。
#方案:01-托管墙-Cloudflare一键防护
#name: harden-cloudflare-managed-wall description: 给一个网站接入 Cloudflare 做零开发的托管级反爬防护(Bot Fight Mode + WAF + 限流 + Turnstile 无感验证)。当用户说「给站点加反爬」「防止被爬」「上 Cloudflare 防护」「加个验证码防机器人」时使用。
#托管墙 —— Cloudflare 一键防护
这份技能教你给一个站做托管墙:把 DNS 切到 Cloudflare,让边缘节点在流量回源前完成风控。核心铁律:能让 Cloudflare 在门口挡掉的流量,绝不放进你的服务器。
参考机制详见同目录 参考文档.md(基于 Cloudflare 官方文档与真实站点拦截行为整理)。
#什么时候用这套
- 想用最小力气拿最大防护、能接受依赖 Cloudflare → 用这套,个人站首选。
- 明确不想依赖任何第三方、要完全自己掌控 → 别用这套,用
02-自建墙那套。 - 两者建议叠加:托管墙挡外层,自建墙兜底应用层业务规则。
#架构总览
[用户/爬虫] → [Cloudflare 边缘:风险评分/挑战/限流] → [你的源站]
↑ 表单请求先过 Turnstile 校验#实现步骤(按顺序执行)
#1. 接入 DNS
- 在 Cloudflare 添加站点,把域名 NS 改到 Cloudflare 分配的地址,等生效。
- 源站 IP 记录设为 Proxied(橙色云),否则防护不生效、还暴露源站真实 IP。
#2. 开边缘防护
- 开 Bot Fight Mode(Security → Bots)。
- Verified Bots 放行:确认搜索引擎白名单开启,避免误伤 SEO。
#3. 配限流规则
- Security → WAF → Rate limiting rules,给
/login/api/*/comment等敏感路径设阈值。 - 维度尽量用 IP + Cookie/账号 组合,别只用 IP。
#4. 嵌 Turnstile 无感验证
- 登录/注册/评论表单前端引入 Turnstile widget,拿到 token。
- 后端必须调
siteverify接口校验 token 通过才处理请求。
#验收清单(务必逐条自测)
-
curl -I https://你的域名响应头出现server: cloudflare和cf-ray。 - 用数据中心 IP 的脚本狂刷敏感路径,会被限流/质询。
- Googlebot(可用 UA + 反查验证)能正常访问,未被误伤。
- 前端伪造 Turnstile token 提交,被后端
siteverify拒绝。 - 真实用户正常浏览全程无感,没被反复弹挑战。
#红线(做错就白做)
- DNS 记录没开 Proxied —— 灰色云=防护完全不生效,且泄露源站 IP,攻击者可绕过 Cloudflare 直连。
- Turnstile 只做前端不做后端校验 —— token 可伪造,等于没验。
- 限流/WAF 一刀切封 UA/国家 —— 误伤搜索引擎和真实用户,掉收录、丢流量。
- 指望免费版挡住住宅代理+真无头浏览器 —— 那是付费 Bot Management 的战场,别自欺。
#技术选型建议
- 边缘防护:Cloudflare 免费版(Bot Fight Mode + WAF Custom Rules + 基础限流)。
- 无感验证:Cloudflare Turnstile(免费无限量、隐私最好、不采集鼠标轨迹)。
- 预算允许再升 Pro(约 $20/月量级)拿 Super Bot Fight Mode 的分类别动作。
#附:只单独引入 Turnstile 加固 saveme505 密码门(不迁 DNS)
场景:站跑在 Vercel、DNS 在 vercel-dns,不想把整站迁到 Cloudflare 边缘,但想给
*.saveme505.help的统一密码门(见~/Desktop/配置信息/站点访问密码门.md)挡暴力破解。 Turnstile 可以脱离 DNS 托管独立使用,只在后台建 widget 即可,是这里性价比最高的一刀。
#为什么加在这里
11 个带门站对陌生人唯一开放的入口是 /api/login,现在防爆破只有一句 setTimeout 600ms。
脚本能并发狂刷这个接口猜 HUB_SITE_PASSWORD。Turnstile 让机器人拿不到有效 token,
后端在校验密码前就拒掉,堵的正是这个洞。
#前置(手动,只做一次)
Cloudflare 后台 → Turnstile → 建 widget,Hostname 填 saveme505.help(覆盖所有子域),
拿到一对 Site Key(公开) + Secret Key(保密),全站通用一对即可。
#改动(2 个门文件 + 每站 2 个 env)
① app/login/page.tsx(前端)
- 顶部引入脚本:
<Script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer /> - 表单里放:
<div className="cf-turnstile" data-sitekey={SITEKEY} data-callback="onTs" /> - token 存进 state,提交时
body: JSON.stringify({ password, turnstileToken }) - 拿到 token 前禁用「进入」按钮
② app/api/login/route.ts(后端,在 checkPassword 之前插入)
const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ secret: process.env.TURNSTILE_SECRET_KEY!, response: turnstileToken }),
}).then((r) => r.json());
if (!verify.success) return NextResponse.json({ error: "人机验证失败" }, { status: 403 });
// 原有的 600ms 延迟保留,作为纵深兜底③ 每个站的 Vercel 环境变量
NEXT_PUBLIC_TURNSTILE_SITEKEY(公开)TURNSTILE_SECRET_KEY(保密,别提交进仓库)
#落地顺序
先拿 hub 做试点跑通(改 2 文件 + 配 2 env + 重新部署,验证真人无感、脚本被 403), 再把改动复制到其余 10 个站,并同步进「给新站加门」的 4 文件模板里。
#边界(诚实提醒)
Turnstile 只护「登录这一步」,不护站内部的业务 API。要护那些得靠 02-自建墙 的应用层限流。
但对「密码门别被爆破」这个诉求,这一刀就够了。
#方案:02-自建墙-限流蜜罐与请求时序
#name: harden-selfhosted-anti-scrape-wall description: 在自己的 Nginx/应用层做零成本、无第三方依赖的反爬(限流 + 蜜罐字段/链接 + 请求时序日志封禁)。当用户说「不想依赖 Cloudflare 做反爬」「自己写规则防爬虫」「防垃圾注册/垃圾评论」「加个限流」时使用。
#自建墙 —— 限流、蜜罐与请求时序
这份技能教你不依赖任何第三方,在自己的服务器上做自建墙:限流卡频率、蜜罐设陷阱、日志看时序。核心铁律:每一条规则都要能区分「真人浏览器」和「脚本」,而不是无差别拦截。
参考机制详见同目录 参考文档.md(基于 OWASP/Nginx 官方文档整理)。
#什么时候用这套
- 明确不想依赖第三方、要完全自己掌控 → 用这套。
- 想花最少力气拿最大防护、能接受依赖 Cloudflare → 用
01-托管墙那套更省事。 - 最佳实践是叠加:托管墙挡外层通用爬虫,自建墙兜底业务规则(防垃圾注册/评论)。
#架构总览
[请求] → [Nginx limit_req 限流] → [应用层蜜罐校验] → [业务]
↑ ↑
Fail2ban 扫日志封 IP 时间戳陷阱校验填写耗时#实现步骤(按顺序执行)
#1. Nginx 限流
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
location /api/ { limit_req zone=perip burst=20 nodelay; }- 敏感路径(登录/评论/API)单独设更严阈值。
#2. 埋蜜罐字段
- 表单加一个 CSS 隐藏的
type="text"诱饵字段,命名website。 - 后端:该字段非空 → 静默丢弃请求(别返回错误,免得爬虫调试)。
#3. 埋时间戳陷阱
- 表单渲染时嵌入
form_render_time隐藏值。 - 提交时后端校验
now - render_time > 2s,秒填即拒。
#4. 埋蜜罐链接 + Fail2ban
- 页面放
display:none的/trap-xxx链接。 - Fail2ban 规则:访问日志出现
/trap-xxx或「只打 HTML 不拉子资源+高频」→ 封 IP 一段时间(设过期)。
#验收清单(务必逐条自测)
- 脚本高频打
/api/会收到 429。 - 自动填充所有字段(含蜜罐
website)的提交被静默丢弃。 - 表单渲染后 1 秒内提交被拒绝。
- 访问
/trap-xxx后该 IP 被 Fail2ban 临时封禁。 - 真实用户正常填表、正常浏览不被误伤,封禁能自动过期。
#红线(做错就白做)
- 限流只用 IP 维度 —— NAT 共享 IP 会误伤一片真实用户,务必叠加 Cookie/账号。
- 蜜罐用
type=hidden—— 爬虫专门跳过 hidden,必须用 CSS 隐藏正常字段。 - Fail2ban 永久封 IP —— IP 会被真实用户复用,必须设封禁时长。
- 以为这套能挡住无头浏览器 —— 完整无头浏览器能绕过,但它的资源成本被你抬高了,这就是目的。
#技术选型建议
- 限流:Nginx
limit_req(零成本首选);有业务维度需求上 Redis + Lua 滑动窗口。 - 蜜罐:前端 CSS 隐藏 + 后端判断,或
django-honeypot等现成库。 - 日志封禁:Fail2ban;想要图形化规则可自托管开源 SafeLine WAF。
#方案:03-前端风控-设备指纹与无头检测
#name: harden-frontend-fingerprint-risk description: 在前端做设备指纹 + 无头浏览器检测的风控层,护登录/下单/投票等场景防刷单薅羊毛。当用户说「防刷单」「防薅羊毛」「防批量注册」「识别无头浏览器」「加设备指纹」时使用。
#前端风控 —— 设备指纹与无头检测
这份技能教你给关键操作加前端风控层:采指纹认设备、检测揪无头浏览器。核心铁律:指纹和检测只产出风险信号,最终封禁必须结合后端综合评分,绝不靠单一前端信号下手。
参考机制详见同目录 参考文档.md(基于 FingerprintJS/botd/creepjs 等开源项目整理)。
#什么时候用这套
- 有登录/下单/投票/抽奖,怕被批量刷 → 用这套。
- 只是防内容被读取抓取 → 别用这套(性价比低),用
01-托管墙+02-自建墙。 - 建议叠在托管墙之上:Cloudflare 挡外层,前端风控护高价值操作。
#架构总览
[页面加载] → [指纹 JS + 无头检测 JS] → [加密上报] → [后端综合评分]
↓ 高风险
[拒绝 / 降级 / 二次验证]#实现步骤(按顺序执行)
#1. 接入设备指纹
- 前端引入 FingerprintJS 开源版,页面加载生成设备 ID。
- 后端存储设备 ID,用于识别「同一设备换 Cookie/换账号」。
#2. 加无头检测
const flags = {
webdriver: navigator.webdriver === true,
noChrome: !window.chrome,
swRenderer: /SwiftShader|llvmpipe/.test(getWebGLRenderer()),
};- 命中任一强信号 → 标记高风险上报。
#3. 一致性校验
- 后端比对「浏览器时区 vs IP 归属地时区」,不符加风险分。
#4. 分级处置
- 低风险放行;高风险要求 Turnstile 或短信二次验证,不直接封。
#验收清单(务必逐条自测)
- 默认 Selenium/Playwright 访问,
navigator.webdriver被检出。 - 无头 Chrome 的 WebGL 渲染器命中
SwiftShader被标记。 - 同一设备清 Cookie 后仍被识别为同一设备指纹。
- 真实用户(含用 Brave/隐私模式的)不被直接封,最多走一次二次验证。
- 上报数据是加密/混淆的,不是明文指纹字段。
#红线(做错就白做)
- 靠单一指纹直接封号 —— 隐私浏览器会让真实用户指纹漂移,误伤严重。
- 明文上报指纹信号 —— 等于把「我在采什么」告诉爬虫,一逆向就被针对性伪造。
- 只做前端不做后端评分 —— 前端 JS 可被无头环境完整执行并篡改上报值,最终判定必须在后端。
- 以为能挡住 stealth 工具 —— puppeteer-stealth 类专门 patch 这些痕迹,你挡的是没伪装的大多数,不是全部。
#技术选型建议
- 指纹:FingerprintJS 开源版(MIT,免费);商业 Pro 版性价比对个人站一般,除非有明确反薅羊毛业务。
- 无头检测:botd/creepjs 的检测清单自建,先做
navigator.webdriver+ WebGL 强信号。 - 二次验证:Cloudflare Turnstile(无感、免费)。
#方案:04-内容护盾-字体加密与结构混淆
#name: harden-content-obfuscation-shield description: 用字体 glyph 映射、CSS 排序混淆、结构随机化保护网页核心数据(价格/评分/独家数据)不被直接抓 DOM 复制。当用户说「防止核心数据被扒」「价格/数据被抄」「内容防复制」「字体加密」时使用。注意:这套会伤 SEO 和无障碍,务必先评估。
#内容护盾 —— 字体加密与结构混淆
这份技能教你给核心数据做内容层混淆:让直接抓 DOM 拿到乱码。核心铁律:只护真正值钱的核心数据,绝不全站铺开——这是会伤 SEO 和无障碍的双刃剑。
参考机制详见同目录 参考文档.md(基于点评/票务类站点公开渲染行为整理)。
#什么时候用这套
- 有自己独家整理的数据(报价体系/数据库)不想被竞品直接复制 → 谨慎评估后用。
- 只是普通内容站、希望被搜索引擎良好收录 → 别用这套,它会掉收录,用
01+02即可。 - 用之前先自问:护这份数据的收益,真的大于掉 SEO + 伤无障碍 + 伤复制体验吗?
#架构总览
[服务端渲染] → 核心数字用自定义字体编码替换(1→a) → 下发乱码HTML+字体文件
↓
[浏览器加载字体渲染→人看到正确值]
[搜索引擎→走白名单拿正常内容]#实现步骤(按顺序执行)
#1. 先上零成本的结构随机化
- 用 CSS Modules / CSS-in-JS,class 名自动随机化,破坏固定选择器爬取。这一步几乎无副作用,先做。
#2. 核心数据上字体映射
- 用 fonttools 生成子集化字体,把字符做 glyph 重映射(如
1→a)。 - 服务端渲染时把真实数字替换成映射字符,配套下发该字体文件。
#3. 给搜索引擎开例外
- 对 Verified Bots(真 Googlebot/Bingbot)下发正常未混淆内容,否则收录乱码。
#4. 定期轮换映射表
- 排期轮换 glyph 映射,避免爬虫逆向一次长期复用。
#验收清单(务必逐条自测)
-
curl直接抓页面,核心数字位置是乱码/无意义字符。 - 真实浏览器打开,数字正常显示。
- Googlebot(验证过的真爬虫)拿到的是正常内容,收录不受影响。
- 评估过并接受:屏幕阅读器、用户复制粘贴对混淆内容的影响。
- 映射表有轮换计划,不是一次性写死。
#红线(做错就白做)
- 全站正文都上字体混淆 —— 杀敌一千自损八百,SEO 和无障碍全崩。
- 不给搜索引擎开例外 —— Googlebot 抓到乱码,收录直接归零。
- 映射表永不轮换 —— 爬虫逆向一次长期复用,等于没防。
- 以为能挡住所有爬虫 —— 内容终究要显示给人,能截图就能 OCR,你挡的是省事爬虫。
#技术选型建议
- 结构随机化:CSS Modules / CSS-in-JS(零成本,先做这个)。
- 字体处理:fonttools(Python 开源库)做子集化 + glyph 重映射。
- 搜索引擎例外:结合 CDN 的 Verified Bots 白名单。
- 强烈建议:能用前四套方案解决就别碰这套,它的维护成本和副作用最高。
#方案:05-接口鉴权-签名与动态Token
#name: harden-api-auth-signing description: 给开放 API / 移动端接口加鉴权防重放(Referer/Origin 校验 + CSRF Token + 动态 Nonce + HMAC 签名/OAuth2)。当用户说「接口防重放」「API 防刷」「保护开放接口」「加签名鉴权」「防止接口被直接调用」时使用。
#接口鉴权 —— 签名与动态 Token
这份技能教你给接口加鉴权:用一次性、限时、可验证的凭证把重放请求逼成多步交互。核心铁律:密钥绝不硬编码到前端 JS 或移动端 APK——那是全套防线的命门。
参考机制详见同目录 参考文档.md(基于 AWS SigV4 / OAuth 官方文档整理)。
#什么时候用这套
- 有开放 API 或移动端 App,接口被直接调用/重放 → 用这套。
- 纯 Web 展示站、只是防内容被读 → 别用这套(过度设计),用
01+02。 - 可与
03-前端风控配合:鉴权管「凭证合不合法」,风控管「环境可不可疑」。
#架构总览
[客户端] --签名(HMAC+timestamp)--> [服务端复算校验+时间窗口] --> [业务]
↑ 密钥只在服务端,客户端转发已签名请求#实现步骤(按顺序执行)
#1. 打底:来源校验
- Nginx
valid_referers/ 框架 CSRF 配置,挡掉不带 Referer/Origin 的懒脚本。
#2. 写操作加 CSRF Token
- 用框架内置 CSRF 中间件(Django/Rails/Spring Security),护住 POST/PUT/DELETE。
#3. 关键操作加动态 Nonce
- 渲染时签发一次性 nonce 存 Redis(带 TTL + 限用一次),提交时校验并作废。
#4. API 加 HMAC 签名
signature = HMAC(secret, method + path + body + timestamp)- 服务端复算比对 + 校验
timestamp在 ±5 分钟窗口内。 - secret 只存服务端;移动端若必须持有,走安全存储 + 混淆,并接受被逆向的残余风险。
#验收清单(务必逐条自测)
- 不带 Referer/Origin 的请求被拒。
- 抓一个合法请求原样重放,因 timestamp 过期/nonce 已用而失败。
- 篡改请求体后签名校验失败。
- CSRF Token 缺失/错误时写操作被拒。
- 全局搜代码,确认密钥没有硬编码进任何前端/客户端产物。
#红线(做错就白做)
- 密钥硬编码进前端/APK —— 逆向即提取,签名逻辑被复现后零成本重放,全套失效。
- 签名不含时间戳/无有效窗口 —— 一个合法签名可无限重放。
- OAuth 注册零门槛 —— 批量注册马甲账号绕过一切限流。
- 为纯 Web 站单独引入 HMAC —— 过度设计,密钥必然下发、易逆向,性价比低。
#技术选型建议
- 来源/CSRF:框架内置能力(Django/Rails/Spring Security),零额外成本。
- 动态 Nonce:Redis + TTL 自建(简单版 1-2 人日)。
- 签名:AWS SigV4 或自实现 HMAC;网关侧 Key 管理用 Kong / APISIX。
- 身份:OAuth2,托管用 Auth0/Okta,自建注意加注册门槛。
来源:沉淀/反爬机制/README.md 及其下 5 套 SKILL.md(01-托管墙 / 02-自建墙 / 03-前端风控 / 04-内容护盾 / 05-接口鉴权)(整理于 2026-08-18)