前言

Cloudflare Workers 是一个支持 jsproxy 的无服务器函数服务,提供全球 CDN 支持,免费用户每天有 10 万次请求额度。通过简单配置,您可以用它来反向代理任意网站,实现流量中转和访问优化。

Cloudflare 官网:https://www.cloudflare.com

实现反代功能

下面是一段简单的 Cloudflare Workers 脚本,您只需将 example.com 替换为您需要反代的网址即可实现反代。

核心代码

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// 需要反代的网站域名
const upstream = 'example.com';

// 自定义的路径(可选,默认根路径)
const upstream_path = '/';

// 是否启用HTTPS协议
const https = true;

// 是否禁用缓存
const disable_cache = false;

// 最大可处理的HTML响应体大小(5MB)
const MAX_HTML_SIZE = 5 * 1024 * 1024;

// 替换文本规则(留空即可,不需要改)
const replace_dict = {
// '旧域名': '新域名',
};

// 监听Fetch事件
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request));
});

// 主逻辑
async function fetchAndApply(request) {
let url = new URL(request.url);
const url_hostname = url.hostname;
const proxy_protocol = https ? 'https:' : 'http:';

// 设置协议
url.protocol = proxy_protocol;

// 设置目标域名
url.host = upstream;

// 处理路径拼接(修正双斜杠问题)
if (upstream_path !== '/') {
const cleanUpstreamPath = upstream_path.replace(/\/+$/, '');
url.pathname = cleanUpstreamPath + url.pathname;
}

// 设置请求头
const method = request.method;
const new_request_headers = new Headers(request.headers);

// 修改 Host 为目标域名
new_request_headers.set('Host', upstream);
new_request_headers.delete('Origin');

// WebSocket 连接处理
const upgradeHeader = new_request_headers.get('Upgrade');
const isWebSocket = upgradeHeader && upgradeHeader.toLowerCase() === 'websocket';

if (isWebSocket) {
return fetch(url.href, {
method,
headers: new_request_headers
});
}

// 使用 manual 模式处理重定向
const fetchOptions = {
method,
headers: new_request_headers,
redirect: 'manual'
};

// 处理请求体(POST/PUT 等)
if (method !== 'GET' && method !== 'HEAD') {
fetchOptions.body = request.body;
}

// 发起请求
const original_response = await fetch(url.href, fetchOptions);

// 处理重定向
if ([301, 302, 303, 307, 308].includes(original_response.status)) {
const location = original_response.headers.get('Location');
if (location) {
let newLocation = location;

try {
const redirectUrl = new URL(location, url.href);
if (redirectUrl.host === upstream) {
redirectUrl.host = url_hostname;
redirectUrl.protocol = proxy_protocol.slice(0, -1);
newLocation = redirectUrl.toString();
}
} catch (e) {
if (location.startsWith('/')) {
newLocation = `${proxy_protocol}//${url_hostname}${location}`;
} else {
const basePath = url.pathname.substring(0, url.pathname.lastIndexOf('/') + 1);
newLocation = `${proxy_protocol}//${url_hostname}${basePath}${location}`;
}
}

const redirectHeaders = new Headers(original_response.headers);
redirectHeaders.set('Location', newLocation);

return new Response(null, {
status: original_response.status,
statusText: original_response.statusText,
headers: redirectHeaders
});
}
}

// 克隆响应
const original_response_clone = original_response.clone();
let response_headers = new Headers(original_response.headers);
let response_body = null;

// 缓存控制
if (disable_cache) {
response_headers.set('Cache-Control', 'no-store, no-cache, must-revalidate');
}

// CORS 头
response_headers.set('Access-Control-Allow-Origin', '*');
response_headers.set('Access-Control-Allow-Credentials', 'true');

// 删除安全限制头
['content-security-policy', 'content-security-policy-report-only', 'clear-site-data', 'x-frame-options'].forEach(header => {
response_headers.delete(header);
});

// 处理响应内容
const content_type = response_headers.get('content-type') || '';
const content_length = parseInt(response_headers.get('content-length') || '0');
const content_encoding = response_headers.get('content-encoding') || '';
let body_modified = false;

if (Object.keys(replace_dict).length > 0 &&
content_type.includes('text/html') &&
!content_encoding &&
content_length < MAX_HTML_SIZE) {
try {
response_body = await replace_response_text(original_response_clone, upstream, url_hostname);
body_modified = true;
} catch (e) {
response_body = original_response_clone.body;
}
} else {
response_body = original_response_clone.body;
}

if (body_modified) {
response_headers.delete('content-length');
}

return new Response(response_body, {
status: original_response.status,
statusText: original_response.statusText,
headers: response_headers
});
}

// 替换响应文本
async function replace_response_text(response, upstream_domain, host_name) {
let text = await response.text();

for (const [key, value] of Object.entries(replace_dict)) {
let search = key;
let replacement = value;

if (key.includes('$upstream')) {
search = search.replace(/\$upstream/g, upstream_domain);
}
if (key.includes('$custom_domain')) {
search = search.replace(/\$custom_domain/g, host_name);
}
if (value.includes('$upstream')) {
replacement = replacement.replace(/\$upstream/g, upstream_domain);
}
if (value.includes('$custom_domain')) {
replacement = replacement.replace(/\$custom_domain/g, host_name);
}

const escapedSearch = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
text = text.replace(new RegExp(escapedSearch, 'g'), replacement);
}

return text;
}

如何使用?

  1. 登录 Cloudflare Workers 管理界面。
  2. 创建一个新的 Worker。
  3. 将代码粘贴到编辑器中。
  4. example.com 替换为您需要反代的目标网站域名。
  5. 保存并部署。

注意事项

  1. 请求限制:免费账户每天请求上限为 10 万次,超出将暂停服务。
  2. 法律合规:确保您有合法权限对目标网站进行反代。
  3. 性能优化:可以调整缓存和替换规则,提高访问速度。

至此,你就可以在HF等无法自定义域名的平台上使用自己的域名了!