核心架构说明(所有图片内容均为个人设置,请自行更改)
本方案需要 两条 DNS 记录配合:
原理:
用户访问
b.example.com,流量被 Cloudflare 代理拦截Worker 根据用户 IP 类型分流:
IPv6 用户 → 302 重定向到
a.example.com:端口,浏览器直连源站IPv4 用户 → Worker 内部请求
a.example.com:端口,通过 CDN 转发响应
准备工作
Cloudflare 账号
域名一个,DNS 托管在 Cloudflare
源服务器已配置好服务,拥有公网 IPv6 地址(如
240e:xxx:xxx:xxx::1)
第一步:创建两条 DNS 记录
假设主域名为 example.com,源站 IPv6 为 240e:123:456:789::1。
1.1 创建 AAAA 记录(内部源站)
这条记录供 Worker 内部使用,不需要开启代理。
类型:
AAAA名称:
a(或任意内部标识,如origin-v6)IPv6 地址:
240e:123:456:789::1代理状态:关闭(灰色云朵,仅 DNS)

1.2 创建 CNAME 记录(用户入口)
这条记录是用户实际访问的地址,必须开启代理。
类型:
CNAME名称:
b(你的服务子域名,如pan、nas)目标:
a.example.com代理状态:开启(橙色云朵,已代理)
⚠️ 关键理解:用户访问的是
b.example.com(走 CDN),Worker 内部连接的是a.example.com(直连源站 IPv6)。两者通过 CNAME 关联,但代理状态不同。我这里用nas作为演示
第二步:部署 Worker
2.1 创建 Worker
进入 Cloudflare 仪表盘 → Workers 和 Pages
点击 创建应用程序 → 创建 Worker
随便起个名字,点击 部署(先部署默认代码)
2.2 粘贴完整代码
点击 编辑代码,清空原有内容,粘贴以下代码:
// ==========================================
// Cloudflare Worker - IPv6 P2P 直连版
// IPv6用户直连 + IPv4走CDN代理
// ==========================================
// 变量命名规则:
// IPV6_HOST -> 全局IPv6主机地址(默认:a.example.com)
// PORT_子域名 -> 目标端口
// SSL_子域名 -> 协议类型 (https/http,默认https)
// ==========================================
// 配置区
// ==========================================
// 缓存配置
const CACHE_CONFIG = {
static: 86400, // 静态资源:24小时
dynamic: 300, // 动态内容:5分钟
api: 0 // API请求:不缓存
};
// 静态资源后缀
const STATIC_EXTENSIONS = [
'css', 'js', 'jpg', 'jpeg', 'png', 'gif', 'svg', 'ico',
'woff', 'woff2', 'ttf', 'eot', 'mp4', 'webp', 'avif'
];
// 必要请求头
const ESSENTIAL_HEADERS = [
'Accept', 'Accept-Encoding', 'Accept-Language',
'Authorization', 'Cache-Control', 'Content-Type',
'Cookie', 'Range', 'User-Agent', 'Referer'
];
// 必要响应头
const ESSENTIAL_RESPONSE_HEADERS = [
'Content-Type', 'Content-Length', 'Content-Encoding',
'Cache-Control', 'ETag', 'Last-Modified',
'Set-Cookie', 'WWW-Authenticate', 'Content-Disposition',
'Location', 'Access-Control-Allow-Origin'
];
// ==========================================
// 工具函数
// ==========================================
function isIPv6(ip) {
return ip && ip.includes(':');
}
function isStaticResource(pathname) {
const ext = pathname.split('.').pop().toLowerCase();
return STATIC_EXTENSIONS.includes(ext);
}
function isAPIRequest(pathname) {
return pathname.startsWith('/api/') || pathname.startsWith('/_api/');
}
/**
* 从环境变量读取服务配置
*/
function getServiceConfig(subdomain) {
const ipv6Host = globalThis['IPV6_HOST'] || 'a.example.com';
const port = globalThis[`PORT_${subdomain}`];
const ssl = globalThis[`SSL_${subdomain}`] || 'https';
if (!port) return null;
return {
host: ipv6Host,
port: port,
protocol: ssl.toLowerCase()
};
}
/**
* 获取缓存TTL
*/
function getCacheTTL(pathname) {
if (isStaticResource(pathname)) return CACHE_CONFIG.static;
if (isAPIRequest(pathname)) return CACHE_CONFIG.api;
return CACHE_CONFIG.dynamic;
}
// ==========================================
// 核心处理函数
// ==========================================
/**
* IPv6 P2P 直连(302重定向到内网地址)
* 让客户端直接连接,Worker不做代理中转
*/
function handleIPv6Direct(request, serviceConfig) {
const url = new URL(request.url);
const directUrl = `${serviceConfig.protocol}://${serviceConfig.host}:${serviceConfig.port}${url.pathname}${url.search}`;
// 方案1:302重定向(推荐,真正的P2P直连)
return new Response(null, {
status: 302,
statusText: 'IPv6 Direct Connect',
headers: {
'Location': directUrl,
'X-Connection-Type': 'IPv6-P2P-Direct',
'X-Direct-Host': serviceConfig.host,
'X-Direct-Port': serviceConfig.port,
'X-Direct-Protocol': serviceConfig.protocol,
'Cache-Control': 'no-cache'
}
});
}
/**
* IPv6 透明代理(备选方案:Worker中转但保持连接)
*/
async function handleIPv6Transparent(request, serviceConfig, clientIP) {
const url = new URL(request.url);
const originUrl = `${serviceConfig.protocol}://${serviceConfig.host}:${serviceConfig.port}${url.pathname}${url.search}`;
console.log(`[IPv6透明代理] ${clientIP} -> ${originUrl}`);
// 构建最小化请求头
const headers = new Headers();
ESSENTIAL_HEADERS.forEach(header => {
const value = request.headers.get(header);
if (value) headers.set(header, value);
});
headers.set('Host', serviceConfig.host);
headers.set('X-Real-IP', clientIP);
headers.set('X-Connection-Type', 'IPv6-P2P');
const fetchOptions = {
method: request.method,
headers: headers,
redirect: 'follow'
};
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method)) {
fetchOptions.body = request.body;
}
const response = await fetch(originUrl, fetchOptions);
// 构建响应
const responseHeaders = new Headers();
ESSENTIAL_RESPONSE_HEADERS.forEach(header => {
const value = response.headers.get(header);
if (value) responseHeaders.set(header, value);
});
responseHeaders.set('X-Connection-Type', 'IPv6-Transparent');
responseHeaders.set('X-Direct-Host', serviceConfig.host);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: responseHeaders
});
}
/**
* IPv4 CDN 代理
*/
async function handleIPv4CDN(request) {
const url = new URL(request.url);
const cacheTTL = getCacheTTL(url.pathname);
const headers = new Headers(request.headers);
headers.set('X-Proxy-Done', '1');
headers.set('X-Connection-Type', 'IPv4-CDN');
const modifiedRequest = new Request(request, {
headers: headers,
cf: {
cacheTtl: cacheTTL,
minify: {
javascript: true,
css: true,
html: false
},
polish: 'lossy',
mirage: true,
}
});
return fetch(modifiedRequest);
}
// ==========================================
// 主请求处理
// ==========================================
async function handleRequest(request) {
try {
const url = new URL(request.url);
const subdomain = url.hostname.split('.')[0];
const clientIP = request.headers.get('CF-Connecting-IP') || '';
// 健康检查端点
if (url.pathname === '/health' || url.pathname === '/_health') {
const isIPv6Client = isIPv6(clientIP);
return new Response(JSON.stringify({
status: 'ok',
region: 'Suzhou-CN',
connection: isIPv6Client ? 'IPv6-P2P' : 'IPv4-CDN',
clientIP: clientIP,
timestamp: Date.now(),
p2p: isIPv6Client ? 'direct' : 'cdn'
}), {
headers: { 'Content-Type': 'application/json' }
});
}
// 获取服务配置
const serviceConfig = getServiceConfig(subdomain);
if (!serviceConfig) {
return fetch(request);
}
// IPv6 用户:P2P 直连
if (isIPv6(clientIP)) {
// 检查是否强制使用透明代理模式
const useTransparent = url.searchParams.get('proxy') === 'transparent';
if (useTransparent) {
// 透明代理模式(Worker中转)
return await handleIPv6Transparent(request, serviceConfig, clientIP);
} else {
// P2P 直连模式(302重定向,默认)
return handleIPv6Direct(request, serviceConfig);
}
}
// IPv4 用户:CDN代理
return await handleIPv4CDN(request);
} catch (error) {
console.error('Worker错误:', error);
// 降级处理
try {
return await fetch(request);
} catch (e) {
return new Response(JSON.stringify({
error: '服务暂时不可用',
timestamp: Date.now()
}), {
status: 502,
headers: { 'Content-Type': 'application/json' }
});
}
}
}
// ==========================================
// 事件监听
// ==========================================
addEventListener('fetch', event => {
event.passThroughOnException();
event.respondWith(handleRequest(event.request));
});2.3 配置环境变量
在代码编辑器中,点击顶部 变量和机密 选项卡,添加以下环境变量:
📌 变量命名规则:
PORT_和SSL_后面的部分必须与你的用户访问子域名一致。
访问
b.example.com→ 配置PORT_b访问
pan.example.com→ 配置PORT_pan访问
nas.example.com→ 配置PORT_nas
我以NAS为例

2.4 部署 Worker
点击右上角 部署 按钮,确认部署成功。
第三步:绑定 Worker 路由
最后一步,让访问 b.example.com 的流量经过 Worker。
进入域名管理页 → Worker 路由(某些版本在 Workers 菜单下)
点击 添加路由
配置:
路由:
b.example.com/*Worker:选择你刚刚创建的 Worker
环境:
production
保存
同样以NAS为例


如果想增免端口访问(自行放行局域网V6防火墙)




完整数据流图解
用户浏览器
│
├─ 访问 b.example.com(CNAME → a.example.com,橙色云朵)
│
▼
Cloudflare CDN 边缘节点
│
├─ 触发 Worker 路由
│
├─ 判断客户端 IP 类型
│
├─── IPv6 客户端 ──→ 302 重定向至 http://a.example.com:8080
│ │
│ └──→ 浏览器直接连接源站 IPv6(灰云记录)
│
└─── IPv4 客户端 ──→ Worker 内部 fetch http://a.example.com:8080
│
└──→ CDN 节点代理转发响应给用户多服务扩展
如果你有多个服务需要代理,只需添加对应的环境变量:
IPV6_HOST = a.example.com
PORT_pan = 8080 # 网盘服务
SSL_pan = http
PORT_nas = 5000 # NAS管理面板
SSL_nas = https
PORT_tv = 8096 # Jellyfin
SSL_tv = http然后分别为每个子域名创建 CNAME 记录(都指向 a.example.com,开启代理),并添加对应的 Worker 路由即可。一个 Worker 搞定所有服务。
