1、前言
自从 cdn.jsdelivr.net 被qiang了之后,很多网站都无法正常访问。目前比较受欢迎的解决方法是用其镜像网址代替,比如 gcore.jsdelivr.net, cf.jsdelivr.net 和 fastly.jsdelivr.net。其中 fastly.jsdelivr.net 由于大陆解析的服务器在日本所以延迟较低,但是丢包较大,而gcore.jsdelivr.net 和 cf.jsdelivr.net 延迟和丢包都不理想。并且,由于某些原因,这些镜像服务并不能保证以后一直可以使用。
本文介绍了一种使用cloudflare workers反代cdn.jsdelivr.net的方法。workers提供每天10w次的免费访问额度,对于一些小站非常好用,若是套上CDN,则通过缓存可以大大减少请求数。同时本文提供的方案可以防止跨站和对url进行加密,从而避免自己的服务被人滥用。本人非专业程序员,js和正则都是现学的,如果有改进方式,非常欢迎指导。
2、代码
// 允许的 CORS 来源
const ALLOWED_REFERER = [
/^https?:\/\/localhost(:\d*)?\/.*$/,
/^https?:\/\/([\w-]+\.)*w3schools\.com(:\d*)?\/.*$/];
// 是否允许所有无 Referer 请求
const ALLOW_NO_ORIGIN = true;
//输入你的密码,密码加在path后面做SHA-1运算
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; // 是否拒绝所有无 Referer 请求
}
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));
})
3、使用教程
3.1 创建一个cloudflare workers
复制粘贴以上代码,建议绑定自己的域名,此处可参考网上其他教程。比如:
3.2 修改参数。
1、修改 ALLOWED_REFERER 常量,里面包含了可以使用本服务的域名列表。按照模板,修改成自己的域名。同时 ALLOW_NO_ORIGIN = true 是表示允许无referer访问本服务,比如直接浏览器打开。
2、修改密码 MYSECRET,这里的密码是用来加密网址的,因为Referer可以伪造,所以为了避免他人用你的服务干自己的事情,所以需要密码进行加密。
3.3 获得加密请求网址
1、假设workers 绑定的域名是 w3schools.com ,密码是 123456 ,想要反代的网址是https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js 。
2、获得带加密的明文,为 url.path + 密码,如上则是 /npm/jquery@3.2.1/dist/jquery.min.js123456 。获得该字符串的SHA-1编码,比如可以通过:SHA1在线加密、校验工具-ME2在线工具 。得到密文371388c8eafe02c8876f67abe1d170b920218881。
3、生成新的请求网址:你的域名 + /密文 + 原url.path。如上文则是 https://w3schools.com/371388c8eafe02c8876f67abe1d170b920218881/npm/[email protected]/dist/jquery.min.js 。然后在网站中替换为该地址即可。
欢迎指出任何有错误或不够清晰的表达,可以在下面评论区评论。