cloudflare dns cloudflared mcp
](https://github.com/andrewkriley/cloudflare-dns-cloudflared-mcp/releases/latest)
用于管理的自托管MCP服务器 Cloudflare DNS 和 云焰隧道 服务——通过具有Google OAuth访问控制的Cloudflare隧道在您的家庭网络上公开SSH主机、web UI和其他服务。
在您自己的基础架构上作为Docker容器运行。通过承载令牌认证的HTTP连接到Claude Code或任何兼容MCP的客户端。
______________________________________________________________________
工具
域名系统
| 工具 | 说明 |
|---|---|
dns_list_zones | 列出帐户中的所有区域 |
dns_list_records | 列出区域的DNS记录 |
dns_create_record | 创建DNS记录(a、AAAA、CNAME、MX、TXT等) |
dns_update_record | 更新现有DNS记录 |
dns_delete_record | 删除DNS记录 |
隧道
| 工具 | 说明 |
|---|---|
tunnel_list | 列出所有Cloudflare隧道 |
tunnel_get | 获取隧道详细信息 |
tunnel_get_token | 获取cloudflared的连接器令牌 |
tunnel_list_connections | 列出活动隧道连接 |
隧道服务(工作流程)
| 工具 | 说明 |
|---|---|
service_list | 列出所有隧道中暴露的所有服务 |
service_expose_ssh | 通过基于浏览器的访问隧道暴露SSH主机 |
service_expose_web | 通过具有访问控制的隧道公开web UI |
service_remove | 删除服务--删除入口、DNS和Access应用程序 |
什么 service_expose_ssh 和 service_expose_web 做
每个工作流工具在一次调用中连接整个堆栈:
- 隧道入口规则 --将公共主机名映射到私有后端服务
- DNS名称 --积分
subdomain.yourdomain.com→[tunnel-id].cfargotunnel.com - Cloudflare访问应用程序 --可以到达服务站的登机口
- 访问策略 --允许特定的谷歌帐户,非谷歌电子邮件可选择一次性PIN(OTP)
______________________________________________________________________
先决条件
Cloudflare隧道
你需要跑步 cloudflared 隧道连接到您的家庭网络。在您的家庭服务器上安装cloudflared,并通过 Cloudflare零信任仪表板.隧道必须显示为 在线的 在通过它公开服务之前。
Google OAuth身份提供者
对于Google身份验证访问,请在Zero Trust仪表板中将Google配置为身份提供者 设置→ 认证这是一次性手动设置——MCP服务器管理每个服务的访问策略,而不是身份提供者本身。
______________________________________________________________________
快速开始
1.克隆
git clone git@github.com:andrewkriley/cloudflare-dns-cloudflared-mcp.git
cd cloudflare-dns-cloudflared-mcp2.配置
cp .env.example .env编辑 .env 并填写:
| 变量 | 描述 |
|---|---|
CF_API_TOKEN | Cloudflare API令牌(请参阅下面的权限) |
CF_ACCOUNT_ID | 您的Cloudflare帐户ID |
MCP_BEARER_TOKEN | MCP客户端身份验证的共享密钥——使用生成 openssl rand -hex 32 |
3.跑步
docker compose up -d检查它是否健康:
curl http://localhost:3000/health
# {"status":"ok"}4.连接克劳德代码
运行一次以注册服务器:
claude mcp add cloudflare-admin --transport http \
--header "Authorization: Bearer YOUR_MCP_BEARER_TOKEN" \
http://localhost:3000/mcp更换 YOUR_MCP_BEARER_TOKEN 与您的价值 .env.
5.示例用法
问克劳德:
“通过我的主隧道将我位于192.168.1.100:8006的Proxmox服务器暴露为Proxmox.yourdomain.com。允许访问user@gmail.com."
克劳德会打电话的 dns_list_zones, tunnel_list那么 service_expose_web 把所有东西都连接起来。
______________________________________________________________________
秘密与安全
环境变量
| 变量 | 灵敏度 | 目的 |
|---|---|---|
CF_API_TOKEN | Secret | Cloudflare API令牌-DNS+隧道+零信任权限 |
CF_ACCOUNT_ID | 低 | Cloudflare帐户标识符 |
MCP_BEARER_TOKEN | Secret | MCP端点身份验证的共享密钥 |
MCP_PORT | 低 | HTTP端口(默认值:3000) |
所有内容均已加载 .env 通过 docker composeThe .env 文件是gitignored的,绝不能提交。
创建Cloudflare API令牌
首选 dash.cloudflare.com/profile/api-tokes 并创建一个 自定义令牌 与:
| 范围 | 权限 |
|---|---|
| 区域>DNS | 编辑 |
| 帐户>Cloudflare隧道 | 编辑 |
| 账户>零信任 | 编辑 |
| 区域>区域 | 阅读 |
集合A 90天到期 在创建时。
代币轮换(每90天一次)
- 在以下位置创建新令牌 dash.cloudflare.com/profile/api-tokes
- 更新
CF_API_TOKEN在.env - 重新启动容器:
docker compose restart - 删除Cloudflare仪表板中的旧令牌
生成不记名代币
openssl rand -hex 32安全控制
| 控制 | 它做什么 |
|---|---|
| 承载令牌身份验证 | 全部 /mcp 请求需要 Authorization: Bearer |
| 非根容器 | 进程以无特权方式运行 mcp 用户 |
| 只读文件系统 | 容器根文件系统是只读的(tmpfs 为了 /tmp) |
| 没有新特权 | no-new-privileges:true 防止特权升级 |
/health 无身份验证 | 返回 {"status":"ok"} 仅--未暴露敏感数据 |
______________________________________________________________________
发展
不使用Docker在本地运行
npm install
cp .env.example .env
# fill in .env
npm run dev构建和测试
npm run build # compile TypeScript
npm run typecheck # type-check without emitting
npm run lint # ESLint
npm test # unit tests (mocked, no credentials needed)
npm run test:integration # integration tests (requires env vars — runs in CI)Docker命令
docker compose up -d # start in background
docker compose logs -f # tail logs
docker compose restart # restart after .env change
docker compose down # stop and remove container
docker compose build --no-cache # force rebuild image______________________________________________________________________
CI
每个推送和拉取请求都会运行:
| 检查 | 工具 | 目的 |
|---|---|---|
| 秘密扫描 | Gitleaks | 检测意外提交的令牌 |
| TypeScript检查 | tsc --noEmit | 严格的编译时正确性 |
| 埃斯林特 | eslint | 代码质量和风格 |
| 单元测试 | Vitest | 模拟测试——工作流工具逻辑 |
| 依赖性审计 | npm audit --audit-level=high | 标记高/严重漏洞 |
| Docker构建 | docker/build-push-action | 验证映像构建是否成功 |
| 隧道集成测试 | Vitest+真正的cloudflared | 针对真正的临时隧道的全生命周期 |
| 版本↔ package.json | npm run verify-version | 保持根 VERSION 和 package.json 同步 |
| 版本差异(PR) | 比较 VERSION 到基地 | 每个PR都必须颠簸 VERSION 当存在于基座上时(请参见 版本.md) |
PR需要进行上述所有检查才能合并到 main 一旦启用了分支保护。推标签 v*.*.* 运行 发布 工作流程(GitHub发布+GHCR镜像+ latest git标签)。
______________________________________________________________________
已知限制
浏览器呈现的SSH和短期证书
service_expose_ssh 为Cloudflare短期SSH证书设置正确的服务器端配置(TrustedUserCAKeys, AuthorizedPrincipalsFile,SSH CA)。然而, Cloudflare的浏览器渲染SSH终端使用libssh2 1.9.0,不支持OpenSSH证书身份验证。libssh2 1.11.0(2023)中添加了证书支持。
效果: 当通过浏览器终端访问SSH服务时,浏览器会提示输入私钥,而不是使用短期证书自动登录。
短期证书正常工作 用于通过以下方式访问本机SSH客户端 cloudflared 代理命令:
Host ssh.yourdomain.com
ProxyCommand cloudflared access ssh --hostname %h仅限浏览器访问的解决方案 (例如,当客户端网络上的出站SSH被阻止时):
选项A——在后端sshd上启用密码身份验证。 SSH端口不公开(只能通过Cloudflare Access门控的隧道访问)。Google OAuth背后的密码认证是一种可以接受的权衡:
# On the SSH backend host
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
sudo systemctl reload ssh选项B——部署一个web终端(潮湿)。 在后端主机上湿运行并将其作为web服务公开。浏览器通过HTTPS连接到wetty;wetty在本地主机上连接到sshd。libssh2没有限制。
docker run -d --restart unless-stopped \
--name wetty \
-p 3000:3000 \
wettyoss/wetty --ssh-host localhost --ssh-port 22 --base /然后通过暴露 service_expose_web 随着 backend_port: 3000, backend_protocol: httpCloudflare Access正常进行访问。
______________________________________________________________________
版本控制
规范版本是根 VERSION 文件(模式与 斯普伦克实验室).跑 npm run sync-version 将其复制到 package.json.推标签 v*.*.* 触发GitHub Release并将Docker镜像发布到 GHCR.
看 版本.md 对于完整的工作流、CI规则和标记格式。
______________________________________________________________________
贡献
main 受保护——所有更改均通过PR进行 dev.CI必须在合并前通过。直接推送到 main 被封锁。
