今天在看腾讯云 CDN 统计数据时,发现一个不起眼的 Referer:

image.png

按照以往的习惯总是会把一些不熟悉的网站点开看看,结果差点就没发现这个山寨货:一个和本站一模一样的网站,但是里面全是繁体字,评论系统原封不动且正常使用。

我甚至怀疑以前检查的时候我都自动忽略了。这次之所以能察觉出端倪是因为我发现假冒站的「友链朋友圈」点不开,返回循环重定向错误页面,打算找问题时才发现域名不对劲。至于繁体文字我一直以为是 Butterfly 偶发故障,毕竟点两下简繁切换按钮就好了。

服了,我真的是要吐槽我自己了,为什么每次博客圈发生什么坏事我总是这么迟钝🤮:

  • 年初网站外链查的紧时,是蜀黍打电话过来时才把它当回事。(那时候已经看到过 @大大的蜗牛 发表过类似文章,处理措施详见 站内文章这篇文章
  • 前段时间中小博客被盗刷 CDN,我是直到钱包被抠破才意识到事情严重,甚至眼睁睁看着正在被盗刷不知道该干啥。(然而那时候已经看到过 @清羽飞扬 发表过类似文章)
  • 现在被镜像了,却不知道已经被镜像 2 个月了,然后才想起来 @杜老师 很早就发过类似的文章…

wcnm

既然事情已经发生,那现在我们就着手处理吧。这篇文章主要分为 3 部分措施:

  • 🛡️预防和保护措施。即使不知道被谁镜像,也会影响镜像站的体验。
  • 🎯针对性保护措施。找出恶意 IP 进行针对性屏蔽。
  • 🗡️反制措施。当你知道对方的域名和爬虫 IP 时,就可以反击了。

假冒站点特征

假冒镜像站的地址:gatoelectric.online(欢迎骚扰)。从域名上看不出什么名堂,感觉是个某个做电子的企业。ICP 备案查不到什么信息(废话),Whois 展示如下:

image.png

这个来自天津的 zhang💩zhen💩yu 同时也镜像了 这位博主 的网站,可以说是个惯犯了。

Google 搜索「半方池水半方田 - Qin’s blog」可以搜索到冒牌镜像站,排名偏后。直接搜域名的话第一个就是冒牌镜像站。

image.png

image.png

通过一些博主的文章了解到,这种假冒镜像站点的行为已经是自动化的了,目的可能是用于养域名,它们的特征有:

  • 国内网络无法访问冒牌镜像站点,返回 404。
  • 主页面的语言是繁体。(你猜受众会是谁?)
  • 伪装成搜索爬虫对网站进行爬取。

image.png

🛡️保护与预防手段

对网站的各个部分,我们可以采取相应的保护措施。

为网站添加 JavaScript 脚本引导用户前往官方站点

原理是检测当前站点是否为正确站点并正常显示,否则:

  • 弹窗提示,说明此站点非官方站点。或直接重定向到官方站点。(为了方便一些博客日常本地调试,比如 Hexo,代码对 localhost127.0.0.1 的站点不做弹窗和水印处理)
  • 弹窗提示,禁止页面嵌套
  • 全站贴满水印
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const validDomain = 'uuanqin.top';
const redirectUrl = 'https://blog.uuanqin.top';
const hostname = document.location.hostname;
const isLocalHost = (hostname === 'localhost' || hostname === '127.0.0.1');

//如果不是本地也不是子域名
if (!isLocalHost && !hostname.endsWith(validDomain)) {
createWatermark(validDomain)
const userResponse = confirm(`警告:本页面非官方页面,可能存在有害信息!建议您立即跳转 ${validDomain} 并向站长举报该冒牌镜像站!`);
if (userResponse) {
window.location.replace(redirectUrl);
}
}

// 检查是否在iframe中
if (window.top !== window.self) {
const userResponse = confirm(`当前访问于嵌套窗口,可能存在侵权行为,请在独立窗口访问 ${validDomain}。`);
if (userResponse) {
window.open(redirectUrl, '_blank');
}
}

function createWatermark(text) {
const watermarkDiv = document.createElement('div');
watermarkDiv.style.pointerEvents = 'none';
watermarkDiv.style.position = 'fixed';
watermarkDiv.style.top = '0';
watermarkDiv.style.left = '0';
watermarkDiv.style.width = '100%';
watermarkDiv.style.height = '100%';
watermarkDiv.style.zIndex = '9999';
watermarkDiv.style.opacity = '0.35';
watermarkDiv.style.background = 'transparent';
watermarkDiv.style.overflow = 'hidden';
watermarkDiv.style.display = 'flex';
watermarkDiv.style.justifyContent = 'center';
watermarkDiv.style.alignItems = 'center';
watermarkDiv.style.flexWrap = 'wrap';

const watermarkText = document.createElement('div');
watermarkText.innerText = text;
watermarkText.style.color = '#8d8d8d';
watermarkText.style.fontSize = '30px';
watermarkText.style.transform = 'rotate(-30deg)';
watermarkText.style.whiteSpace = 'nowrap';
watermarkText.style.margin = '20px';
// 文本阴影(增加干扰)
watermarkText.style.textShadow = '2px 2px 5px rgba(0, 0, 0, 0.5)';

for (let i = 0; i < 60; i++) {
watermarkDiv.appendChild(watermarkText.cloneNode(true));
}

document.body.appendChild(watermarkDiv);
}

js 引入前记得做混淆处理,因为据说恶意脚本会把一些网址给正则替换了。可以使用这个在线工具 JavaScript Obfuscator Tool 对代码加密混淆,记得勾选 unicode escape sequence 选项把中文进行转义处理。

当然最好的方法是让这段代码和一些关键组件 js 融合。不然假站禁掉 js 或挑出那个关键的 js 文件禁掉就破解了。

将此 js 部署后效果立竿见影,几乎一发布就被假冒镜像站捕获到:

image.png

image.png

注意,后续更改 js 时注意把文件名也改一改以更新网站缓存。

附一个检测到嵌入窗口的弹窗示例:

image.png

但是点击「确定」键会被浏览器阻止弹窗,并询问用户是否弹出窗口:

image.png

禁止 iframe 的话会导致一些合法的工具失效,比如「百度统计」中无法查看页面点击图。

Waline 评论系统设置安全域名

Waline 评论内容能被假冒镜像站显示是我完全没想到的。我们可以在环境变量配置安全域名。详看:服务端环境变量 | Waline

效果为评论内容不加载,且禁止评论:

image.png

🎯针对性防御

得到假冒镜像站的域名或有害爬虫的 IP 后,我们可以进行定点屏蔽及时止损。

CDN 图床防盗链黑名单

腾讯云 CDN 访问控制开启防盗链黑名单:

image.png

注意:

  • 不用选「拒绝空 referer 访问」,这影响范围比较大,容易误伤一些正常访问,不好处理。
  • 对图床防盗链意思意思即可。如果站点也启用 CDN 的话,站点不用防盗链。因为这会导致用户点击你在假冒镜像站设置的跳转弹窗时被自己的官方站点拒绝。

效果:

image.png

找出可疑 IP 并封禁

关于用户的源 IP 地址

如果你的网站又套 CDN 或 Cloudflare 代理的,Nginx 日志中展示的可能不会是最初用户的 IP 地址。附常用 IP 地址检查:

访问日志的途径:

  • Nginx 访问日志一般在 /var/log/nginx 目录下
  • Cloudflare:安全性 -> 分析

夜深人静的时候改动一下自己的文章并发布。不访问官方站点,而是直接访问假冒镜像站点,查看新文章或新改动是否更新。如果假站做出了改动,请查询日志,根据请求路径和时间判断出可疑的 IP。

Cloudflare 封禁方式:安全性 -> WAF -> 工具。手工添加可疑 IP。

可疑 IP 判断:

  • 频繁地、无故地扫描系统根目录不存在的文件或文件夹。
  • 如果你的主题不是 Wordpress 的话,那些频繁访问 /wp-content /wp /wp-admin 或各种敏感的 .php 文件的 IP 很可能是恶意 IP。

image.png

只要你找对了,一击必杀!🔪🩸🩸🩸

image.png

🗡️反制措施

免责声明

  • 本章节内容仅供学习和交流,切勿用于违法行为。本文作者不对读者的不当使用负责。
  • 请确保你的反制行为不对其他第三方网站造成过度负担,也不违反当地法规。比如在进行重定向操作时,要慎重考虑重定向的目的站点。

这里的反制措施主要指主动下线假冒镜像站点,或误导有害爬虫爬取其他页面,使不法分子造成一定的损失。

获得搜索引擎站长管理系统下伪站点的所有权

常用站长工具有:百度站长、谷歌站长(Search Console)、Bing Webmasters。这里以「谷歌站长」为例,其他的操作方式大差不差。

用自己的 Google 小号,在「谷歌站长」新加一个网站,网址就是冒牌镜像站的网址。利用冒牌镜像站原封不动爬取资源的特点,通过 HTML 验证获得「谷歌站长」下该假冒镜像站点的所有权。

image.png

Hexo 博客放置步骤可以是:

  1. 放到 source 文件夹下
  2. 在配置 _config.yml 中指定文件不被渲染
1
2
skip_render:
- googlefcd336221d7decf8.html # 验证文件
  1. 正常发布即可

image.png

然后就时不时看数据,建有索引的就直接提交删除:

image.png

image.png

image.png

谷歌完成移除后,无论之前怎样搜,搜索结果中不会再出现冒牌镜像站了。

狡猾的 zhang💩zhen💩yu 看完本文说道:学到啦,感谢博主!以后我不会爬取这些验证文件啦!

今天 250108 实测发现,恶意爬虫不再爬取 HTML 验证文件,但谷歌站长还提供以下验证方法:

image.png

Hexo 方法为在主题配置文件下配置以下内容即可。

1
2
3
4
inject:
head:
# 反制镜像站措施
- <meta name="google-site-verification" content="ppz3zz_ljO3DX-wcnmsb-zhang-zhen-yu" />

image.png

在 Cloudflare 中设置重定向规则

前面章节我们已经讲到我们在 Cloudflare 中已经找到了可疑 IP,并设置了 WAF 规则对其进行封禁。我们还可以在保持封禁的同时设置重定向规则,让可疑 IP 爬取到其他的网页。

image.png

参考写法如下。至于重定向到哪里,就发挥读者的想象力咯:

image.png

点击「部署」即可。然后再次访问冒牌镜像站,正能量扑面而来,相信它的受众们会很喜欢。

image.png

博主声明:上图仅作为本次演示用,并非当前本站的实际配置!
更多 Cloudflare 重定向的玩法详见这篇文章:站内文章域名 DNS 服务托管至 Cloudflare 以及 301 重定向的配置

此外,我们还可以利用这个有用的 链接 ,得到最美的结局:

image.png

但你解除重定向后发现服务器还是没死,真是伤不到一点😅。

在 Nginx 中将假爬虫的请求转发到其他站点

使用此方式的前提

  • 你已确定是伪造的 Google 爬虫爬取了你的网站。
  • 请确保落在 Nginx 上的访问的 IP 是来自真实用户的 IP,而不是被 Cloudflare 等服务代理过的 IP。

首先获得谷歌爬虫的 IP 段:googlebot.json

将 IP 段转换成这种形式:

1
2
3
66.249.76.96/27 1;
66.249.77.0/27 1;
66.249.77.128/27 1;

可以找 AI 帮忙生成代码而不是直接要结果,毕竟 IP 太多了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import json

# 输入文件和输出文件的路径
input_file = 'googlebot.json'
output_file = 'converted_ipranges.txt'

# 读取 JSON 数据
with open(input_file, 'r', encoding='utf-8') as f:
data = json.load(f)

# 提取 IP 地址段
ip_ranges = data.get("prefixes", [])

# 将结果写入输出文件
with open(output_file, 'w', encoding='utf-8') as f:
for range in ip_ranges:
# 检查是否包含 ipv4Prefix 或 ipv6Prefix,并提取
if 'ipv4Prefix' in range:
f.write(f'{range["ipv4Prefix"]} 1;\n')
elif 'ipv6Prefix' in range:
f.write(f'{range["ipv6Prefix"]} 1;\n')

print(f"转换结果已保存到 {output_file}")

将上面生成的文件 converted_ipranges.txt 放到服务器中。

打开 Nginx 日志(/var/log/nginx 目录下),搜索可疑爬虫的 User Agent,如果爬虫的 IP 不在官方的列表中,就说明这个爬虫是假的。

在 Nginx 配置文件(http 块)中加入以下字段:

1
2
3
4
5
# 加载 IP 白名单文件
geo $crawler_ip {
default 0;
include /etc/nginx/conf.d/googlebot_ipranges/converted_ipranges.txt;
}

主站 location 块中加入判断,将假爬虫反代到其他站点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server {

listen 443 ssl;
server_name blog.uuanqin.top;
access_log /var/log/nginx/host.access.log main;


location / {
root /var/www/blog.uuanqin.top;
index index.html index.htm;

set $temp "";

# 符合UA
if ($http_user_agent ~* 'compatible; Googlebot/2.1;') {
set $temp "${temp}1";
}
# 但不符合IP段时自动反代指定网页
if ($crawler_ip != 1) {
set $temp "${temp}1";
}

if ($temp ~* "11") {
proxy_pass https://www.cac.gov.cn; # 网信办
break; # 添加 break 语句,确保后续的处理被中断
}
}

# 此处省略其他配置
}

配置更改后记得重启 Nginx:

1
nginx -s reload
写 Nginx 配置文件遇到的各种坑

特么的,这些东西花了我几个小时排查,各式 AI 检查都不靠谱。可能是我的 Nginx 版本原因吧,单纯写个简单的「与」条件判断够复杂的。

  • geomap 必须在 server 块外面
  • if 条件语句写在 location 里面
  • if 条件语句不能嵌套
  • if 条件语句中不能使用「与」「或」判断
  • if 和括号 ( 中间必须有空格
  • proxy_pass 接的网址最后不能是 /
  • 奇怪的正则表达式

我们可以通过修改输出日志的格式完成 Nginx 的调试:

1
2
3
4
5
6
7
log_format alogformat '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for -- is_crawler_ip: $crawler_ip | fakeBotWillBe11: $temp "';

server{
access_log /var/log/nginx/host.access.log alogformat;
}

通过日志查看指定的 IP 是否被拦截。

image.png

然而并没有什么用,因为配置的原因,站长的 Nginx 日志暂时看不出用户原始地址,屏蔽的也只是 Cloudflare 的代理 IP 地址。

其他反制措施

列举一些还可以进行的手段:

  • 向各种服务商举报滥用。我们可以向 Google、Bing、Cloudflare、Aliyun、域名商以 DMCA 为理由举报滥用行为。有试过的读者可以评论下,不知道有没有用。我嫌填表单麻烦没试。
  • 攻击对方服务器。这个方式就留给技术大拿们补充了。

后记

好不容易出个假冒镜像站点,不得好好把玩把玩?感觉假站的点击量都是我贡献的。不久后,Bing 收录了假冒镜像站的域名,但是没有展现任何一点信息,算是预防成功了吧。

image.png

继续排查反链,又发现一个假冒镜像站,特征一模一样,只不过镜像的是我的一个友链😂(心疼 3 分钟)。

大家要保护好自己的网站哦。

本文参考

镜像站相关:

Nginx 相关:

其他: