cloudflare-zero-trust について
cloudflare-zero-trust は Cloudflare Zero Trust の設定スキルです。トンネル、ID ポリシー、デバイスチェック、DNS フィルタリングで、内部サービスとリモートアクセスを保護します。
主な機能
- 01Tunnel による内部サービスの公開
- 02ID ベースのアプリケーションアクセス設定
- 03デバイスポスチャチェックの適用
- 04Gateway DNS フィルタリングの設定
- 05WARP によるトラフィックのルーティング
活用シーン
- 01内部アプリへの VPN アクセスの置き換え
- 02SSH または RDP のリモートアクセス保護
- 03DNS による悪意あるドメインの遮断
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill cloudflare-zero-trustインストール後、Claude Code で/cloudflare-zero-trustを入力して読み込まれたか確認します。
詳細
Cloudflare Zero Trust
CloudflareのZero Trustプラットフォーム(Access、Tunnel、Gateway、WARP)を使用して、VPNなしで内部サービスへのアクセスを保護します。
使用する場面
- 内部Webアプリケーション、SSH、RDPへのアクセスをVPNから置き換える場合。
- 内部ツール(ダッシュボード、管理パネル)に対して、ID認識型のアクセスポリシーを適用する場合。
- オンプレミスまたはプライベートネットワークのサービスを、リモートチームに安全に公開する場合。
- DNSトラフィックをフィルタリングして、マルウェア、フィッシング、シャドーITをブロックする場合。
- デバイスの状態チェック(管理対象デバイス、OSバージョン、ディスク暗号化)を適用する場合。
前提条件
- Zero TrustプランのCloudflareアカウント(無料プランは最大50ユーザーに対応)。
- Cloudflare上のドメイン(Accessアプリケーションのホスト名用)。
- IDプロバイダーの設定(Google Workspace、Okta、Azure AD/Entra ID、GitHub)。
- 内部サービスをホストするサーバーに
cloudflaredCLIをインストールしていること。
# Install cloudflared
# macOS
brew install cloudflared
# Debian/Ubuntu
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install -y cloudflared
# Docker
docker pull cloudflare/cloudflared:latest
Cloudflare Tunnelのセットアップ
Tunnelは、インフラストラクチャからCloudflareのエッジへの暗号化されたアウトバウンド接続を作成し、インバウンドポートを開放する必要をなくします。
Tunnelの作成と設定
# Authenticate with Cloudflare
cloudflared tunnel login
# Create a named tunnel
cloudflared tunnel create internal-apps
# This creates credentials at ~/.cloudflared/<TUNNEL_ID>.json
# List tunnels
cloudflared tunnel list
# Route DNS to the tunnel (creates a CNAME record)
cloudflared tunnel route dns internal-apps grafana.example.com
cloudflared tunnel route dns internal-apps wiki.example.com
cloudflared tunnel route dns internal-apps ssh.example.com
Tunnel設定ファイル
# ~/.cloudflared/config.yml
tunnel: <TUNNEL_ID>
credentials-file: /home/deploy/.cloudflared/<TUNNEL_ID>.json
ingress:
# Grafana dashboard
- hostname: grafana.example.com
service: http://localhost:3000
# Internal wiki
- hostname: wiki.example.com
service: http://localhost:8080
originRequest:
noTLSVerify: true
# SSH access via browser
- hostname: ssh.example.com
service: ssh://localhost:22
# Private network access (CIDR routing)
- hostname: internal.example.com
service: http://10.0.0.0/24
# Catch-all — required as the last rule
- service: http_status:404
Tunnelの実行
# Run in foreground (for testing)
cloudflared tunnel run internal-apps
# Install as a systemd service
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
# Or run via Docker
docker run -d --name cloudflared \
--restart unless-stopped \
-v /home/deploy/.cloudflared:/etc/cloudflared \
cloudflare/cloudflared:latest \
tunnel run internal-apps
Tunnelを使用したDocker Compose
# docker-compose.yml
version: "3.8"
services:
cloudflared:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=${TUNNEL_TOKEN}
networks:
- internal
grafana:
image: grafana/grafana:latest
networks:
- internal
wiki:
image: requarks/wiki:2
networks:
- internal
networks:
internal:
driver: bridge
アクセスポリシー
アクセスポリシーは、Cloudflareの背後にあるアプリケーションにアクセスできるユーザーを制御します。
Accessアプリケーションの作成
# Via API — create a self-hosted application
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" \
-d '{
"name": "Grafana",
"domain": "grafana.example.com",
"type": "self_hosted",
"session_duration": "12h",
"auto_redirect_to_identity": true,
"allowed_idps": ["<IDP_UUID>"]
}'
ポリシーの種類と例
# Allow policy — members of the engineering group
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" \
-d '{
"name": "Engineering Team",
"decision": "allow",
"include": [
{ "group": { "id": "<GROUP_UUID>" } }
],
"require": [
{ "login_method": { "id": "<MFA_METHOD_UUID>" } }
]
}'
一般的なポリシーパターン
| パターン | Includeルール | Requireルール |
|---|---|---|
| 全従業員 | メールドメイン@company.com | - |
| エンジニアリング部門のみ | Access Group "Engineering" | MFA |
| 契約社員(期間限定) | メールリスト | デバイスの状態 |
| CI/CDの自動化 | サービストークン | - |
| 外部パートナー | 特定のメールアドレス | 国の確認 |
自動化用サービストークン
# Create a service token for CI/CD
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/service_tokens" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "github-actions-deploy"}'
# Response includes Client ID and Client Secret
# Use in CI with headers:
# CF-Access-Client-Id: <CLIENT_ID>
# CF-Access-Client-Secret: <CLIENT_SECRET>
# Use service token in CI/CD
curl -H "CF-Access-Client-Id: $CF_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_CLIENT_SECRET" \
https://grafana.example.com/api/health
デバイスの状態チェック
アクセスを許可する前に、エンドポイント要件を適用します。
状態チェックの設定(ダッシュボード)
- Settings > WARP Client > Device postureに移動します。
- チェック項目を追加します。
- ディスク暗号化:FileVault(macOS)またはBitLocker(Windows)を必須にします。
- OSバージョン:macOS 14.0以降、またはWindows 11を必須にします。
- ファイアウォール:ホストファイアウォールが有効であることを確認します。
- Crowdstrike/SentinelOne:EDRエージェントが実行中であることを確認します。
- AccessポリシーのRequireルールで状態チェックを参照します。
Gateway DNSフィルタリング
DNSレベルで悪意のあるドメインをブロックし、適切な利用ポリシーを適用します。
DNSロケーション
# Configure DNS endpoints for offices or networks
# Dashboard: Gateway > DNS Locations > Add a location
# Assign the Gateway DNS IPs to your network's DNS resolver:
# IPv4: 172.64.36.1, 172.64.36.2
# IPv6: 2606:4700:4700::1111
# DoH: https://<UNIQUE_ID>.cloudflare-gateway.com/dns-query
DNSポリシー
# Create a DNS policy to block malware and phishing
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Block Security Threats",
"enabled": true,
"action": "block",
"traffic": "any(dns.security_category[*] in {80 83 131 134 151 153})",
"filters": ["dns"]
}'
一般的なDNSポリシールール
| ルール名 | トラフィック式 | アクション |
|---|---|---|
| マルウェアをブロック | any(dns.security_category[*] in {80 83}) | ブロック |
| フィッシングをブロック | any(dns.security_category[*] in {131 134}) | ブロック |
| ソーシャルメディアをブロック | any(dns.content_category[*] in {75}) | ブロック |
| 例外を許可 | dns.fqdn == "allowed.example.com" | 許可 |
WARPクライアントのデプロイ
Cloudflare WARPクライアントをデプロイして、Gateway経由でトラフィックをルーティングします。
# MDM deployment — macOS configuration profile
# Use Cloudflare's managed deployment:
# Dashboard: Settings > WARP Client > Device enrollment
# Manual enrollment
# 1. Install WARP client from https://1.1.1.1
# 2. Click gear icon > Account > Login with Cloudflare Zero Trust
# 3. Enter your team name (from Settings > General)
# Verify WARP is connected
curl https://connectivity.cloudflare.com/cdn-cgi/trace
# Look for: warp=on
WARPのスプリットトンネル
# Configure split tunnels to exclude certain traffic from WARP
# Dashboard: Settings > WARP Client > Device settings > Split Tunnels
# Exclude mode (default): WARP handles everything except listed IPs
# Include mode: WARP only handles listed IPs/domains
# Common exclusions:
# - Local network: 192.168.0.0/16, 10.0.0.0/8
# - Video conferencing: zoom.us, *.teams.microsoft.com
# - Printer subnets
SSHとブラウザーベースのターミナル
# In cloudflared config.yml — expose SSH via browser rendering
ingress:
- hostname: ssh.example.com
service: ssh://localhost:22
# Users access ssh.example.com in their browser
# Cloudflare renders an in-browser terminal after Access authentication
# Or use cloudflared on the client side for native SSH
cloudflared access ssh --hostname ssh.example.com
# Add to SSH config for seamless access
# ~/.ssh/config
# Host ssh.example.com
# ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
トラブルシューティング
| 症状 | 原因 | 対処方法 |
|---|---|---|
ダッシュボードでトンネルが ERR と表示される | cloudflared が実行されていない、または設定にエラーがある | systemctl status cloudflared を確認し、設定 YAML を検証します |
| 正しい ID なのにアクセスすると 403 が返される | ポリシーの順序、または require ルールがない | ポリシーは上から順に評価されます。Allow が Block より上にあることを確認します |
| WARP に「Unable to connect」と表示される | チーム名が間違っている、または登録が無効になっている | Settings > General でチーム名を確認し、登録権限を確認します |
| サービストークン認証に失敗する | トークンの有効期限切れ、またはヘッダーが間違っている | トークンを再生成し、CF-Access-Client-Id と CF-Access-Client-Secret の両方を使用します |
| DNS フィルタリングでブロックされない | クライアントが Gateway DNS リゾルバーを使用していない | DNS が 172.64.36.1 に設定されていることを確認し、WARP が接続されていることを確認します |
| トンネルのレイテンシーが急増する | トンネルが過負荷のホストで実行されている | cloudflared のリソース使用量を監視し、専用インフラで実行します |
| 「No healthy origins」エラー | バックエンドサービスが停止している | 設定された ingress ポートでサービスを確認し、cloudflared のログを確認します |
関連スキル
- cloudflare-workers - Access ポリシーの背後で動作するエッジコンピューティング
- dns-management - DNS ルーティングとレコード管理
- reverse-proxy - 代替ゲートウェイパターン
- service-mesh - 内部サービス間のセキュリティ
コメント
Markdown 対応