| name | deploying-cloudflare-access-for-zero-trust |
| description | 部署 Cloudflare Access 和 Cloudflare Tunnel,为自托管和私有应用程序提供零信任访问, 配置身份感知访问策略、设备态势检查,以及用于 VPN 替代的 WARP 客户端注册。
|
| domain | cybersecurity |
| subdomain | zero-trust-architecture |
| tags | ["cloudflare","cloudflare-access","zero-trust","cloudflare-tunnel","warp","ztna","cloudflare-one"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
为零信任部署 Cloudflare Access
适用场景
- 使用 Cloudflare One 以身份感知应用访问取代 VPN 基础设施时
- 通过 Cloudflare Tunnel 暴露自托管内部应用程序而无需开放入站端口时
- 为分布式员工队伍访问 Web 应用、SSH 和 RDP 服务实施 ZTNA 时
- 需要具备集成 DLP、CASB 和 SWG 能力的经济高效零信任解决方案时
- 确保承包商和第三方对特定应用的访问而不赋予完整网络访问权限时
不适用于需要 Cloudflare Tunnel 不支持的持久 UDP 连接的应用程序、需要气隔离或完全本地访问控制的环境,或法规要求禁止通过第三方云基础设施路由流量的场景。
前置条件
- 具有零信任订阅的 Cloudflare 账户(最多 50 名用户免费,大型团队需付费计划)
- 由 Cloudflare DNS 管理的域名(或能够添加 CNAME 记录)
- 用于运行
cloudflared 隧道守护进程的 Linux、Windows 或 macOS 服务器
- 身份提供商:Okta、Microsoft Entra ID、Google Workspace、GitHub 或任何 SAML/OIDC 提供商
- 用于设备级注册的 Cloudflare WARP 客户端(可选但推荐)
工作流程
步骤 1:创建连接内部应用的 Cloudflare Tunnel
安装 cloudflared 并创建持久隧道以暴露内部服务。
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
-o cloudflared.deb
sudo dpkg -i cloudflared.deb
cloudflared tunnel login
cloudflared tunnel create internal-apps
cat > ~/.cloudflared/config.yml << 'EOF'
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/admin/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
ingress:
- hostname: wiki.company.com
service: http://localhost:8080
- hostname: git.company.com
service: http://10.1.1.50:3000
- hostname: grafana.company.com
service: http://10.1.1.60:3000
- hostname: ssh.company.com
service: ssh://localhost:22
- hostname: rdp.company.com
service: rdp://10.1.1.100:3389
- service: http_status:404
EOF
cloudflared tunnel route dns internal-apps wiki.company.com
cloudflared tunnel route dns internal-apps git.company.com
cloudflared tunnel route dns internal-apps grafana.company.com
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
cloudflared tunnel info internal-apps
步骤 2:配置身份提供商集成
配置与组织身份提供商的认证集成。
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Corporate Okta",
"type": "okta",
"config": {
"client_id": "OKTA_CLIENT_ID",
"client_secret": "OKTA_CLIENT_SECRET",
"okta_account": "company.okta.com",
"api_token": "OKTA_API_TOKEN",
"claims": ["email", "groups", "name"],
"email_claim_name": "email"
}
}'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Microsoft Entra ID",
"type": "azureAD",
"config": {
"client_id": "AZURE_APP_CLIENT_ID",
"client_secret": "AZURE_APP_CLIENT_SECRET",
"directory_id": "AZURE_TENANT_ID",
"support_groups": true,
"claims": ["email", "groups", "name"]
}
}'
步骤 3:创建访问应用和策略
为每个内部服务定义具有身份感知策略的访问应用。
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Internal Wiki",
"domain": "wiki.company.com",
"type": "self_hosted",
"session_duration": "8h",
"auto_redirect_to_identity": true,
"http_only_cookie_attribute": true,
"same_site_cookie_attribute": "lax",
"logo_url": "https://company.com/wiki-logo.png",
"allowed_idps": ["OKTA_IDP_ID", "AZURE_IDP_ID"]
}'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id}/policies" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Allow Engineering Team",
"decision": "allow",
"precedence": 1,
"include": [
{"group": {"id": "ENGINEERING_GROUP_ID"}},
{"okta": {"name": "Engineering", "identity_provider_id": "OKTA_IDP_ID"}}
],
"require": [
{"device_posture": {"integration_uid": "CROWDSTRIKE_INTEGRATION_ID"}}
]
}'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "SSH Access",
"domain": "ssh.company.com",
"type": "ssh",
"session_duration": "4h",
"auto_redirect_to_identity": true
}'
步骤 4:部署 WARP 客户端进行设备注册
使用 Cloudflare WARP 注册企业设备,以实现私有网络访问和设备态势检查。
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Corporate Device Enrollment",
"match": "identity.email matches \".*@company\\.com$\"",
"precedence": 100,
"enabled": true,
"gateway_unique_id": "GATEWAY_ID",
"support_url": "https://helpdesk.company.com/warp-help"
}'
cat > warp_mdm_config.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>organization</key>
<string>company</string>
<key>auto_connect</key>
<integer>1</integer>
<key>switch_locked</key>
<true/>
<key>onboarding</key>
<false/>
</dict>
</plist>
EOF
sudo cp cloudflare-root-ca.pem /usr/local/share/ca-certificates/cloudflare-root-ca.crt
sudo update-ca-certificates
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy/{policy_id}/fallback_domains" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '[
{"suffix": "internal.corp", "description": "内部企业域名"},
{"suffix": "10.0.0.0/8", "description": "私有网络范围"}
]'
步骤 5:配置设备态势检查
将端点安全信号集成到访问策略中。
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture/integration" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "CrowdStrike Falcon",
"type": "crowdstrike_s2s",
"config": {
"api_url": "https://api.crowdstrike.com",
"client_id": "CS_API_CLIENT_ID",
"client_secret": "CS_API_CLIENT_SECRET",
"customer_id": "CS_CUSTOMER_ID"
},
"interval": "10m"
}'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Disk Encryption Required",
"type": "disk_encryption",
"match": [{"platform": "windows"}, {"platform": "mac"}],
"input": {"requireAll": true}
}'
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/posture" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Minimum OS Version",
"type": "os_version",
"match": [{"platform": "windows"}],
"input": {"version": "10.0.19045", "operator": ">="}
}'
步骤 6:设置审计日志和分析
配置访问决策日志记录和隧道健康监控。
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/logpush/jobs" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "access-audit-logs",
"output_options": {
"field_names": ["RayID","Action","Allowed","AppDomain","AppUUID","Connection","Country","CreatedAt","Email","IPAddress","PurposeJustificationPrompt","PurposeJustificationResponse","TemporaryAccessDuration","UserUID"],
"timestamp_format": "rfc3339"
},
"destination_conf": "s3://security-logs-bucket/cloudflare-access/?region=us-east-1&access-key-id=AKID&secret-access-key=SECRET",
"dataset": "access_requests",
"enabled": true
}'
curl -X POST "https://api.cloudflare.com/client/v4/graphql" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"query": "{ viewer { accounts(filter: {accountTag: \"ACCOUNT_ID\"}) { accessLoginRequestsAdaptiveGroups(filter: {datetime_gt: \"2026-02-22T00:00:00Z\"}, limit: 100, orderBy: [count_DESC]) { dimensions { action appName userEmail country } count } } } }"
}'
核心概念
| 术语 | 定义 |
|---|
| Cloudflare Tunnel | 从基础设施到 Cloudflare 网络的仅出站加密连接,无需开放入站防火墙端口即可暴露内部服务 |
| Cloudflare Access | 身份感知反向代理,在授权访问受保护应用前评估每个请求 |
| WARP Client | Cloudflare 端点 Agent,将设备流量路由到 Cloudflare 网络以执行策略和访问私有网络 |
| Access Application(访问应用) | 定义受保护资源(自托管、SaaS 或基础设施)及其关联访问策略的配置对象 |
| Device Posture(设备态势) | 端点健康信号(操作系统版本、磁盘加密、EDR 状态),作为访问策略的条件评估 |
| Cloudflare One | 统一 SASE 平台,整合 ZTNA(Access)、SWG(Gateway)、CASB、DLP 和 RBI |
工具与系统
- Cloudflare Access:提供每请求授权的身份感知应用代理
- Cloudflare Tunnel(cloudflared):从内部网络到 Cloudflare 边缘创建加密隧道的守护进程
- WARP Client:用于设备注册、DNS 过滤和私有网络路由的跨平台端点 Agent
- Cloudflare Gateway:提供 DNS/HTTP 过滤和 DLP 检查的安全 Web 网关
- Cloudflare Logpush:向外部 SIEM 和存储目标实时流式传输日志
- Access for Infrastructure:基于短期证书和会话录制的 SSH 和 RDP 访问
常见场景
场景:拥有 200 名员工的初创公司从零开始部署零信任
场景背景:一家拥有 200 名员工的 SaaS 初创公司没有现有 VPN,希望为运行在 AWS 上的内部工具(Grafana、内部 API、暂存环境)提供安全访问。预算有限,团队没有专职安全人员。
方法:
- 从 Cloudflare Zero Trust 免费版(最多 50 名用户)开始概念验证
- 在生产 VPC 的 EC2 实例上部署一个
cloudflared 隧道
- 通过隧道和 DNS 路由暴露 Grafana、内部 wiki 和暂存应用
- 配置 Google Workspace 作为 IdP 进行单点登录认证
- 创建要求所有应用使用 @company.com 邮箱域的访问策略
- 添加磁盘加密和操作系统版本的设备态势检查
- 升级到付费计划,通过 MDM 将 WARP 客户端部署到所有员工笔记本
- 启用 Gateway DNS 过滤和 HTTP 检查以防范恶意软件
- 配置 Logpush 将访问日志发送到 Datadog 进行监控
常见陷阱:TLS 检查功能需要在所有设备上安装 Cloudflare 根证书,某些应用可能因 TLS 拦截而中断。隧道故障转移需要运行多个 cloudflared 实例或使用 Cloudflare 的副本功能。访问策略应始终包含默认拒绝规则。WebSocket 应用可能需要特定的隧道配置。
输出格式
Cloudflare Zero Trust 部署报告
==================================================
组织:StartupCorp
团队名称:startupcorp
部署日期:2026-02-23
隧道基础设施:
活跃隧道:2(主 + 故障转移)
隧道状态:健康
连接边缘:华盛顿特区、Ashburn
入站路由:8
访问应用:
自托管应用:6
SaaS 应用:3
SSH/基础设施:2
总策略数:15
设备注册:
已注册设备:187 / 200
WARP 已连接:182 / 187(97.3%)
态势合规:175 / 187(93.6%)
访问指标(过去 30 天):
总请求数:89,432
已允许:88,756(99.2%)
已拦截:676(0.8%)
唯一用户数:195
国家/地区:12
平均会话时长:6.2 小时