环境:阿里云 ECS · Windows Server 2019 Datacenter (17763) · 4 GB 内存 · XAMPP / Apache 2.4 · WordPress · 云锁客户端 · 域名 511yj.com
.htaccess 用「A 版底子 + 搜索引擎放行 + 字体补全 + Google 多后缀」这一版;B 版(拦空 Referer)永远不要上;云锁防盗链例外里只补 google.com(裸域名,不是路径);cnblogs 不加、原有七条不删、不勾允许空 Referer。
一、现象与定性:8214 条日志到底是什么
防护日志里 2026-11-11 ~ 11-12 共 8214 条、83 页(单页 100 条),几乎全是「防盗链 / 盗链防护(会话方式) / 已被拦截」。典型一条:
2026-11-12 22:33:27 防盗链 113.24.225.235(中国山西长治) 访问 www.511yj.com/wp-content/uploads/2016/07/511yujian25.jpg 触发规则:盗链防护(会话方式),已被拦截。 (http://www.cnblogs.com/xiager/p/6855533.html 正在盗链您的资源)
同一秒里 .235 / .29 / .73 / .96 各来一条、全是 511yujian*.jpg —— 这是一个外部页面里嵌了四张图,浏览器并发加载,不是四个攻击者。波兰、法国、美国、大连、南京那些 IP 同理,是外站读者点开旧文、图片缓存服务、爬虫各来一次。
- 8214 是两天累计,按时间倒序显示,不是「十分钟八千次」,也不是攻击爆发。
- 日志条数 ≠ 服务器负载。这些
.jpg被挡在 Apache 外面,不进 PHP、不查库、不读磁盘上的图,单次成本只是「匹配一次 Referer 规则 + 写一条日志 + 回一段响应」。约每小时 170 次,对 4G 机器很轻。之前 CPU 冲 100% 又掉回 2% 那波,是/index.php动态请求 + 扫描并发 + 弹窗重绘的瞬时尖峰,和这些被秒拒的图片不同步。 - 博客园那篇是别人的站(作者 xiager),你没权限改它的 HTML、删不了它引用的 img 标签。「去把那篇旧文的图搬走」是站着说话不腰疼,做不到。
所以真正能做的,不是让请求消失(只要对方 HTML 还指向 www.511yj.com,DNS 就解析到你 ECS,TCP 就得建一次),而是决定「它来时这台机器用多小的代价把它打发掉」。
二、先分清三层,不然一定改错地方
| 层 | 在哪 | 它干什么 | 能不能动 |
|---|---|---|---|
| 别人的 HTML | 博客园等外站 | 写着 <img src="https://www.511yj.com/..."> 或 <link href=".../bootstrap.min.css"> |
动不了 |
| 云锁「网站防盗链」 | 本地云锁客户端,Apache 之前 | 按 Referer 判来源,非法来源回一整页 5758 字节「网站防火墙」HTML | 能改例外名单、拦截文案 |
Apache .htaccess |
C:\xampp\htdocs\.htaccess |
第二道保险,按 Referer + 后缀回 403 |
能改,本文重点 |
关键认知:防盗链不是「拒收」,是「收进来、判一下、再回一个拦截页」。所以它会占一点 CPU 和出站带宽,但没有把真图供出去。云锁在 Apache 之前,带外站 Referer 的请求已经被它截了,根本到不了 .htaccess —— 所以新加的 Apache 规则是双保险,补的是「云锁被切回监控模式 / 漏判 / 空 Referer」那部分,不追求在 curl 里看到 403。
三、云锁「网站防盗链」:例外名单是放行列表,不是黑名单
设置页那份「网站例外名单」里原有七条:
baidu.com so.com sogou.com bing.com bbs.511yj.com weibo.com qq.com
标题写得清楚:「加入到例外名单的项,不再受此功能的保护」。也就是这七条是允许的来源(给搜索引擎收录、微博 / QQ 分享、自己 bbs 子域看的)。cnblogs 不在里面,所以博客园那篇取图被拦 —— 和日志完全对得上。
- 七条一条都别删:删了会误伤 SEO 收录和 bbs 引用主站资源。
- 绝不加
www.cnblogs.com:目标是拦,不是放行。上一轮把「放行 cnblogs」摆成选项是跑偏的。 - 不勾「允许空 Referer / 允许直接访问」(如果面板有这一项)。
- 「拦截信息提示」那个长文本框只是 HTML 页里的文案,清空或改成短词可以让拒绝更便宜;不影响拦截逻辑。右下「恢复默认配置」别点,一点把所有例外全清。
监控模式只记日志不拦,防护模式真拦并返回「网站防火墙」页。别人以前能用你的 css/js,很可能是当时在监控模式;切到防护模式后,实测 Referer: https://www.cnblogs.com/ 和空 Referer 都返回 200 text/html(拦截页),说明云锁两层都拦住了。
切到防护模式后观察两天:WP 后台发文章、前台含代码 / SQL 示例的页面有没有被误拦。真被拦就去防护日志看是哪条规则,按规则加白,不要整体关防护。
为什么 CSS / JS 也会被外站用
防盗链默认按 Referer 判「图片等资源」,对 .css / .js 这类静态文本资源检查常偏松;再加上 ExpiresByType text/css "access plus 1 year",外站一旦把 <link> 引进去,浏览器缓存一年,二次请求甚至不带 Referer。三种漏口:
- 请求不带 Referer(直接
script src/link,或缓存后不再发 Referer) - 用了
rel="noreferrer"/Referrer-Policy: no-referrer - 来源站被列进了例外名单(cnblogs 不在,所以这条不成立)
云锁这层加不了严:它的防盗链设置里只有「例外名单 + 拦截信息提示」,没有「文件类型」「空 Referer」开关。要按后缀锁死 css/js,只能靠下面的 .htaccess。
四、Apache 层:最终版 .htaccess 片段
先答一个常问的:<IfModule mod_rewrite.c> / RewriteEngine On / RewriteBase / 这三行不是要新增的东西,是文件里 # BEGIN WordPress 下面早已存在的外壳。别再新起一个块,直接把规则插进现有块内部。
精确插入点:两条裸域 301 之后、RewriteRule ^index\.php$ - [L] 之后、/weixin/ 与 Super Static Cache 之前。原因:301 要最先把 Host 统一;缓存那两条 [L] 会终止本轮重写,规则放它后面就永远跑不到。
# ---- HTTP → HTTPS + www(原有,不动)----
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?511yj\.com$ [NC]
RewriteRule ^(.*)$ https://www.511yj.com%{REQUEST_URI} [L,R=301]
# ---- HTTPS 但仍是裸域 → 补跳 www(原有,不动)----
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^511yj\.com$ [NC]
RewriteRule ^(.*)$ https://www.511yj.com%{REQUEST_URI} [L,R=301]
RewriteRule ^index\.php$ - [L]
# ===== 静态资源防盗链(最终版,就放这里)=====
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?511yj\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://bbs\.511yj\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([a-z0-9-]+\.)?(baidu|so|sogou|bing|weibo|qq)\.com(\.cn)?/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://([a-z0-9-]+\.)?google\.(com|com\.hk|co\.jp|co\.uk|cn)(\.[a-z]{2})?/ [NC]
RewriteRule \.(jpe?g|png|gif|webp|ico|svg|css|js|woff2?|ttf|eot|otf)$ - [F,NC]
# ===== /weixin/ 动态取件目录(原有,不动)=====
RewriteRule ^weixin/ - [L]
# ===== Super Static Cache 开始(原有,不动)=====
这一版定死的几件事
| 决定 | 理由 |
|---|---|
保留 !^$(A 版底子) |
空 Referer 交给云锁拦,Apache 不重复下手。且 Googlebot、图片爬虫、访客新标签直接打开图片常不带 Referer,删了会误伤收录。 |
B 版(删掉 !^$)永远不上 |
实测空 Referer 已经被云锁回 200 text/html,删掉零收益;只带来搜索引擎图片 / 社交抓取 / 缓存复用的误伤。 |
| 搜索引擎对齐云锁原有七条 | 云锁已放行 baidu / so / sogou / bing / weibo / qq,Apache 若不放行等于白放行还伤收录。([a-z0-9-]+\.)? 覆盖 image.baidu.com、pic.sogou.com、cn.bing.com 这类子域。 |
| Google 单独一条多后缀 | 并进单行版会漏 google.com.hk / google.co.jp —— (\.cn)? 只兼容 .com.cn / .cn。用两行版不留漏口。 |
用 RewriteRule 判后缀,不用 REQUEST_URI |
本站 CSS 全带 ?ver=1791971959,%{REQUEST_URI} 含 query string,$ 锚不到 .css 结尾,规则会整个跳过。RewriteRule 匹配不含 query 的路径,自动剥掉 ?ver=。 |
[F] 不写 [L] |
不是漏项,[F] 隐含 [L]。403 比云锁回 5758 字节 HTML 便宜得多,正是「把拒绝做便宜」。 |
补 ttf|eot|otf |
font-awesome 老版本字体一起锁住。 |
/.well-known/acme-challenge/<token> 无后缀、probe.txt 是 .txt,都不进正则;/wp-admin/load-styles.php 是 .php,WP 后台不会裂;Super Static Cache 内部重写到 .gz 后,内层第一句 RewriteRule ^super-static-cache/ - [L] 先终止,第二轮不会再跑防盗链。1/5 自动续期不受影响。
C:\xampp\htdocs\.htaccess,只管主站。bbs.511yj.com 是独立 DocumentRoot(C:/xampp/htdocs/bbs),有自己那份 .htaccess,这段对它不生效。写的 !^https?://bbs\.511yj\.com/ 是放行「bbs 页面引用主站 CSS」,方向没错。外站若引的是 bbs 自己的图片,得单独在 bbs 那份里补(且要先补 RewriteEngine On),先别开新线。
五、Google 怎么加:两边写法不一样,别填串
1)云锁防盗链例外 —— 填「裸域名」
应用防护 → 网站防盗链 → 白名单设置 / 例外名单- 点「新增」,输入框逐条填:
google.com - 点「加入例外 / 确定」,回到设置页再单独点一次「保存」
- 先只加这一条,观察两天防护日志里还有没有
google...被拦,有再补google.com.hk
格式:裸域名,不带 https://、不带路径、不带端口、不带星号。多数面板对 google.com 会连带匹配 www.google.com 这类子域。
· 防盗链这页要来源域名:
google.com· 那两页要路径:
/.well-known/acme-challenge/别把
google.com 加到 ACME 那两页,也别把路径加到防盗链。切左侧菜单时看清标题是「网站防盗链」。
2).htaccess —— 用上面的两行版
即「原 7 家」一条 + 「Google 多后缀」一条并列,别两条都塞进同一个括号里图省事。Google Search Console 的「抓取诊断」测不出这两行加没加对:Googlebot 通常不带 Referer,走的是 !^$ 那条。要验就用下面手工带 Referer 的 curl。已收录链接不用重新提交、不用改 robots.txt、不用动 sitemap。
六、验证:命令与判读
先备份。.htaccess.bakN 会被 <FilesMatch "^\.ht"> 挡住,不会被下载。.htaccess 即时生效,不用重启 Apache。
copy C:\xampp\htdocs\.htaccess C:\xampp\htdocs\.htaccess.bak5
ECS 上把 probe 放回去(这台机器 curl.exe 被本机拦截,只用 CMD 内置命令):
mkdir "C:\xampp\htdocs\.well-known\acme-challenge" 2>nul echo ok> C:\xampp\htdocs\.well-known\acme-challenge\probe.txt
在本地电脑(zcp52)跑,全部完整 URL、无省略号:
curl.exe -s -o nul -w "self=%{http_code} %{content_type}\n" -H "Referer: https://www.511yj.com/" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "baidu=%{http_code} %{content_type}\n" -H "Referer: https://image.baidu.com/" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "google_com=%{http_code} %{content_type}\n" -H "Referer: https://www.google.com/" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "google_hk=%{http_code} %{content_type}\n" -H "Referer: https://www.google.com.hk/" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "cnblogs=%{http_code} %{content_type}\n" -H "Referer: https://www.cnblogs.com/" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "empty=%{http_code} %{content_type}\n" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
curl.exe -s -o nul -w "acme=%{http_code} %{content_type}\n" "https://www.511yj.com/.well-known/acme-challenge/probe.txt"
| 条 | 必须是 | 说明 |
|---|---|---|
self |
200 text/css | 本站必须正常,否则就是规则写错 |
baidu |
200 text/css | 若回 200 text/html,是云锁白名单没覆盖 image.baidu.com 子域,去防盗链例外补一条即可,不改 .htaccess |
google_com |
200 text/css | 云锁放行 + .htaccess 放行,两层都过 |
google_hk |
200 text/css | 两行版就过;若单行版会 text/html,去云锁补 google.com.hk |
cnblogs |
200 text/html |
云锁在 Apache 之前先拦成 HTML 页,测不到新规则,正常 |
empty |
200 text/html |
空 Referer 也已被云锁拦。这正是「B 版零收益」的实测证据 |
acme |
200 text/plain | probe 文件放回去就对了 |
① 别拿
cnblogs / empty 判断新规则生没生效 —— 它们都在云锁层被截了,到不了 Apache。这层是双保险,不追求在 curl 里看到 403;真看到 403 反而说明云锁没拦住。②
acme=404 不是被防盗链拦的。[F] 回的是 403,404 是 Apache 的 Not Found,只说明 probe.txt 不在磁盘上(被删了,或被 Validation.CleanupFolders: true 清掉)。把文件放回去即可,跟证书路径无关。
self 不是 200,或 acme 不是 200,就回退,即时生效:
copy C:\xampp\htdocs\.htaccess.bak5 C:\xampp\htdocs\.htaccess
测完删掉 probe.txt。
七、ACME 例外:和防盗链弹窗长得像,但不是一回事
之前给「网站漏洞防护」和「抗CC攻击」加的 */.well-known/acme-challenge/ 是路径例外,按功能隔离,防盗链不认。实测 www / bbs 两条 probe 都是 200 text/plain 4。目录平时不存在是正常的 —— wacs 续期时自己 mkdir → 写无扩展名 token → 验证完删掉,例外名单存的是路径字符串,不要求目录当前存在,直接手打即可。
抗 CC 阈值是 60 秒 200 次 / 锁定 300 分钟,三个域名一共几个 GET 连零头都够不到,「脚本验证跳转方式 HTTP 200 / 302」保持默认 200 别动 —— 真被挑战,两种都拿 HTML 而不是 token,关键从来是别触发。
八、顺带核查过的云锁设置:全部保持原样
| 页 / 项 | 现状 | 结论 |
|---|---|---|
| 允许的请求类型 | GET / POST / HEAD |
全齐,别加 OPTIONS / PUT / DELETE / TRACE。GET 覆盖 LE 回读 token |
| 禁止下载的文件类型 | db mdf log mdb dat myd bak sql md |
合理。没有 css/js/png/gz 是对的,尤其别加 gz(首页缓存本身就是 index.html.gz) |
| 网页浏览实时防护后缀表 | asa / asp / aspx / cgi / jsp / php / php3 / php5 / php7 / phtml … | 防源码被当文本读,不阻断 PHP 执行。别删 php、别加 html / gz。ACME token 无后缀天然不进表 |
| 网站漏洞防护四个未勾 | 溢出防护 / HTTP响应内容保护 / 请求头防护 / 隐藏版本 | 前三个保持不勾(本站全是代码 / SQL / 命令行教程,响应内容保护必误伤);只勾「隐藏WebServer版本信息」 |
| 隐藏版本信息 | 已勾,实测 Server: 511yj |
达标。后面的「设置」不用点,别去改自定义串 |
| 防端口扫描 | 10 秒内 10 个端口 / 锁定 60 分钟 | 合适,别动。别从本地跑 nmap 扫自己 ECS,封的是源 IP,会把自己的 3389 锁 60 分钟 |
| 抗 CC | 60 秒 200 次 / 300 分钟 / 低(智能验证) | 偏宽松但够用,别为 8214 条日志调紧 |
累计拦截攻击次数 117.10 万次 是这台机器云锁所有防护的全局累计,不是某一功能、更不是今天的新故障;「今日拦截 5138 / 5220 次」才是当天量。别被大数吓到去调参。CPU 平时低于 10%、内存 70% 主要是 httpd 1.1~1.2 GB(mod_php 内存池只申请不归还),跟这些勾选无关,别为内存去关防护。
九、踩坑清单
google.com;漏洞防护 / 抗CC 填路径 /.well-known/acme-challenge/;带尾斜杠、不写 http://、不写盘符。... -H ... ...style.css 原样粘进 CMD 会得到 curl: (3) URL rejected: Bad hostname 和 (6) Could not resolve host —— 不是网站问题、不是 DNS 问题,是 curl 把 ... 当成字面主机名。所有命令写完整 URL。curl.exe 做验证。这台机器会报「拒绝访问」—— 是本机进程创建被拦,不是网络不通(不通会显示 code=000)。网络类验证一律在本地电脑跑。十、命令速查
| 用途 | 命令 | 在哪跑 |
|---|---|---|
| 备份 .htaccess | copy C:\xampp\htdocs\.htaccess C:\xampp\htdocs\.htaccess.bak5 |
ECS |
| 回退 | copy C:\xampp\htdocs\.htaccess.bak5 C:\xampp\htdocs\.htaccess |
ECS |
| 确认新增行落盘 | findstr /i /c:"静态资源防盗链" C:\xampp\htdocs\.htaccess |
ECS |
| 确认 junction 还挂着 | fsutil reparsepoint query "C:\xampp\htdocs\bbs\.well-known" |
ECS |
| 带 Referer 验证 | curl.exe -s -o nul -w "%{http_code} %{content_type}\n" -H "Referer: ..." "完整URL" |
本地 |
| 确认版本头已隐藏 | curl.exe -sI https://www.511yj.com/ | findstr /i "server" |
本地 |
| 看证书到期(顺手) | C:\xampp\apache\bin\openssl.exe x509 -in C:\xampp\apache\conf\ssl\www.511yj.com-crt.pem -noout -dates |
ECS |
十一、不动清单与边界
- 不加 cnblogs、不删原有七条、不勾允许空 Referer、不上 B 版、不整体关防盗链。
- 其余全不动:两条裸域 301、证书(2026-11-12 00:36 落地,下次自动续期 2027/1/5)、ECN
disabled、junction、Certificates_bak、两处 ACME 例外、抗 CC、防端口扫描阈值、监控/防护模式。 - ACME 的
/.well-known/acme-challenge/会被裸域 301 带到 www,LE 允许跟随 301、junction 让两边读同一份文件,1/5 自动续期不受这轮任何改动影响。 - 别人 HTML 里那行 img / link 删不了,请求还是会来;能做的是让「不认自己人」的请求在尽量靠前的位置被便宜地拒掉。真「本机零处理」只有把图片 / CSS 迁到带 Referer 黑名单的 CDN / OSS,那是改媒体库 URL 的大工程,不是这次做的。
- 抓取结果里那些「资源解析服务请求失败」:畸形
www.511yj.com%、W3C XHTML DTD、style.css的「网站防火墙」旧留存、首页正文快照,全是抓取通道超时或历史留存,不是站点状态,别当新线索。
.htaccess 做第二道按后缀的便宜拒绝,搜索引擎和 Google 两边按各自格式补白名单。日志还在涨不代表机器在扛,收录也不会因此掉。
记录时间:2026-11-12 · 三份笔记之三(证书续订 / 裸域 301 / 防盗链)