Cloudflare DNS和隧道管理服务

一个自托管的MCP服务器,用于管理Cloudflare DNS和cloudflared隧道服务,通过Cloudflare Tunnels和Google OAuth访问控制,将家庭网络中的SSH主机、Web UI等服务暴露到公网。

  • by andrewkriley
  • TypeScript
  • 本地部署
  • 3 星标
  • 更新于
在 GitHub 查看 andrewkriley/cloudflare-dns-zt-mcp

使用说明

cloudflare dns cloudflared mcp

用于管理的自托管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 做

每个工作流工具在一次调用中连接整个堆栈:

  1. 隧道入口规则 --将公共主机名映射到私有后端服务
  2. DNS名称 --积分 subdomain.yourdomain.com → [tunnel-id].cfargotunnel.com
  3. Cloudflare访问应用程序 --可以到达服务站的登机口
  4. 访问策略 --允许特定的谷歌帐户,非谷歌电子邮件可选择一次性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-mcp

2.配置

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天一次)

  1. 在以下位置创建新令牌 dash.cloudflare.com/profile/api-tokes
  2. 更新 CF_API_TOKEN 在 .env
  3. 重新启动容器: docker compose restart
  4. 删除Cloudflare仪表板中的旧令牌

生成不记名代币

openssl rand -hex 32

安全控制

控制 它做什么
承载令牌身份验证 全部 /mcp 请求需要 Authorization: Bearer <token>
非根容器 进程以无特权方式运行 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 被封锁。