FreshRSS 解决 sspai 图片防盗链问题

FreshRSS 解决 sspai 图片防盗链问题
Photo by Patrick Robert Doyle / Unsplash

起因

作为 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 配置一起改。

ImageProxy Configuration

原理是所有图片请求会到 Nginx 上,如果域名是以 sspai.com 结尾,设置 referer 为 https://sspai.com,需要增加其它域名在 # insert here 增加就可以了。如果未命中,即直接通过 302 重定向到原地址。
方案还有提升的空间,现在不管什么图片都会请求 Nginx 进行判断。更高效的办法是在插件里面做判断,只有需要代理的图片再请求 Nginx。因为目前看性能还行就不折腾了。