Cloudflare Workers反向代理IP地址限制

您的代码混合了两种方法,需要做一些调整。我看到有几个问题:

  1. 映射格式不一致:有些值有 http:// 前缀,有些没有
  2. DNS记录需要先设置backend1.thanx.topbackend2.thanx.top 需要先在DNS中设置A记录指向 106.15.4.153
  3. 重定向和内容替换逻辑需要更新:现在只检查 106.15.4.153,但可能还有其他IP

让我帮您修正代码:

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
// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
// 确保 backend1.thanx.top 和 backend2.thanx.top 已在DNS设置A记录指向 106.15.4.153
const domainMappings = {
'test.thanx.top': 'http://backend1.thanx.top:8085',
'api.thanx.top': 'http://backend2.thanx.top:8086',
'admin.thanx.top': 'http://backend3.thanx.top:8087', // 建议也使用域名
'reverse-proxy.yuebinliu.workers.dev': 'http://backend1.thanx.top:8085' // 测试用
};

// 用于内容替换的目标IP列表(支持多个IP)
const targetIPs = ['106.15.4.153']; // 可以添加多个IP

const url = new URL(request.url);
const target = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!target) {
return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}

// 准备转发请求
const targetUrl = new URL(url.pathname + url.search, target);
const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');

// 设置正确的Host头(目标服务器期望的Host)
const targetHost = new URL(target).hostname;
newHeaders.set('Host', targetHost);

try {
// 转发请求到目标服务器
let response = await fetch(targetUrl.toString(), {
method: request.method,
headers: newHeaders,
body: request.body,
redirect: 'manual' // 手动处理重定向
});

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

// 替换所有目标IP的重定向
for (const ip of targetIPs) {
newLocation = newLocation.replace(
new RegExp(`http://${ip}:\\d+`, 'g'),
`https://${url.hostname}`
);
}

// 如果重定向地址被修改,更新响应
if (newLocation !== location) {
const newResponse = new Response(response.body, response);
newResponse.headers.set('location', newLocation);
return newResponse;
}
}
}

// 处理HTML内容,替换其中的链接
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html')) {
let html = await response.text();

// 替换所有目标IP的链接
for (const ip of targetIPs) {
html = html.replace(
new RegExp(`http://${ip}:\\d+`, 'g'),
`https://${url.hostname}`
);
}

// 返回修改后的HTML
return new Response(html, {
status: response.status,
headers: response.headers
});
}

// 对于非HTML内容,直接返回
return response;

} catch (error) {
// 错误处理
return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, {
status: 502,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}
}
}

在部署此代码前,您需要:

  1. 在DNS中设置A记录

    • backend1.thanx.top106.15.4.153 (DNS only - 灰色云)
    • backend2.thanx.top106.15.4.153 (DNS only - 灰色云)
    • backend3.thanx.top106.15.4.153 (DNS only - 灰色云)
  2. 确保后端服务器配置

    • 后端服务器需要能够接受这些域名的请求
    • SSL证书需要对这些域名有效(或者使用HTTP)

如果您不想设置额外的DNS记录,可以使用这个简化版本:

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
export default {
async fetch(request) {
const domainMappings = {
'test.thanx.top': { ip: '106.15.4.153', port: '8085' },
'api.thanx.top': { ip: '106.15.4.153', port: '8086' },
'admin.thanx.top': { ip: '106.15.4.153', port: '8087' }
};

const url = new URL(request.url);
const target = domainMappings[url.hostname];

if (!target) return new Response('Not found', { status: 404 });

const targetUrl = `http://${target.ip}:${target.port}${url.pathname}${url.search}`;

const newHeaders = new Headers(request.headers);
newHeaders.set('Host', url.hostname);
newHeaders.set('X-Forwarded-Host', url.hostname);

return fetch(targetUrl, {
method: request.method,
headers: newHeaders,
body: request.body,
cf: { resolveOverride: target.ip }
});
}
}

建议先设置DNS记录,然后使用第一个版本的代码,这样最稳定可靠。

时间: 2025-09-06T01:29:06


👤 用户

cloudflare 谁用works配置反向代理时候,发现无法代理ip地址

时间: 2025-09-06T01:12:23


🤖 DeepSeek (deepseek-chat)

您好!您遇到的问题非常典型,Cloudflare Workers 在设计上出于安全和架构原因,默认不允许直接代理(即作为反向代理)到裸IP地址

这是一个有意为之的限制,而不是一个故障或错误配置。下面我将详细解释原因、变通方案以及最佳实践。

为什么 Cloudflare Workers 不允许代理到 IP 地址?

  1. 安全风险(最主要原因)

    • SNI 要求:现代TLS(HTTPS)通信依赖于服务器名称指示(SNI)。当客户端(这里是Worker)连接到一台服务器时,它必须在TLS握手阶段通过SNI指明它想要连接的主机名。IP地址无法提供有效的主机名信息。
    • 证书验证问题:目标服务器上的SSL证书是针对域名签发的(例如 example.com)。如果你让Worker访问一个IP地址,Worker在验证SSL证书时,会尝试将IP地址与证书中的域名列表进行匹配,这几乎总是会失败,导致SSL证书验证错误。
    • 规避安全策略:直接使用IP地址可能会被用来绕过基于域名的安全策略和内容过滤。
  2. 架构设计

    • Cloudflare 的网络是为基于域名的路由而构建的。IP地址绕过了Cloudflare的DNS系统和全球智能路由(Argo Smart Routing)等优化功能。
  3. 滥用防范

    • 禁止IP地址可以防止Worker被滥用来攻击或扫描内网或其他网络资源。

错误信息

当您尝试在 fetch()serviceBinding 中使用IP地址时,通常会遇到以下类似错误:

  • CF-Workers script will not be able to fetch 123.123.123.123. You should use a hostname instead.
  • Destination 123.123.123.123 is not allowed.

解决方案和变通方法

虽然不能直接使用 https://192.0.2.1,但有几种方法可以实现您的需求:

方法一:使用域名(最佳实践)

这是最推荐、最符合标准且没有副作用的方法。

  1. 为您要代理的IP地址创建一个子域名
  2. 在该子域名的DNS记录中,设置一个 A 记录,指向您的目标IP地址。
    • 例如: 您想代理 192.0.2.1,可以创建一个DNS记录:
      • 类型A
      • 名称my-backend.example.com
      • 内容/目标192.0.2.1
      • 代理状态: (橙色云)DNS only(灰色云)
  3. 在您的Worker代码中,使用这个子域名而不是IP地址。
1
2
3
4
5
6
7
8
9
10
11
export default {
async fetch(request) {
// 将目标URL中的IP地址替换为您设置的域名
const url = new URL(request.url);
url.hostname = 'my-backend.example.com'; // 您的域名,指向目标IP
// url.port = '8000'; // 如果需要,可以修改端口

let new_request = new Request(url, request);
return fetch(new_request);
}
};

优点

  • 完全符合Worker的安全要求。
  • 可以正常进行TLS/SSL握手和证书验证(只要您的证书对该域名有效)。
  • 是最清晰、最可维护的方案。

方法二:使用 resolveOverride 参数(高级用法)

这是一个非官方但广为人知的“特性”,它允许您通过自定义DNS解析来“绕过”限制。您仍然需要提供一个主机名,但Worker会将其解析到您指定的IP。

在您的 fetch 请求中,添加 cf 属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export default {
async fetch(request) {
// 定义一个主机名(可以是任意有效的域名,它本身解析到哪里不重要)
const fakeHostname = 'my-target.example.com';

let new_url = new URL(request.url);
new_url.hostname = fakeHostname;

let new_request = new Request(new_url, request);

return fetch(new_request, {
cf: {
// resolveOverride 会告诉Cloudflare的边缘网络:
// “不要正常解析 my-target.example.com,直接把它解析成这个IP地址”
resolveOverride: '192.0.2.1' // 您的目标IP
}
});
}
};

重要注意事项

  • 这不是官方API:Cloudflare 并未正式将其纳入文档,其行为在未来可能会改变。
  • SNI问题依然存在resolveOverride 只解决了DNS解析问题,但没有解决SNI问题。发送到目标IP的请求中的SNI头仍然是 my-target.example.com。这意味着:
    • 如果目标IP上的服务器配置了针对 my-target.example.com 的SSL证书,那么一切正常。
    • 如果目标服务器使用的是自签名证书、通配符证书,或者证书与 my-target.example.com 不匹配,您可能需要禁用SSL证书验证(不推荐,有安全风险)。
  • 谨慎使用:建议仅在开发和测试中使用,生产环境更推荐方法一

方法三:禁用SSL验证(极度不推荐)

强烈不建议在生产环境中使用此方法,因为它会破坏TLS的安全性,使连接容易受到中间人攻击。

如果您在使用 resolveOverride 时遇到证书错误,可以通过将 insecureSkipVerify 设置为 true 来跳过证书验证(这需要与 resolveOverride 结合使用)。

1
2
3
4
5
6
7
return fetch(new_request, {
cf: {
resolveOverride: '192.0.2.1',
// 警告:这会禁用SSL证书验证!
insecureSkipVerify: true
}
});

总结

方法 推荐度 说明
为IP绑定域名(方法一) ⭐⭐⭐⭐⭐ 最佳实践 安全、可靠、符合规范,是Cloudflare设计的工作方式。
使用 resolveOverride(方法二) ⭐⭐☆ 临时/高级方案 有效但非官方,需要注意SNI/证书匹配问题。
禁用SSL验证(方法三) ⭐☆☆ 危险,应避免 破坏安全性,仅用于极端情况下的测试。

对于绝大多数用户,请直接采用方法一。花几分钟时间为您要代理的IP地址设置一个DNS A 记录,可以避免后续无数的麻烦和潜在的安全隐患。

时间: 2025-09-06T01:12:23


👤 用户

帮我修改下下面的代码。好能够直接代理IP

// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
const domainMappings = {
‘test.thanx.top’: ‘http://106.15.4.153:8085‘,
‘api.thanx.top’: ‘http://106.15.4.153:8086‘,
‘admin.thanx.top’: ‘http://106.15.4.153:8087‘,
‘reverse-proxy.yuebinliu.workers.dev’: ‘http://106.15.4.153:8085‘ // 测试用
};

const url = new URL(request.url);
const target = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!target) {
  return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), { 
    status: 404,
    headers: { 'Content-Type': 'text/plain; charset=utf-8' }
  });
}

// 准备转发请求
const targetUrl = new URL(url.pathname + url.search, target);
const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');
newHeaders.delete('host'); // 删除原始host头

try {
  // 转发请求到目标服务器
  let response = await fetch(targetUrl.toString(), {
    method: request.method,
    headers: newHeaders,
    body: request.body,
    redirect: 'manual' // 手动处理重定向
  });

  // 处理重定向响应
  if ([301, 302, 303, 307, 308].includes(response.status)) {
    const location = response.headers.get('location');
    if (location && location.includes('106.15.4.153')) {
      // 替换重定向地址中的原始IP为代理域名
      const newLocation = location.replace(
        /http:\/\/106\.15\.4\.153:\d+/g, 
        `https://${url.hostname}`
      );
      const newResponse = new Response(response.body, response);
      newResponse.headers.set('location', newLocation);
      return newResponse;
    }
  }

  // 处理HTML内容,替换其中的链接
  const contentType = response.headers.get('content-type') || '';
  if (contentType.includes('text/html')) {
    let html = await response.text();
    
    // 替换所有原始服务器链接为代理域名
    html = html.replace(
      /http:\/\/106\.15\.4\.153:\d+/g,
      `https://${url.hostname}`
    );
    
    // 返回修改后的HTML
    return new Response(html, {
      status: response.status,
      headers: response.headers
    });
  }

  // 对于非HTML内容,直接返回
  return response;
  
} catch (error) {
  // 错误处理
  return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, { 
    status: 502,
    headers: { 'Content-Type': 'text/plain; charset=utf-8' }
  });
}

}
}

时间: 2025-09-06T01:15:11


🤖 DeepSeek (deepseek-chat)

我来帮您修改代码,使其能够直接代理IP地址。根据Cloudflare Workers的限制,我们需要使用resolveOverride方法来实现。

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
// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
// 格式: { '代理域名': { ip: '目标IP', port: '端口' } }
const domainMappings = {
'test.thanx.top': { ip: '106.15.4.153', port: '8085' },
'api.thanx.top': { ip: '106.15.4.153', port: '8086' },
'admin.thanx.top': { ip: '106.15.4.153', port: '8087' },
'reverse-proxy.yuebinliu.workers.dev': { ip: '106.15.4.153', port: '8085' } // 测试用
};

const url = new URL(request.url);
const targetConfig = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!targetConfig) {
return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}

const { ip, port } = targetConfig;

// 创建一个虚拟的主机名用于SNI(可以是任意有效域名)
const virtualHostname = `target-${ip.replace(/\./g, '-')}-${port}.proxy.internal`;

// 构建目标URL(使用虚拟主机名)
const targetUrl = new URL(url.pathname + url.search, `http://${virtualHostname}`);
if (port) {
targetUrl.port = port;
}

const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');
newHeaders.set('Host', virtualHostname); // 设置虚拟主机名

try {
// 转发请求到目标服务器,使用resolveOverride指向目标IP
let response = await fetch(targetUrl.toString(), {
method: request.method,
headers: newHeaders,
body: request.body,
redirect: 'manual', // 手动处理重定向
cf: {
resolveOverride: ip, // 关键:将虚拟主机名解析到目标IP
// 注意:如果目标服务器使用自签名证书,可能需要添加下面这行(不推荐)
// insecureSkipVerify: true
}
});

// 处理重定向响应
if ([301, 302, 303, 307, 308].includes(response.status)) {
const location = response.headers.get('location');
if (location) {
// 替换重定向地址中的原始IP为代理域名
const newLocation = location.replace(
new RegExp(`http://${ip}:${port}`, 'g'),
`https://${url.hostname}`
);
const newResponse = new Response(response.body, response);
newResponse.headers.set('location', newLocation);
return newResponse;
}
}

// 处理HTML内容,替换其中的链接
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html')) {
let html = await response.text();

// 替换所有原始服务器链接为代理域名
html = html.replace(
new RegExp(`http://${ip}:${port}`, 'g'),
`https://${url.hostname}`
);

// 返回修改后的HTML
return new Response(html, {
status: response.status,
headers: response.headers
});
}

// 对于非HTML内容,直接返回
return response;

} catch (error) {
// 错误处理
return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, {
status: 502,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}
}
}

主要修改内容:

  1. 修改映射结构:将映射从字符串改为对象,包含ipport字段
  2. 使用虚拟主机名:创建了一个虚拟主机名用于SNI握手
  3. 添加resolveOverride:在fetch请求中使用cf.resolveOverride将虚拟主机名解析到目标IP
  4. 更新正则表达式:使用动态的IP和端口来构建正则表达式,避免硬编码

注意事项:

  1. SSL证书问题:如果目标服务器使用自签名证书或证书与虚拟主机名不匹配,可能会遇到SSL错误。在这种情况下,您可能需要取消注释insecureSkipVerify: true,但这会降低安全性。

  2. 长期解决方案:建议为每个服务配置一个子域名(如service1.yourdomain.com)指向目标IP,然后在Worker中使用这些子域名,这样更符合Cloudflare的最佳实践。

  3. 测试:部署后请仔细测试所有功能,特别是重定向和链接替换功能。

这个修改后的代码应该能够成功代理到IP地址,同时保持原有的重定向处理和内容替换功能。

时间: 2025-09-06T01:15:11


👤 用户

Error 1016 Ray ID: 97a7620810d7a5a0 • 2025-09-05 17:17:55 UTC
Origin DNS error
What happened?
You’ve requested a page on a website (target-106-15-4-153-8085.proxy.internal) that is on the Cloudflare network. Cloudflare is currently unable to resolve your requested domain (target-106-15-4-153-8085.proxy.internal).

Please see https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1016/ for more details.

时间: 2025-09-06T01:18:41


🤖 DeepSeek (deepseek-chat)

这个错误是因为我使用了虚拟主机名 target-106-15-4-153-8085.proxy.internal,但这个域名实际上不存在,Cloudflare 无法解析它。我们需要换一种方法来解决这个问题。

让我重新修改代码,使用更简单直接的方法:

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
// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
// 格式: { '代理域名': { ip: '目标IP', port: '端口' } }
const domainMappings = {
'test.thanx.top': { ip: '106.15.4.153', port: '8085' },
'api.thanx.top': { ip: '106.15.4.153', port: '8086' },
'admin.thanx.top': { ip: '106.15.4.153', port: '8087' },
'reverse-proxy.yuebinliu.workers.dev': { ip: '106.15.4.153', port: '8085' } // 测试用
};

const url = new URL(request.url);
const targetConfig = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!targetConfig) {
return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}

const { ip, port } = targetConfig;

// 构建目标URL(直接使用IP地址)
const targetBaseUrl = `http://${ip}:${port}`;
const targetUrl = new URL(url.pathname + url.search, targetBaseUrl);

const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');

// 设置正确的Host头(目标服务器期望的Host)
// 这里使用原始请求的hostname,或者根据您的后端需求调整
newHeaders.set('Host', url.hostname);

try {
// 转发请求到目标服务器
let response = await fetch(targetUrl.toString(), {
method: request.method,
headers: newHeaders,
body: request.body,
redirect: 'manual',
cf: {
// 使用resolveOverride来绕过IP限制
resolveOverride: ip,
// 如果需要跳过SSL验证(如果目标服务器使用自签名证书)
// insecureSkipVerify: true
}
});

// 处理重定向响应
if ([301, 302, 303, 307, 308].includes(response.status)) {
const location = response.headers.get('location');
if (location && location.includes(ip)) {
// 替换重定向地址中的原始IP为代理域名
const newLocation = location.replace(
new RegExp(`http://${ip}:${port}`, 'g'),
`https://${url.hostname}`
);
const newResponse = new Response(response.body, response);
newResponse.headers.set('location', newLocation);
return newResponse;
}
}

// 处理HTML内容,替换其中的链接
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html')) {
let html = await response.text();

// 替换所有原始服务器链接为代理域名
html = html.replace(
new RegExp(`http://${ip}:${port}`, 'g'),
`https://${url.hostname}`
);

// 返回修改后的HTML
return new Response(html, {
status: response.status,
headers: response.headers
});
}

// 对于非HTML内容,直接返回
return response;

} catch (error) {
// 错误处理
return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, {
status: 502,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}
}
}

如果仍然遇到问题,这里是一个更简单的版本:

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
// 简化版 - 多域名反向代理
export default {
async fetch(request, env) {
const domainMappings = {
'test.thanx.top': '106.15.4.153:8085',
'api.thanx.top': '106.15.4.153:8086',
'admin.thanx.top': '106.15.4.153:8087',
'reverse-proxy.yuebinliu.workers.dev': '106.15.4.153:8085'
};

const url = new URL(request.url);
const target = domainMappings[url.hostname];

if (!target) {
return new Response('域名未配置', { status: 404 });
}

const [ip, port] = target.split(':');
const targetUrl = `http://${ip}:${port}${url.pathname}${url.search}`;

// 修改请求头
const newHeaders = new Headers(request.headers);
newHeaders.set('Host', url.hostname);
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', 'https');
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || '');

try {
const response = await fetch(targetUrl, {
method: request.method,
headers: newHeaders,
body: request.body,
cf: {
resolveOverride: ip
}
});

return response;

} catch (error) {
return new Response(`代理错误: ${error.message}`, { status: 502 });
}
}
}

如果还是不行,建议采用最佳实践:

  1. 为每个服务创建DNS记录

    • backend1.yourdomain.com106.15.4.153 (端口8085)
    • backend2.yourdomain.com106.15.4.153 (端口8086)
    • 等等…
  2. 然后在Worker中使用这些域名

1
2
3
4
5
const domainMappings = {
'test.thanx.top': 'backend1.yourdomain.com:8085',
'api.thanx.top': 'backend2.yourdomain.com:8086',
// ...
};

这样既符合Cloudflare的安全要求,又能稳定工作。

时间: 2025-09-06T01:18:41


👤 用户

这样吗?
// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
const domainMappings = {
‘test.thanx.top’: ‘backend1.thanx.top:8085’,
‘api.thanx.top’: ‘backend2.thanx.top:8086’,
‘admin.thanx.top’: ‘http://106.15.4.153:8087‘,
‘reverse-proxy.yuebinliu.workers.dev’: ‘http://backend1.thanx.top:8085‘ // 测试用
};

const url = new URL(request.url);
const target = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!target) {
  return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), { 
    status: 404,
    headers: { 'Content-Type': 'text/plain; charset=utf-8' }
  });
}

// 准备转发请求
const targetUrl = new URL(url.pathname + url.search, target);
const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');
newHeaders.delete('host'); // 删除原始host头

try {
  // 转发请求到目标服务器
  let response = await fetch(targetUrl.toString(), {
    method: request.method,
    headers: newHeaders,
    body: request.body,
    redirect: 'manual' // 手动处理重定向
  });

  // 处理重定向响应
  if ([301, 302, 303, 307, 308].includes(response.status)) {
    const location = response.headers.get('location');
    if (location && location.includes('106.15.4.153')) {
      // 替换重定向地址中的原始IP为代理域名
      const newLocation = location.replace(
        /http:\/\/106\.15\.4\.153:\d+/g, 
        `https://${url.hostname}`
      );
      const newResponse = new Response(response.body, response);
      newResponse.headers.set('location', newLocation);
      return newResponse;
    }
  }

  // 处理HTML内容,替换其中的链接
  const contentType = response.headers.get('content-type') || '';
  if (contentType.includes('text/html')) {
    let html = await response.text();
    
    // 替换所有原始服务器链接为代理域名
    html = html.replace(
      /http:\/\/106\.15\.4\.153:\d+/g,
      `https://${url.hostname}`
    );
    
    // 返回修改后的HTML
    return new Response(html, {
      status: response.status,
      headers: response.headers
    });
  }

  // 对于非HTML内容,直接返回
  return response;
  
} catch (error) {
  // 错误处理
  return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, { 
    status: 502,
    headers: { 'Content-Type': 'text/plain; charset=utf-8' }
  });
}

}
}

时间: 2025-09-06T01:29:06


🤖 DeepSeek (deepseek-chat)

您的代码混合了两种方法,需要做一些调整。我看到有几个问题:

  1. 映射格式不一致:有些值有 http:// 前缀,有些没有
  2. DNS记录需要先设置backend1.thanx.topbackend2.thanx.top 需要先在DNS中设置A记录指向 106.15.4.153
  3. 重定向和内容替换逻辑需要更新:现在只检查 106.15.4.153,但可能还有其他IP

让我帮您修正代码:

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
// Cloudflare Worker 代码 - 多域名反向代理
export default {
async fetch(request, env) {
// 域名到目标服务器的映射
// 确保 backend1.thanx.top 和 backend2.thanx.top 已在DNS设置A记录指向 106.15.4.153
const domainMappings = {
'test.thanx.top': 'http://backend1.thanx.top:8085',
'api.thanx.top': 'http://backend2.thanx.top:8086',
'admin.thanx.top': 'http://backend3.thanx.top:8087', // 建议也使用域名
'reverse-proxy.yuebinliu.workers.dev': 'http://backend1.thanx.top:8085' // 测试用
};

// 用于内容替换的目标IP列表(支持多个IP)
const targetIPs = ['106.15.4.153']; // 可以添加多个IP

const url = new URL(request.url);
const target = domainMappings[url.hostname];

// 如果域名未配置,返回404
if (!target) {
return new Response('域名未配置: ' + url.hostname + '\n\n已配置的域名: ' + Object.keys(domainMappings).join(', '), {
status: 404,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}

// 准备转发请求
const targetUrl = new URL(url.pathname + url.search, target);
const newHeaders = new Headers(request.headers);

// 设置代理头
newHeaders.set('X-Forwarded-Host', url.hostname);
newHeaders.set('X-Forwarded-Proto', url.protocol.replace(':', ''));
newHeaders.set('X-Real-IP', request.headers.get('cf-connecting-ip') || 'unknown');

// 设置正确的Host头(目标服务器期望的Host)
const targetHost = new URL(target).hostname;
newHeaders.set('Host', targetHost);

try {
// 转发请求到目标服务器
let response = await fetch(targetUrl.toString(), {
method: request.method,
headers: newHeaders,
body: request.body,
redirect: 'manual' // 手动处理重定向
});

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

// 替换所有目标IP的重定向
for (const ip of targetIPs) {
newLocation = newLocation.replace(
new RegExp(`http://${ip}:\\d+`, 'g'),
`https://${url.hostname}`
);
}

// 如果重定向地址被修改,更新响应
if (newLocation !== location) {
const newResponse = new Response(response.body, response);
newResponse.headers.set('location', newLocation);
return newResponse;
}
}
}

// 处理HTML内容,替换其中的链接
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html')) {
let html = await response.text();

// 替换所有目标IP的链接
for (const ip of targetIPs) {
html = html.replace(
new RegExp(`http://${ip}:\\d+`, 'g'),
`https://${url.hostname}`
);
}

// 返回修改后的HTML
return new Response(html, {
status: response.status,
headers: response.headers
});
}

// 对于非HTML内容,直接返回
return response;

} catch (error) {
// 错误处理
return new Response(`代理错误: ${error.message}\n\n目标URL: ${targetUrl.toString()}`, {
status: 502,
headers: { 'Content-Type': 'text/plain; charset=utf-8' }
});
}
}
}

在部署此代码前,您需要:

  1. 在DNS中设置A记录

    • backend1.thanx.top106.15.4.153 (DNS only - 灰色云)
    • backend2.thanx.top106.15.4.153 (DNS only - 灰色云)
    • backend3.thanx.top106.15.4.153 (DNS only - 灰色云)
  2. 确保后端服务器配置

    • 后端服务器需要能够接受这些域名的请求
    • SSL证书需要对这些域名有效(或者使用HTTP)

如果您不想设置额外的DNS记录,可以使用这个简化版本:

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
export default {
async fetch(request) {
const domainMappings = {
'test.thanx.top': { ip: '106.15.4.153', port: '8085' },
'api.thanx.top': { ip: '106.15.4.153', port: '8086' },
'admin.thanx.top': { ip: '106.15.4.153', port: '8087' }
};

const url = new URL(request.url);
const target = domainMappings[url.hostname];

if (!target) return new Response('Not found', { status: 404 });

const targetUrl = `http://${target.ip}:${target.port}${url.pathname}${url.search}`;

const newHeaders = new Headers(request.headers);
newHeaders.set('Host', url.hostname);
newHeaders.set('X-Forwarded-Host', url.hostname);

return fetch(targetUrl, {
method: request.method,
headers: newHeaders,
body: request.body,
cf: { resolveOverride: target.ip }
});
}
}

建议先设置DNS记录,然后使用第一个版本的代码,这样最稳定可靠。

时间: 2025-09-06T01:29:06



对话统计

  • 消息总数: 8 条
  • 处理状态: 成功转换