使用CF反代E站

Cloudflare Workers 是什么?

Cloudflare Workers

Cloudflare Workers 是一个平台,用于使无服务器功能尽可能接近最终用户运行。本质上,无服务器代码本身是“缓存”在网络上的,并在收到正确类型的请求时运行。Cloudflare Workers 是根据 service workers API 用 JavaScript 编写的,这意味着它们可以使用 service workers 提供的所有功能。它们利用 Chrome V8 引擎执行。Cloudflare Workers 代码托管在 Cloudflare 遍布全球的庞大数据中心网络中。

由于 workers.dev 已被 GFW 阻断,所以此方案需要你有一个域名。

本教程灵感来源于 ProgCZ

镜像 E-Hentai 站点

注意:仅实现了基本功能,评论,打TAG,调整设置等需要E站响应的功能未实现。

创建 Worker

首先,登录 Cloudflare,切换至 Workers & Pages 菜单,点击 创建 按钮:
创建

然后,点击 创建 Worker 按钮新建一个 Worker:
创建 Worker

接着,设置一个三级域名 eh.example.workers.dev,点击 部署 按钮:
设置三级域名

再接着,我们点击 编辑代码 按钮编辑代码:
编辑代码

最后,粘贴以下代码片段后,点击 部署 完成部署,然后通过域名 eh.example.workers.dev 访问镜像站:

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
const CONFIG = {
upstream: 'e-hentai.org',
allowedRegion: ['CN'],
blockedIpAddresses: ['0.0.0.0', '127.0.0.1'],
https: true,
disableCache: false, // 设置为 true 时禁用缓存
replaceDict: {
'$upstream': '$custom_domain',
'//e-hentai.org': ''
},
customCookies: {
'ipb_member_id': '114514',
'ipb_pass_hash': 'homo114514'
},
fixedUserAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36'
};

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

// 处理请求并返回响应
async function fetchAndApply(request) {
const {
upstream,
allowedRegion,
blockedIpAddresses,
https,
disableCache,
customCookies,
replaceDict,
fixedUserAgent
} = CONFIG;

// 获取请求头中的地区和IP地址
const region = request.headers.get('cf-ipcountry')?.toUpperCase() || '';
const ipAddress = request.headers.get('cf-connecting-ip');

// 检查地区是否被允许
if (!allowedRegion.includes(region)) {
return jsonResponse('ACCESS_DENIED', '镜像站仅在中国提供服务。', 403);
}

// 检查IP地址是否被阻止
if (blockedIpAddresses.includes(ipAddress)) {
return jsonResponse('ACCESS_DENIED', '您的IP地址已被阻止。', 403);
}

// 构建上游请求的URL
let url = new URL(request.url);
url.protocol = https ? 'https:' : 'http:';
url.host = upstream;

// 设置新的请求头
const newRequestHeaders = new Headers(request.headers);
newRequestHeaders.set('Host', url.host);
newRequestHeaders.set('Referer', `${url.protocol}//${url.hostname}`);
newRequestHeaders.set('Cookie', formatCookies(customCookies));
newRequestHeaders.set('User-Agent', fixedUserAgent);

try {
// 发送请求到上游服务器
const originalResponse = await fetch(url.href, {
method: request.method,
headers: newRequestHeaders
});

// 设置新的响应头
const newResponseHeaders = new Headers(originalResponse.headers);
if (disableCache) newResponseHeaders.set('Cache-Control', 'no-store');

// 设置CORS头
newResponseHeaders.set('access-control-allow-origin', '*');
newResponseHeaders.set('access-control-allow-credentials', 'true');
removeSecurityHeaders(newResponseHeaders);

if (newResponseHeaders.get('x-pjax-url')) {
newResponseHeaders.set(
'x-pjax-url',
newResponseHeaders.get('x-pjax-url').replace(`//${url.host}`, `//${url.hostname}`)
);
}

// 检查响应是否为 HTML
let responseText;
if (isHtmlResponse(newResponseHeaders)) {
responseText = await replaceResponseText(originalResponse, replaceDict, url.host, url.hostname);
} else {
responseText = originalResponse.body;
}

return new Response(responseText, {
status: originalResponse.status,
headers: newResponseHeaders
});

} catch (error) {
return jsonResponse('FETCH_ERROR', '获取上游响应时出错。', 502);
}
}

// 格式化 Cookie 字符串
function formatCookies(cookies) {
return Object.entries(cookies)
.map(([key, value]) => `${key}=${value}`)
.join('; ');
}

// 移除安全相关的响应头
function removeSecurityHeaders(headers) {
['content-security-policy', 'content-security-policy-report-only', 'clear-site-data'].forEach(header => {
headers.delete(header);
});
}

// 检查响应是否为 HTML
function isHtmlResponse(headers) {
const contentType = headers.get('content-type');
return contentType && contentType.includes('text/html');
}

// 替换响应文本中的指定内容
async function replaceResponseText(response, replaceDict, upstreamDomain, hostname) {
let text = await response.text();
for (let [key, value] of Object.entries(replaceDict)) {
key = key === '$upstream' ? upstreamDomain : key;
value = value === '$custom_domain' ? hostname : value;
text = text.split(key).join(value);
}
return text;
}

// 生成 JSON 格式的响应
function jsonResponse(code, message, status) {
return new Response(JSON.stringify({ code, message }), {
status,
headers: { 'Content-Type': 'application/json' }
});
}

代理里站需将 e-hentai.org 替换成 exhentai.org,同时 customCookies 中需加入有效的 igneous 值。

捐赠用户不需要更改域名,但需要在 customCookies 中加入有效的 star 值。

绑定自定义域名

设置 - 触发器 - 自定义域中填入你要绑定的域名,例如 e-hentai.example.com
绑定自定义域名

最后,等待 DNS 解析生效,即可使用 e-hentai.example.com 域名访问 E-Hentai 。


使用CF反代E站
https://blog.tmby.shop/使用CF反代E站/
作者
天命不又
发布于
2024年7月17日
许可协议