如何防止Cloudflare CDN背后的图片被盗连(Hotlink Protection)?
「Hotlink Protection」(直接链接保护)是经营网站经常需要去注意的一块,但为什么我们会需要「Hotlink Protection」呢?身为图文并茂的网络文章作家,最担心得就是自己的文章被别人整篇连文带图地拷贝粘贴到其它地方了。此时如果图片有套用「Hotlink Protection」的话,就可以让被盗用的图片在其它网站上「不被正常显示」出来,如此一来,就能使其它误入盗文页面的访客可以知道该篇文章是篇被盗用的文章。不同的网站架构有不同的「Hotlink Protection」的设置方式,如果您的网站有打开Cloudflare的CDN服务的话,可以参考这篇文章,来实现「Hotlink Protection」的功能。
我的网站服务器是用Nginx或Apache,难道不能直接对它们做设置吗?
很遗憾,只要我们有激活Cloudflare的CDN服务,就无法有效地通过自己的服务器程序来设置Hotlink Protection。这是因为网页浏览器在打开您网站的图片时,会去链接Cloudflare的CDN服务器,而非我们自己的服务器,所以就算我们有在自己的服务器上制作Hotlink Protection的功能,也根本不会被触发到。
既然有Cloudflare CDN,为什么还要Hotlink Protection?被盗连的图,其流量不是不会算在我们头上吗?
的确,有了Cloudflare CDN之后,就算图片被盗连,它主要也还是会去吃Cloudflare CDN服务器的流量。但是,您真的愿意让您文章中的图片原封不动地在盗文网站上显示出来吗?所以还是设置一下Hotlink Protection吧!
Cloudflare内置的Hotlink Protection开关
Cloudflare的控制后台中,其实就有提供一个一键套用Hotlink Protection的开关,只要打开来,就可以让有激活CDN功能的网域拥有Hotlink Protection的功能。这个开关藏在Cloudflare控制后台的「Scrape Shield」分页中。
这个Hotlink Protection一旦打开,整个有打开Cloudflare CDN服务的网域(包含子网域)下的图片链接,就只能在这整个网域(包含子网域)下打开,否则的话会直接回传HTTP的403状态(Forbidden)。这个开关确实很方便,但它完全不能做其它额外的设置。也就是说,如果您只想要让部份图片链接有Hotlink Protection,或是也想把其它网域纳入白名单的话,这个功能就不太合用了。
用Cloudflare的Workers来实作Hotlink Protection
Cloudflare提供的「Workers」可以针对有打开CDN服务的网域加入额外的中介程序。中介程序所使用的编程语言为JavaScript,建议使用Chrome浏览器或是其它以Chromium为内核的浏览器来做这个小节的动作。
官方也有在文档中提供Hotlink Protection的代码样板:
https://developers.cloudflare.com/workers/templates/#hot_link_protection
addEventListener('fetch', event => { | |
event.respondWith(fetchAndApply(event.request)) | |
}) | |
| |
/** | |
* If the browser is requesting an image and | |
* the referer does not match your host | |
* we redirect the request to your page | |
*/ | |
async function fetchAndApply(request) { | |
// Fetch the response. | |
let response = await fetch(request) | |
| |
// If it's an image, engage hotlink protection based on the | |
// Referer header. | |
let referer = request.headers.get('Referer') | |
let contentType = response.headers.get('Content-Type') || '' | |
if (referer && contentType.startsWith('image/')) { | |
// It's an image and there's a Referer. Verify that the | |
// hostnames match. | |
if (new URL(referer).hostname !== | |
new URL(request.url).hostname) { | |
// Hosts don't match. This is a hotlink. Redirect the | |
// user to our homepage. | |
return new Response('', { | |
status: 302, | |
headers: { | |
'Location': '/' | |
} | |
}) | |
} | |
} | |
| |
// Everything is fine, return the response normally. | |
return response | |
} |
以上这个样板,可以限制图片链接,只能够在相同的网域中被打开。如果是不同的网域,就会被暂时转址到该图片链接网域的首页。
若要使用这个样板,我们需要先打开Cloudflare的「Workers」编辑器。
接着创建一个新的脚本(Script),脚本名称自订。在此笔者将这个脚本的名称取为「image-hotlink-protection」。
接着先不要去编辑脚本,先来到路径(Route)的设置分页。
添加要套用脚本的网址,网址可以使用星号「*」来符合所有字符串组合。以本站来说,本站的图床网域为「img.magiclen.org」,文章中所有的图片都放置在这个「img.magiclen.org」网域下,因此笔者填入的网址为「https://img.magiclen.org/*」。
添加好网址后,就可以回去脚本分页,编辑刚才添加的脚本。
将样板的代码粘贴。
接着就可以改改这个样板代码,使它更符合我们的需求。以本站的情况来说,我们希望被盗连的图,可以转而去连「https://magiclen.org/images/OG-image.jpg」,所以就去修改回传的HTTP标头的「Location」字段,直接将网址填入。这边要注意的是,填进「Location」字段的网址,最好不要去激活Hotlink Protection。
同样再以本站的情况来说,我们希望我们的图床「img.magiclen.org」,可以至少在本站网域「magiclen.org」和子网域中正常使用。因此去修改原先判断「hostname」的方式,如下图:
脚本程序撰写完后,就可以按下「Deploy」(部署)按钮来套用。
来源:https://magiclen.org/cloudflare-hotlink-protection/
评论