cloudflare-vpc-services
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare VPC Services
Cloudflare VPC Services
Enable Workers to securely access private APIs and services through encrypted tunnels without public internet exposure.
让Workers能够通过加密隧道安全访问私有API和服务,无需暴露在公网中。
⚠️ BEFORE YOU START
⚠️ 开始之前
This skill prevents 5 common errors and saves ~60% tokens.
| Metric | Without Skill | With Skill |
|---|---|---|
| Setup Time | 45+ min | 10 min |
| Common Errors | 5 | 0 |
| Token Usage | ~8000 | ~3000 |
本技能可避免5种常见错误,并节省约60%的token使用量。
| 指标 | 未使用技能 | 使用技能 |
|---|---|---|
| 设置时间 | 45+ 分钟 | 10 分钟 |
| 常见错误数量 | 5 | 0 |
| Token使用量 | ~8000 | ~3000 |
Known Issues This Skill Prevents
本技能可预防的已知问题
- from outdated cloudflared version or wrong protocol
dns_error - Requests leaving VPC due to using public hostnames instead of internal
- Port mismatch - fetch() port is ignored, service config port is used
- Missing absolute URLs in fetch() calls
- Incorrect tunnel ID or service binding configuration
- 因cloudflared版本过旧或协议错误导致的
dns_error - 因使用公网主机名而非内部主机名,导致请求流出VPC
- 端口不匹配 - fetch()中的端口会被忽略,将使用服务配置中的端口
- fetch()调用中缺少绝对URL
- 隧道ID或服务绑定配置错误
Quick Start
快速开始
Step 1: Verify Tunnel Requirements
步骤1:验证隧道要求
bash
undefinedbash
undefinedCheck cloudflared version on remote infrastructure (K8s, EC2, etc.)
检查远程基础设施(K8s、EC2等)上的cloudflared版本
Must be 2025.7.0 or later
必须为2025.7.0或更高版本
cloudflared --version
cloudflared --version
Verify QUIC protocol is configured (not http2)
验证已配置QUIC协议(而非http2)
Check tunnel config or Cloudflare dashboard
检查隧道配置或Cloudflare控制台
**Why this matters:** Workers VPC requires cloudflared 2025.7.0+ with QUIC protocol. Older versions or http2 protocol cause `dns_error`.
**为什么这很重要:** Workers VPC要求cloudflared版本为2025.7.0及以上,且使用QUIC协议。旧版本或http2协议会导致`dns_error`。Step 2: Create VPC Service
步骤2:创建VPC服务
bash
undefinedbash
undefinedUse Cloudflare API or dashboard to create VPC service
使用Cloudflare API或控制台创建VPC服务
See templates/vpc-service-ip.json or templates/vpc-service-hostname.json
参考templates/vpc-service-ip.json或templates/vpc-service-hostname.json
**Why this matters:** The VPC service defines the actual target (IP/hostname) that the tunnel routes to. The fetch() URL only sets Host header and SNI.
**为什么这很重要:** VPC服务定义了隧道要路由到的实际目标(IP/主机名)。fetch() URL仅用于设置Host头和SNI。Step 3: Configure Wrangler Binding
步骤3:配置Wrangler绑定
jsonc
// wrangler.jsonc
{
"vpc_services": [
{
"binding": "PRIVATE_API",
"service_id": "<YOUR_SERVICE_ID>",
"remote": true
}
]
}Why this matters: The binding name becomes the environment variable used in Worker code: .
env.PRIVATE_API.fetch()jsonc
// wrangler.jsonc
{
"vpc_services": [
{
"binding": "PRIVATE_API",
"service_id": "<YOUR_SERVICE_ID>",
"remote": true
}
]
}为什么这很重要: 绑定名称将成为Worker代码中使用的环境变量:。
env.PRIVATE_API.fetch()Critical Rules
关键规则
✅ Always Do
✅ 必须遵守
- ✅ Use absolute URLs with protocol, host, and path in fetch()
- ✅ Use internal VPC hostnames, not public endpoints
- ✅ Ensure cloudflared is 2025.7.0+ with QUIC protocol
- ✅ Allow UDP port 7844 outbound for QUIC connections
- ✅ 在fetch()中使用包含协议、主机和路径的绝对URL
- ✅ 使用内部VPC主机名,而非公网端点
- ✅ 确保cloudflared版本为2025.7.0及以上,且使用QUIC协议
- ✅ 允许UDP 7844端口的出站流量,用于QUIC连接
❌ Never Do
❌ 禁止操作
- ❌ Use port numbers in fetch() URL (they're ignored)
- ❌ Use public hostnames for services inside VPC
- ❌ Assume http2 protocol works (only QUIC is supported)
- ❌ Use relative URLs in fetch()
- ❌ 在fetch() URL中使用端口号(会被忽略)
- ❌ 为VPC内的服务使用公网主机名
- ❌ 假设http2协议可用(仅支持QUIC)
- ❌ 在fetch()中使用相对URL
Common Mistakes
常见错误示例
❌ Wrong:
javascript
// Port is ignored, relative URL fails
const response = await env.VPC_SERVICE.fetch("/api/users:8080");✅ Correct:
javascript
// Absolute URL, port configured in VPC service
const response = await env.VPC_SERVICE.fetch("https://internal-api.company.local/api/users");Why: The VPC service configuration determines actual routing. The fetch() URL only populates the Host header and SNI value.
❌ 错误写法:
javascript
// 端口会被忽略,相对URL会失败
const response = await env.VPC_SERVICE.fetch("/api/users:8080");✅ 正确写法:
javascript
// 使用绝对URL,端口在VPC服务中配置
const response = await env.VPC_SERVICE.fetch("https://internal-api.company.local/api/users");原因: VPC服务配置决定了实际路由规则。fetch() URL仅用于填充Host头和SNI值。
Known Issues Prevention
已知问题预防方案
| Issue | Root Cause | Solution |
|---|---|---|
| cloudflared < 2025.7.0 or http2 protocol | Update cloudflared, configure QUIC, allow UDP 7844 |
| Requests go to public internet | Using public hostname in fetch() | Use internal VPC hostname |
| Connection refused | Wrong port in VPC service config | Configure correct http_port/https_port in service |
| Timeout | Tunnel not running or wrong tunnel_id | Verify tunnel status, check tunnel_id |
| 404 errors | Incorrect path routing | Verify internal service path matches fetch() path |
| 问题 | 根本原因 | 解决方案 |
|---|---|---|
| cloudflared版本低于2025.7.0或使用http2协议 | 升级cloudflared,配置QUIC协议,允许UDP 7844端口 |
| 请求流向公网 | fetch()中使用了公网主机名 | 使用内部VPC主机名 |
| 连接被拒绝 | VPC服务配置中的端口错误 | 在服务中配置正确的http_port/https_port |
| 请求超时 | 隧道未运行或隧道ID错误 | 验证隧道状态,检查隧道ID |
| 404错误 | 路径路由配置错误 | 验证内部服务路径与fetch()中的路径一致 |
Configuration Reference
配置参考
wrangler.jsonc
wrangler.jsonc
jsonc
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2024-01-01",
"vpc_services": [
{
"binding": "PRIVATE_API",
"service_id": "daf43e8c-a81a-4242-9912-4a2ebe4fdd79",
"remote": true
},
{
"binding": "PRIVATE_DATABASE",
"service_id": "453b6067-1327-420d-89b3-2b6ad16e6551",
"remote": true
}
]
}Key settings:
- : Environment variable name for accessing the service
binding - : UUID from VPC service creation
service_id - : Must be
remotefor VPC servicestrue
jsonc
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2024-01-01",
"vpc_services": [
{
"binding": "PRIVATE_API",
"service_id": "daf43e8c-a81a-4242-9912-4a2ebe4fdd79",
"remote": true
},
{
"binding": "PRIVATE_DATABASE",
"service_id": "453b6067-1327-420d-89b3-2b6ad16e6551",
"remote": true
}
]
}关键设置:
- : 用于访问服务的环境变量名称
binding - : 创建VPC服务时生成的UUID
service_id - : 对于VPC服务必须设置为
remotetrue
Common Patterns
常见使用模式
Basic GET Request
基础GET请求
javascript
export default {
async fetch(request, env) {
const response = await env.PRIVATE_API.fetch(
"https://internal-api.company.local/users"
);
return response;
}
};javascript
export default {
async fetch(request, env) {
const response = await env.PRIVATE_API.fetch(
"https://internal-api.company.local/users"
);
return response;
}
};POST with Authentication
带认证的POST请求
javascript
const response = await env.PRIVATE_API.fetch(
"https://internal-api.company.local/users",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.API_TOKEN}`
},
body: JSON.stringify({ name: "John", email: "john@example.com" })
}
);javascript
const response = await env.PRIVATE_API.fetch(
"https://internal-api.company.local/users",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.API_TOKEN}`
},
body: JSON.stringify({ name: "John", email: "john@example.com" })
}
);API Gateway with Path Routing
带路径路由的API网关
javascript
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/users')) {
return env.USER_SERVICE.fetch(
`https://user-api.internal${url.pathname}`
);
} else if (url.pathname.startsWith('/api/orders')) {
return env.ORDER_SERVICE.fetch(
`https://orders-api.internal${url.pathname}`
);
}
return new Response('Not Found', { status: 404 });
}
};javascript
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/users')) {
return env.USER_SERVICE.fetch(
`https://user-api.internal${url.pathname}`
);
} else if (url.pathname.startsWith('/api/orders')) {
return env.ORDER_SERVICE.fetch(
`https://orders-api.internal${url.pathname}`
);
}
return new Response('Not Found', { status: 404 });
}
};Bundled Resources
附带资源
Templates
模板
Located in :
templates/- - Ready-to-use wrangler config with VPC bindings
wrangler-vpc.jsonc - - IP-based VPC service API payload
vpc-service-ip.json - - Hostname-based VPC service API payload
vpc-service-hostname.json
Copy these templates as starting points for your implementation.
位于目录下:
templates/- - 可直接使用的带VPC绑定的wrangler配置模板
wrangler-vpc.jsonc - - 基于IP的VPC服务API请求体模板
vpc-service-ip.json - - 基于主机名的VPC服务API请求体模板
vpc-service-hostname.json
可复制这些模板作为实现的起点。
Scripts
脚本
Located in :
scripts/- - List VPC services via Cloudflare API
list-vpc-services.sh - - Debug VPC connections with live logs
tail-worker.sh - - Set secrets for private API auth
set-api-token.sh
位于目录下:
scripts/- - 通过Cloudflare API列出VPC服务
list-vpc-services.sh - - 通过实时日志调试VPC连接
tail-worker.sh - - 设置私有API认证所需的密钥
set-api-token.sh
References
参考文档
Located in :
references/- - Comprehensive fetch() patterns and examples
api-patterns.md
位于目录下:
references/- - 全面的fetch()使用模式和示例
api-patterns.md
Dependencies
依赖项
Required
必须安装
| Package | Version | Purpose |
|---|---|---|
| wrangler | latest | Deploy Workers with VPC bindings |
| cloudflared | 2025.7.0+ | Tunnel daemon (on remote infrastructure) |
| 包名 | 版本 | 用途 |
|---|---|---|
| wrangler | latest | 部署带VPC绑定的Workers |
| cloudflared | 2025.7.0+ | 隧道守护进程(部署在远程基础设施上) |
Optional
可选安装
| Package | Version | Purpose |
|---|---|---|
| @cloudflare/workers-types | latest | TypeScript types for Workers |
| 包名 | 版本 | 用途 |
|---|---|---|
| @cloudflare/workers-types | latest | Workers的TypeScript类型定义 |
Official Documentation
官方文档
Troubleshooting
故障排查
dns_error when calling VPC service
调用VPC服务时出现dns_error
Symptoms: Worker returns when calling
dns_errorenv.VPC_SERVICE.fetch()Solution:
- Update cloudflared to 2025.7.0+ on remote infrastructure
- Configure QUIC protocol (not http2)
- Allow UDP port 7844 outbound
症状: 调用时,Worker返回
env.VPC_SERVICE.fetch()dns_error解决方案:
- 在远程基础设施上升级cloudflared到2025.7.0及以上版本
- 配置QUIC协议(而非http2)
- 允许UDP 7844端口的出站流量
Requests going to public internet
请求流向公网
Symptoms: Logs show requests hitting public endpoints instead of internal
Solution:
javascript
// Use internal hostname
const response = await env.VPC_SERVICE.fetch(
"https://internal-api.vpc.local/endpoint" // Internal
// NOT "https://api.company.com/endpoint" // Public
);症状: 日志显示请求命中了公网端点而非内部服务
解决方案:
javascript
// 使用内部主机名
const response = await env.VPC_SERVICE.fetch(
"https://internal-api.vpc.local/endpoint" // 内部地址
// 不要使用 "https://api.company.com/endpoint" // 公网地址
);Connection timeout
请求超时
Symptoms: Requests hang and eventually timeout
Solution:
- Verify tunnel is running: check cloudflared logs
- Verify tunnel_id matches in VPC service config
- Check network connectivity from tunnel to target
症状: 请求挂起并最终超时
解决方案:
- 验证隧道是否运行:检查cloudflared日志
- 验证VPC服务配置中的隧道ID是否正确
- 检查隧道到目标服务的网络连通性
Setup Checklist
设置检查清单
Before using this skill, verify:
- cloudflared 2025.7.0+ deployed on remote infrastructure
- QUIC protocol configured (not http2)
- UDP port 7844 outbound allowed
- VPC service created with correct tunnel_id
- wrangler.jsonc has vpc_services binding
- Using internal hostnames (not public endpoints)
- Using absolute URLs in fetch() calls
使用本技能前,请验证以下项:
- 远程基础设施上已部署2025.7.0及以上版本的cloudflared
- 已配置QUIC协议(而非http2)
- 已允许UDP 7844端口的出站流量
- 已创建带正确隧道ID的VPC服务
- wrangler.jsonc中已配置vpc_services绑定
- 使用的是内部主机名(而非公网端点)
- fetch()调用中使用的是绝对URL