前言
自從 jsDelivr 被 DNS 污染後,比較常用的解決方法是使用其鏡像代替,例如 fastly.jsdelivr.net
、gcore.jsdelivr.net
、cf.jsdelivr.net
,但是這些鏡像不能保證將來是否能保持活躍。所以,使用反向代理是最有效的一個解決方案。
這裡使用了 Cloudflare Workers 進行反向代理,Cloudflare Workers 提供每天 10 萬次的請求數量,搭配 CDN 又可以通過緩存大大減少請求數。同時也可以設置防盜鏈和加密 URL 以防止濫用。
參考:https://www.430074.xyz/posts/workers-jsdeliver.html
快速上手
創建 Workers
打開 Cloudflare 儀錶板,轉到 Workers,創建一個新項目
編輯代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| const ALLOWED_REFERER = [ /^https?:\/\/localhost(:\d*)?\/.*$/, /^https?:\/\/([\w-]+\.)*w3schools\.com(:\d*)?\/.*$/ ];
const ALLOW_NO_ORIGIN = true;
const MYSECRET = "123456";
function validateReferer(req) { const referer = req.headers.get('Referer'); if (referer) { for (const el of ALLOWED_REFERER) { if (el.exec(referer)) { return true; } } return false; } return ALLOW_NO_ORIGIN; }
async function handle(request) { let url = new URL(request.url); const acceptType = request.headers.get('Accept'); const hash_request = url.pathname.split("/")[1]; const path_real = url.pathname.substring(hash_request.length + 1, url.pathname.length); url.hostname = "cdn.jsdelivr.net"; url.pathname = path_real;
if (!(await validatePath(hash_request, path_real))) { return new Response('Error Hash', { status: 403 }); }
if (!(validateReferer(request))) { return new Response('Blocked Host', { status: 403 }); }
return await fetch(url); }
async function validatePath(hash_request, path_real) { const message = new TextEncoder().encode(path_real + MYSECRET); const myDigest = await crypto.subtle.digest('SHA-1', message); const hashArray = Array.from(new Uint8Array(myDigest)); const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); return (hashHex == hash_request); }
addEventListener('fetch', event => { event.respondWith(handle(event.request)); })
|
編輯下面參數
- 修改 ALLOWED_REFERER 常量,裡麵包含了可以使用本服務的域名列表。按照模板,修改成自己的域名,需要使用正則表達式。同時
ALLOW_NO_ORIGIN = true
是表示允許無 Referer 訪問本服務,比如直接瀏覽器打開。
- 修改密碼 MYSECRET,這裡的密碼是用來加密 URL 的,因為 Referer 可以偽造,所以為了避免他人濫用,所以需要密碼進行加密。
如果對正則表達式不熟悉,可以使用 Regex Vis (一個正則表達式可視化工具),右上角可以切換語言。

如果不需要防盜鏈和加密,可以注釋掉下面內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| - if (!(await validatePath(hash_request, path_real))) { - return new Response('Error Hash', { - status: 403 - }); - } - - if (!(validateReferer(request))) { - return new Response('Blocked Host', { - status: 403 - }); - } + // if (!(await validatePath(hash_request, path_real))) { + // return new Response('Error Hash', { + // status: 403 + // }); + // } + + // if (!(validateReferer(request))) { + // return new Response('Blocked Host', { + // status: 403 + // }); + // }
|
綁定域名
進入一個域,轉到 DNS,添加一條 A 記錄,IP 值隨意,打開右邊的 CDN

轉到 Workers,為二級域名設置路由,選中剛剛部署的 Workers 服務

如果你想使用未通過 NS 接入 Cloudflare 的域名設置路由,也可以使用 SaaS 通過 IP/CNAME 接入,fallback.b.com
作為回退源,任意指向一個 IP,將 demo.a.com
指向 fallback.b.com
,然後在 b.com
的域下為 demo.a.com/*
設置路由。
參考:
添加 WAF 規則(可選)
添加一條 WAF 規則作為防盜鏈,腳本中的防盜鏈就可以注釋掉
轉到 Security 中的 WAF,創建一條規則
該規則釋義為如果 Referer 不包含 example.com
,且請求的主機名中等於 raw.example.com
,則阻斷

獲得加密請求 URL
- 假設 Workers 綁定的域名是
w3schools.com
,密碼是 123456 ,想要反代的是 /npm/[email protected]/dist/jquery.min.js
- 獲得帶加密的明文,為
url.path + 密碼
,如上則是 /npm/[email protected]/dist/jquery.min.js123456
。獲得該字符串的 SHA-1 編碼 。得到密文 371388c8eafe02c8876f67abe1d170b920218881
。
- 生成新的請求 URL :
域名 + /密文 + 原 url.path
。如上文則是 https://w3schools.com/371388c8eafe02c8876f67abe1d170b920218881/npm/[email protected]/dist/jquery.min.js
。
jsDelivr Reverse Proxy on Cloudflare Workers