FreshRSS 解决 sspai 图片防盗链问题
起因
作为 RSS 阅读器的坚守者,因为支持 fever API 的客户端越来越少,同时功能上也非常受限,无法完成源的新增、删除等。所以最近把服务端从 Tiny Tiny RSS + RSSHub + Mercury + Browserless 换成 FreshRSS + RSSHub 的方案。
整体用下来,FreshRSS 对于我来讲功能够用,可定制的内容要少一些,功能更简单,UI 更现代,体感上性能更好,最重要支持的客户端够多。特别喜欢它自带的 Web 爬虫功能,如果会写一点 XPath 就能抓取不支持 RSS 的网站,可以不用通过 RSSHub,但是这种方式也有个缺点是不支持 JS 渲染内容的页面。
换服务端的过程中,对 RSS 源也进行了一些整理,加了一些新源。过程中发现 少数派图片无法正常显示,测试了一下加入了简单的防盗链机制。搜了一下为了屏蔽一些恶意的用户,所以增加了盗链。
没有图片看起来确实有点难受,所以有了这篇文章。原则上该文章的方式,适用于任何通过 referer 判断盗链的场景。当然我们的目的不是为了去盗链,而是在个人使用场景上的便捷。
方案
大概搜索了一下,FreshRSS 有个图片代理的插件 xExtension-ImageProxy。插件原来的目的是让一些使用非加密链接的 http 请求图片,通过代理变成加密 https 的图片。但是我们可以借助它的能力,来解决防盗链的功能。
需要一台外网能正常访问的服务器,通过 Nginx 实现,Nginx 配置如下。SSL 证书地址和端口可以根据自己服务器情况调整:
map $arg_path $new_referer {
default "";
"~*sspai\.com" "https://sspai.com";
# insert here
}
server {
listen 443 ssl;
http2 on;
root /config/www;
ssl_certificate /config/keys/full.pem;
ssl_certificate_key /config/keys/key.pem;
location /proxy {
if ($request_uri ~* "^/proxy\?path=(.*)") {
set $destination $1;
}
if ($domain = "") {
return 302 $destination;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Referer $new_referer;
proxy_pass $arg_path;
}
}
ImageProxy 的配置如下,URL 换成你自己的域名或者 IP,后面部分 /proxy?path=
不变,如果要修改和 Nginx 配置一起改。
原理是所有图片请求会到 Nginx 上,如果域名是以 sspai.com
结尾,设置 referer 为 https://sspai.com
,需要增加其它域名在 # insert here
增加就可以了。如果未命中,即直接通过 302 重定向到原地址。
方案还有提升的空间,现在不管什么图片都会请求 Nginx 进行判断。更高效的办法是在插件里面做判断,只有需要代理的图片再请求 Nginx。因为目前看性能还行就不折腾了。