how-to-build-a-proxy-by-CFWorkers
T Lv1

背景

Cloudflare是著名的CDN提供商,有着庞大的边缘网络。cloudflare边缘网络 他们提供了一项构建无服务器应用程序的CFWorkers,可以把JS脚本快速部署到CF的边缘网络上来搞事情。

也就是说我们可以通过CFWorkers搭建反向代理来实现科学上网

第一次见到这个操作还是某个sd群友的谷歌反代站不过因为不可抗力因素这个反代站已经关闭了……所以建议学会反代的同学自己偷着乐就可以了。而且有的网站禁止反代,比如P站;有的网站反代没用,比如GMAIL,因为涉及到账号登陆。不过反代个wiki啥的还是很香的

准备

  • Cloudflare账户
  • 一个域名(可要可不要,workers默认部署的子域太长)

实现

首先登录你的Cloudflare账户,选择页面右侧的

1
2
3
Workers
构建无服务器应用程序

在新页面单击

1
2
3

创建Worker

接着在左侧脚本框内输入以下代码

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
142
143
144
145
146
147
148
149
150
151
152
// Website you intended to retrieve for users.
const upstream = 'www.example.com'

// Custom pathname for the upstream website.
const upstream_path = '/'

// Website you intended to retrieve for users using mobile devices.
const upstream_mobile = 'www.example.com'

// Countries and regions where you wish to suspend your service.
const blocked_region = ['KP', 'SY', 'PK', 'CU']

// IP addresses which you wish to block from using your service.
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']

// Whether to use HTTPS protocol for upstream address.
const https = true

// Whether to disable cache.
const disable_cache = true

// Replace texts.
const replace_dict = {
'$upstream': '$custom_domain',
'//www.example.com': ''
}

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');

let response = null;
let url = new URL(request.url);
let url_hostname = url.hostname;

if (https == true) {
url.protocol = 'https:';
} else {
url.protocol = 'http:';
}

if (await device_status(user_agent)) {
var upstream_domain = upstream;
} else {
var upstream_domain = upstream_mobile;
}

url.host = upstream_domain;
if (url.pathname == '/') {
url.pathname = upstream_path;
} else {
url.pathname = upstream_path + url.pathname;
}

if (blocked_region.includes(region)) {
response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
status: 403
});
} else if (blocked_ip_address.includes(ip_address)) {
response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
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', url.hostname);
new_request_headers.set('Referer', url.hostname);

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;

if (disable_cache) {
new_response_headers.set('Cache-Control', 'no-store');
}

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');

if(new_response_headers.get("x-pjax-url")) {
new_response_headers.set("x-pjax-url", response_headers.get("x-pjax-url").replace("//" + upstream_domain, "//" + url_hostname));
}

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_hostname);
} 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;
}


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;
}

在右侧选项卡选择预览选项卡并刷新检查是否反代成功。
成功后保存并退出到上一层页面,重命名一个好记的名字,并打开左侧

1
2
3

已在workers.dev子域中提供

好了,一个基于CFWorkers的反代站已经做好了,把它收藏在浏览器收藏夹里就可以方便地调用了。

使用客制化域名

首先你得准备好一个域名,不妨假设是 www.example.com 。在域名的注册商那儿把该域名的DNS服务器改为Cloudflare的DNS服务器。具体请参见如何在Cloudflare中添加站点。
然后,在