看了 Diygod 的新文章優雅使用 Cloudflare WARP 應對 RSSHub 反爬難題 - DIYgod,十分激動,開始折騰,給自己的實例上 WARP,但是用了和他不太一樣的方法,使用了宿主機開 socks 代理供 Docker 容器使用的方法。
本文適用於使用 docker run /docker compose 搭建的 RSSHub,以 docker compose 為例演示。
來自 DIYgod:
為什麼要用 WARP ?
在開發 RSSHub 的幾年中,我發現提供公共 API 的站點非常少,許多站點還會採取嚴格的反爬控制來限制其平台內容的獲取。有些站點會屏蔽同一 IP 發出過多請求,而還有一些站點則會全面屏蔽常見雲伺服器廠商的 IP 地址。因此,僅僅為了獲取最新幾條內容更新卻變得非常困難。
這種情況需要使用代理,但是專門的爬蟲代理通常價格昂貴,性價比極低,如果 Cloudflare WARP 的無限流量和豐富的 IP 資源能被 RSSHub 利用就太棒了。RSSHub 已經支持了通用的代理協議,只要能將 WARP 包裝為通用的 proxy 就可以。
本人對 proxy 的理解很淺,基本上本文的內容都是試出來的。如有可以改善的地方,請評論指正。
我原本寫過一篇部署 RSSHub(以及 Miniflux)的文章:自建 RSSHub 與 Miniflux | Yunfi's Blog
還寫過一篇關於 RSS 的總覽:RSS: 是什麼?為什麼?怎麼用? | Yunfi's Blog
如果還不會用 Docker 搭建應用,可以看看這篇,以 Nginx Proxy Manager 為例演示了從安裝 Docker 到反向代理的全过程:Docker 系列前置技能:用 Nginx Proxy Manager 可視化管理 Nginx
有興趣的看官可以去看看。
2023/08/26 更新:解決安全性問題
方法區別#
官方方案使用 Docker 部署。
我使用的是 fscarmen/warp 這個項目的一鍵腳本,實際上調用了pufferffish/wireproxy 來生成 SOCKS 代理。
對比 | Docker 方法 | 腳本方法 |
---|---|---|
優點 | 簡單方便,只要更新一下 compose 文件即可 | 更靈活,可以更方便的使用 WARP+ 和團隊版;可以優選 endpoint |
缺點 | 使用自定義配置較為麻煩(要自己寫兩個文件) | 直接在宿主機上操作,略顯麻煩 |
總的來說,Docker 方案在於方便,腳本方法在於靈活。而且腳本還可以用來幹其他事情,比如刷 WARP+ 的流量。
直接採用從官方倉庫下載的 docker-compose.yml 的話,不再同一個 compose 裡的其他 Docker 應用將不能使用該容器提供的 WARP。需要稍作修改。
由於 WARP 免費版與其他版本速度區別不大,使用 Docker 部署可能是更好的方法,但是我還是用的一鍵腳本的方案,因為我本來一直就用這個😂而且防火牆設置起來也相對方便一些。
Docker 版部署#
快速部署#
DIYgod 已經把添加了 WARP 的 docker-compose.yml 放到 RSSHub 的 main 倉庫底下了,如果想直接用的話,直接按照文檔部署 | RSSHub裡的操作即可。
但是這樣有兩個不足之處,如果想要克服這兩個問題,可以看下面的高級設置部分:
- 只有在同一個 compose 文件裡的服務才能訪問該代理。
- 只能使用默認的免費 WARP 賬號。
值得注意的是,直接提供的 docker-compose.yml 使用的是一種更為佔空間和內存的方法,可以按照文件中的註釋操作,也可以直接複製一下的 yaml:
version: "3.9"
services:
rsshub:
image: diygod/rsshub:chromium-bundled
restart: always
ports:
- "1200:1200"
environment:
NODE_ENV: production
CACHE_TYPE: redis
REDIS_URL: "redis://redis:6379/"
PROXY_URI: "socks5h://warp-socks:9091"
# add other environment variables below
depends_on:
- redis
redis:
image: redis:alpine
restart: always
volumes:
- redis-data:/data
warp-socks:
image: monius/docker-warp-socks:latest
privileged: true
volumes:
- /lib/modules:/lib/modules
cap_add:
- NET_ADMIN
- SYS_ADMIN
sysctls:
net.ipv6.conf.all.disable_ipv6: 0
net.ipv4.conf.all.src_valid_mark: 1
healthcheck:
test: ["CMD", "curl", "-f", "https://www.cloudflare.com/cdn-cgi/trace"]
interval: 30s
timeout: 10s
retries: 5
volumes:
redis-data:
高級設置#
對於上面提到的問題 1,可以添加 ports,~~ 但是可能會帶來安全隱患(詳見文末)(已經解決)~~ 通過把 ports 設置到 172.17.0.1 和 127.0.0.1 可以讓本機應用和其他 Docker 容器訪問,而其他來源 IP 不行;
對於問題 2,可以掛載自己的 conf 文件,相對複雜。
可以修改 warp-socks 部分為:(注意縮進)
warp-socks:
image: monius/docker-warp-socks:latest
privileged: true
ports:
- "172.17.0.1:9091:9091"
- "127.0.0.1:9091:9091" #solve problem 1
volumes:
- /lib/modules:/lib/modules
- ./wireguard:/opt:ro # solve problem 2
cap_add:
- NET_ADMIN
- SYS_ADMIN
sysctls:
net.ipv6.conf.all.disable_ipv6: 0
net.ipv4.conf.all.src_valid_mark: 1
healthcheck:
test: ["CMD", "curl", "-f", "https://www.cloudflare.com/cdn-cgi/trace"]
interval: 30s
timeout: 10s
retries: 5
需要在 compose 文件同目錄下新建一個 wireguard 文件夾,其中放入 wgcf-profile.conf
和 danted.conf
(可選)。
以下是 wgcf-profile.conf
文件的一個示例,如果自己有這些值的話(比如折騰過 Surge/Loon 等軟件的 WARP),照貓畫虎填進去即可;如果還沒有的話,可以試著用ViRb3/wgcf生成一個(如果沒有 WARP+ 或者團隊版的就算了,會自動生成免費版,把 - ./wireguard:/opt:ro # solve problem 2
這行註釋掉即可)
[Interface]
PrivateKey = SNbsrC3W7PAcIvcdUUgqdRKBjOuUby1VPtDurefGJns=
DNS = 1.1.1.1
DNS = 1.0.0.1
Address = 172.16.0.2
Address = fd01:5ca1:ab1e:815a:634d:1529:f7a0:8f32
[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0
AllowedIPs = ::/0
Endpoint = engage.cloudflareclient.com:2408
注意:文檔裡是把這兩個文件掛載到
/opt/wireguard/
下,我實測不行;DIYgod 在評論裡說他看源碼訪問的是/opt/
下的這兩個文件,我就這麼寫了,還沒有實測,有問題評論踢我。
為了方便一鍵複製,將 [暴露端口 | 不使用自定義配置 | 設置了容器名稱] 的 docker-compose.yml
貼一份在下面,也可以直接 wget 下載我放在 gist 裡的。
wget https://gist.githubusercontent.com/yy4382/4f78b860fef29a7878e03a8a886a7367/raw/docker-compose.yml
version: "3.9"
# https://gist.githubusercontent.com/yy4382/4f78b860fef29a7878e03a8a886a7367/raw/docker-compose.yml
services:
rsshub:
image: diygod/rsshub:chromium-bundled
restart: always
container_name: rsshub-app
ports:
- "1200:1200"
environment:
NODE_ENV: production
CACHE_TYPE: redis
REDIS_URL: "redis://redis:6379/"
PROXY_URI: "socks5h://warp-socks:9091"
# add other environment variables below
depends_on:
- redis
redis:
image: redis:alpine
container_name: rsshub-redis
restart: always
volumes:
- redis-data:/data
warp-socks:
image: monius/docker-warp-socks:latest
container_name: rsshub-warp
privileged: true
ports:
- "172.17.0.1:9091:9091"
- "127.0.0.1:9091:9091"
volumes:
- /lib/modules:/lib/modules
cap_add:
- NET_ADMIN
- SYS_ADMIN
sysctls:
net.ipv6.conf.all.disable_ipv6: 0
net.ipv4.conf.all.src_valid_mark: 1
healthcheck:
test: ["CMD", "curl", "-f", "https://www.cloudflare.com/cdn-cgi/trace"]
interval: 30s
timeout: 10s
retries: 5
volumes:
redis-data:
使用一鍵腳本版部署#
原理是生成一個 SOCKS 代理,然後讓 RSSHub 使用這個代理。
使用項目 fscarmen/warp ,可以通過 WARP Linux Client 或者第三方項目pufferffish/wireproxy生成代理。
WARP Linux Client | wireproxy | |
---|---|---|
免費版 | 支持✅ | 支持✅ |
WARP+ | 支持✅ | 支持✅ |
WARP Teams | 不支持❌ | 支持✅ |
生成 0.0.0.0 的 SOCKS | 不支持❌ | 支持✅,需要修改配置文件 |
WARP+ 需要 licence,Teams 有四種認證方案,具體參考原項目README.md
生成代理#
由於目前只有 wireproxy 可以生成 0.0.0.0:40000 的 socks,所以採用該方案。(關於 Client 的問題可以看這個issue)
如果使用 WARP Client,則需要將 RSSHub 的網絡模式改為 host,這又會影響到與 Redis 的連接,又要再花一翻功夫設置,不推薦。
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh w
按流程走,記下設置的端口,本文中以默認端口 40000 為例。
第一次運行後,使用
warp
命令和warp h
可以喚起兩個不同的幫助列表,建議看一看。
修改代理訪問權限#
生成的代理是只允許 localhost 訪問,而來自 Docker 容器的訪問在本機看來並不是 localhost,所以需要更改。
打開 /etc/wireguard/proxy.conf
,將
[Socks5]
BindAddress = 127.0.0.1:40000
改為:
[Socks5]
BindAddress = 0.0.0.0:40000
讓 RSSHub 使用代理#
打開舊版的 docker-compose.yml,添加這一行:
PROXY_URI: 'socks://172.17.0.1:40000'
其中的172.17.0.1
是 docker0 的 ip,一般都是這個,不放心可以運行 ip addr show docker0
看一看有沒有 inet 172.17.0.1/16
這種。
完整的文件如下:
version: "3.9"
services:
rsshub:
image: diygod/rsshub:chromium-bundled
restart: always
ports:
- "1200:1200"
environment:
NODE_ENV: production
CACHE_TYPE: redis
REDIS_URL: "redis://redis:6379/"
PROXY_URI: "socks://172.17.0.1:40000"
# add other environment variables below
depends_on:
- redis
redis:
image: redis:alpine
restart: always
volumes:
- redis-data:/data
volumes:
redis-data:
然後再 docker compose up -d
即可。
安全性改進#
因為代理監聽 0.0.0.0
,有很大的安全隱患,任何知道伺服器 ip 的人都可以使用這個代理。
如果你的服務提供商提供了額外的一層防火牆,如騰訊雲、阿里雲、AWS、hz 之類,那最好不過,只要保證它們的面板那裡 9091/40000 端口關著。
而對於一些小 VPS 供應商,事情變得沒那麼簡單,需要設置好防火牆規則,只讓 docker 訪問 40000 端口即可,以 ufw 為例:
sudo ufw allow from 172.17.0.0/16
尾聲#
其實我的 VPS 的 IP 還不錯,還沒有遇見被哪個網站反爬了,搞這個主要是折騰一下。
中途也遇到了不少問題,也走了一些彎路,但最終還是搞出來了。
感謝這些項目的作者和 RSSHub 群友的指導。
題外話:#
我最初接觸 WARP 是在年初的時候為了把它提取到 Surge 裡,用來解鎖 ChatGPT。如果你對通過 Surge 使用 WARP 或者註冊獲得團隊版 WARP 感興趣,可以看看我當時看的兩篇教程:
本文採用 CC BY-NC-SA 4.0 許可協議
可以在我的 Hexo 博客閱讀 本文
也可以看看這個 Page 來選擇關注我各方面的更新