1. 说明

我的目的是,图床的域名,国内依旧使用七牛云CDN,境外的请求使用Cloudflare代理。Cloudflare能帮我们拦截一些高危的IP地址,能避免海外肉鸡刷你的图床服务。

如果你用过Cloudflare,其在SSL/TLS模块提供了一个自定义主机名的服务,可以让用户在不将域名改成Cloudflare的DNS的情况下,使用Cloudflare的代理功能。

这个功能是Cloudflare for SAAS的一部分,你应该能在网上找到很多教程。

简单说来,想使用这个功能,需要如下几个条件

  • 实际使用的域名:对于我而言是musnow.top
  • 用于指定回退源的域名:这是第二个域名,名字无所谓,可以直接去EU.org申请一个免费的。该域名需要接入Cloudflare的DNS,这里用example.com举例子(对于用户来说,这个域名是感受不到的);
  • 一个云服务器:IP用1.1.1.1举例子;

当你配置好了之后,请求网站的路径变成了如下模样

1
2
配置前:域名musnow.top->A记录->云服务器1.1.1.1
配置后:域名musnow.top->CNAME记录->回退源域名example.com->Cloudflare->云服务器1.1.1.1

使用自定义主机名功能,可以让Cloudflare在请求你源站的时候,使用原有域名(实际使用的域名),而不是回退源域名。假设你需要回源的云服务器是国内的服务器。

1
2
3
4
回退源域名example.com没有备案 -> 请求国内服务器会被服务商拦截
配置自定义主机名musnow.top后;
Cloudflare在回源到服务器的时候,采用自定义主机名的域名,即musnow.top;
实际使用的域名musnow.top已备案 -> 请求国内服务器不再被拦截

整个过程中,回退源域名example.com对于用户是无感知的!我们实现了在原有域名musnow.top的DNS没有接入Cloudflare的情况下,使用了Cloudflare的防护服务。

目前免费版本的自定义主机名有如下要求:

  • Cloudflare必须要验证你的支付方式,不会扣你钱的(paypal或者银联信用卡,当时为此我还专门去办了个没有额度的学生信用卡,后来发现压根不需要,直接用paypal绑定个银联储蓄卡/借记卡就可以了)
  • 免费版本的回退源只能指定一个,即只能回源到一个IP地址的服务。

当然你也可以去多弄几个域名,每一个域名都可以设置一个回退源。白嫖嘛,不寒掺。

2. 配置

2.1. 回退源

首先是设置回退源域名的DNS,将其接入Cloudflare。随后是在DNS记录中添加一个A记录,指向你的源站服务器IP。

image.png

这里我使用的名称是back.回退源域名,在SSL/TLS模块的自定义主机名中开通Cloudflare SAAS服务,并添加回退源域名

image.png

添加回退源域名并验证成功后,就可以点击蓝色添加自定义主机名按钮,添加你需要代理的原始域名了。

这里我添加了我的图床域名img.musnow.top,首先是在腾讯云的DNS中设置CNAME解析,将境外线路设置为回退源的域名,默认线路还是七牛云CDN的CNAME。

image.png

添加了域名解析之后,你还需要在musnow.top的DNS解析里面添加两个TXT记录来验证回退源,参考Cloudflare给出的txt记录提示就可以。界面类似下图

image.png

添加了之后点击刷新,直到自定义主机名的状态显示为有效,即配置成功。

image.png

使用海外服务器测试,配置前,解析到七牛云CDN;配置后,解析到回退源域名,即Cloudflare

image.png

2.2. 反向代理

但这里只是配置好了域名解析而已,还需要用反代才能让境外访问图床域名能访问出图片来。

2.2.1. 反代原有七牛云CDN的CNAME不起作用

但是这个反代要怎么配置呢?因为只是解析线路不同,直接把img.musnow.top反向代理到img.musnow.top肯定不行,试试反代到七牛云的CNMAE

测试发现,直接通过七牛云CDN里面的CNAME访问这个图片会403(不管是浏览器访问还是使用curl访问)

而反代过后,curl和wget的结果都变成了526,无法访问图片

1
2
3
4
5
6
7
8
9
╰─ curl https://img.musnow.top/i/2023/05/647563ddab0fb.gif
error code: 526%

╰─ wget https://img.musnow.top/i/2023/05/647563ddab0fb.gif
--2023-12-16 18:48:21-- https://img.musnow.top/i/2023/05/647563ddab0fb.gif
Resolving img.musnow.top (img.musnow.top)... 172.67.157.61, 104.21.56.251, 2606:4700:3035::ac43:9d3d, ...
Connecting to img.musnow.top (img.musnow.top)|172.67.157.61|:443... connected.
HTTP request sent, awaiting response... 526
2023-12-16 18:48:21 ERROR 526: (no description).

image.png

即便在反代里面设置了后端请求的域名为img.musnow.top,访问依旧会是526

image.png

2.2.2. 未设置Cloudflare时能成功解析

作为对比,在没有配置解析到Cloudflare的时候,使用wget是能访问出图片来的

image.png

将wget的这个图片通过sftp下载下来,能看到它是正常的gif,图片访问没有问题。

image.png

2.2.3. 解决方案

我能想到的解决办法,是白嫖一下七牛云免费的10GB HTTP流量,新建一个HTTP回源的CDN,绑定到图床的bucket上即可。

image.png

注意,只要你的回源地址是国内的bucket,那么域名就必须要备案才能配置CDN。

因为现在是通过云服务器反代来访问这个CDN,此时反代的proxy设置为http,在添加img.musnow.top的cert证书到反代设置里面,就能实现https。

1
https://img.musnow.top 反代 http://img-cloudflare.musnow.top

image.png

注意,反代中的后端域名也需要设置为新的CDN域名,否则访问会因为域名不匹配而403拒绝访问。

image.png

随后就是添加img.musnow.top的SSL证书

image.png

测试一下,新建的这个cdn域名可以通过http访问到bucket里面的图片

image.png

再测试一下反代后的域名,也可以访问到图片了,这里访问的IP地址104.21.56.251也已经是Cloudflare的IP了。配置成功!

image.png

此时海外访问我的图床,解析变成了如下过程

1
2
3
img.musnow.top -> CNAME回退源域名 -> cloudflare(https) 
-> 云服务器反代(https) -> img-cloudflare.musnow.top(http)
-> 七牛云CDN -> 七牛云bucket

因为最终访问的CDN是通过HTTP回源bucket的,能白嫖七牛云10G的免费流量!

当然,如果真有人在海外打你,刷完10G流量也不是不可能……所以在cloudflare里面最好再配置一下单IP访问的频次限制!

比如下图,我设置访问URL为图床开头/i时进行速率监看,如果单IP访问速率超过60次/10秒,那么就会触发cloudflare的速率限制响应,持续10秒。

因为我的博客已经设置了懒加载,所以一次性加载60个图片的场景是不存在的!这种规模的请求肯定是攻击了!再加上我的博客理论上不会有几个海外用户阅读,所以这个配置不会对国内用户产生影响。

如果你使用了代理,请把musnow.top所有子域名加入代理白名单。

image.png

2.2.4. 进一步优化,IP白名单

进一步优化,就是把新创建的这个HTTP CDN里面设置IP白名单,只允许我们设置反代的服务器的那个IP地址访问,这样就保证了其他人不能直接刷我新建的这个HTTP的CDN域名。

image.png

在七牛云的CDN配置界面可以看到IP黑白名单,添加服务器IP地址为白名单即可

image.png

配置后需要过一段时间才会生效,会有个进度条。完成后,再次本地测试一下,发现已经403不允许访问了。

image.png

此时在海外服务器尝试反代域名访问,依旧是OK的,访问的IP地址172.67.157.61也依旧是Cloudflare的IP。

image.png

3. The end

至此,配置完成!