前端时间,JSD挂了一会,国内无法访问了,导致了博客都不发访问,但是那么多js和css文件,以及文章的很多picture都是放在github上由JSD代理的,所以在网上搜索众多方法后选择了做一个零成本的JSD反向代理。虽然是很早之前的事了,但是还是想拿出来水一水文章,顺便做一个备忘

在Cloudflare上创建Workers

7758fd94b919cce806b0393bc458c5a0.webp

部署Workers服务

0f8f7d288c37f17c19ac452b28e36b50.webp

在创建的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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 替换成你想镜像的站点
const upstream = 'cdn.jsdelivr.net'
 
// 如果那个站点有专门的移动适配站点,否则保持和上面一致
const upstream_mobile = 'cdn.jsdelivr.net'
 
const blocked_region = ['KP','RU']
 
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']

const allow_referer = ['https://www.imbai.cn/','https://imbai.cn/']
 
const replace_dict = {
    '$upstream': '$custom_domain',
    '//cdn.jsdelivr.net': ''
}
 
//以下内容都不用动
addEventListener('fetch', event => {
    event.respondWith(fetchAndApply(event.request));
})
 
async function fetchAndApply(request) {
 
    const region = request.headers.get('cf-ipcountry').toUpperCase();
    const ip_address = request.headers.get('cf-connecting-ip');
    const user_agent = request.headers.get('user-agent');
    const referer = request.headers.get('Referer');
 
    let response = null;
    let url = new URL(request.url);
    let url_host = url.host;
    
    // 将http跳转到https
    if (url.protocol == 'http:') {
        url.protocol = 'https:'
        response = Response.redirect(url.href);
        return response;
    }
    
    // 检测User-Agent
    if (await device_status(user_agent)) {
        upstream_domain = upstream
    } else {
        upstream_domain = upstream_mobile
    }
 
    url.host = upstream_domain;
    
    // BAN掉指定区域的请求
    if (blocked_region.includes(region)) {
        response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
            status: 403
        });
    // BAN掉指定的IP
    } else if(blocked_ip_address.includes(ip_address)){
        response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
            status: 403
        });
    // BAN掉允许域名外的请求
    }else if(!allow_referer.includes(referer)){
        response = new Response('Your referer is not allowed!',{
            status: 403
        });
    } else{
        // 反向代理请求
        let method = request.method;
        let request_headers = request.headers;
        let new_request_headers = new Headers(request_headers);
 
        new_request_headers.set('Host', upstream_domain);
        new_request_headers.set('Referer', url.href);
 
        let original_response = await fetch(url.href, {
            method: method,
            headers: new_request_headers
        })
 
        let original_response_clone = original_response.clone();
        let original_text = null;
        let response_headers = original_response.headers;
        let new_response_headers = new Headers(response_headers);
        let status = original_response.status;
 
        new_response_headers.set('access-control-allow-origin', '*');
        new_response_headers.set('access-control-allow-credentials', true);
        new_response_headers.delete('content-security-policy');
        new_response_headers.delete('content-security-policy-report-only');
        new_response_headers.delete('clear-site-data');
 
        const content_type = new_response_headers.get('content-type');
        if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
            original_text = await replace_response_text(original_response_clone, upstream_domain, url_host);
        } else {
            original_text = original_response_clone.body
        }
 
        response = new Response(original_text, {
            status,
            headers: new_response_headers
        })
    }
    return response;
}
 
async function replace_response_text(response, upstream_domain, host_name) {
    let text = await response.text()
 
    var i, j;
    for (i in replace_dict) {
        j = replace_dict[i]
        if (i == '$upstream') {
            i = upstream_domain
        } else if (i == '$custom_domain') {
            i = host_name
        }
 
        if (j == '$upstream') {
            j = upstream_domain
        } else if (j == '$custom_domain') {
            j = host_name
        }
 
        let re = new RegExp(i, 'g')
        text = text.replace(re, j);
    }
    return text;
}

// 检测UA
async function device_status (user_agent_info) {
    var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
    var flag = true;
    for (var v = 0; v < agents.length; v++) {
        if (user_agent_info.indexOf(agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
}

将自己的域名部署到workers上

创建完Workers服务后,会分配到一个xxx.xxx.workers.dev的域名,由于某种原因,这个域名在国内似乎不能访问,或者访问速度很慢,所以建议加上自己的域名用作代理。

  1. 将域名CNAME解析到分配的域名

  2. 在触发器中添加路由,域名/*

8868ac26749928032259d4a889f10a4e.webp

这样一个JSD反向代理就部署完成,根据这段代码,你也可以部署其他的反向代理服务,以及修改对应的url请求。

之前由于学校BB平台的图片访问需要认证,但是微信小程序没有为图片添加认证的方法,于是尝试过用这个方法修改请求代理,但是学校的https服务似乎有点问题,导致cf与学校服务器握手失败,最后以失败告终,去用了nginx反向代理(恼)

更多的反向代理姿势可以参考:

使用CloudFlare Workers反代网站 | So导航 (sonav.net)