ネットワーク · ゼロトラスト

Cloudflare Tunnel 入門 — ポートを開けずに社内サービスを安全に外部公開する

「Difyを在宅社員にも使わせたいが、ルーターのポートを開けるのはセキュリティ上怖い」——情シスが自社にAIツールを導入するときによく突き当たる壁だ。VPNを構築するにしても、設定は複雑でクライアント側にソフトのインストールが必要になる。

Cloudflare Tunnel はこの問題をまるごと解決する。サーバー側から Cloudflare のエッジへアウトバウンド接続を張るだけで、インターネット経由の安全なアクセスが完成する。ポートは一切開けない。サーバーのIPアドレスも公開されない。無料で使える。

この記事の検証環境
cloudflared
2026.6.0
OS
Ubuntu 22.04 LTS / Docker
Cloudflareプラン
無料(Zero Trust Free)
難易度
★★☆ Cloudflareアカウントとドメインが必要
Cloudflare Zero Trust の無料プランでトンネル数・帯域に制限なし(2026年7月時点)。

なぜCloudflare Tunnelか

従来の外部公開手段と比較する。

方法設定の複雑さセキュリティコスト主なデメリット
ポートフォワーディング❌ 低¥0サーバーIP露出・ルーター設定変更が必要
VPN(WireGuard等)✅ 高¥0〜クライアントへのインストール・鍵管理が必要
リバースプロキシ(ngrok等)△ 中月$8〜有料プランでないとURL固定不可
Cloudflare Tunnel✅ 高¥0Cloudflare管理ドメインが必要
✅ Cloudflare Tunnelの3つの強み
  • ポート開放ゼロ — サーバー側はアウトバウンド通信(TCP/UDP 7844)のみ。ルーターに一切触らない
  • IPアドレス非公開 — ユーザーが見るのは Cloudflare のエッジIPだけ。本番サーバーのIPが漏れない
  • Cloudflare WAF・DDoS保護が自動適用 — 無料プランでもエッジ側で基本的な保護が入る

仕組みを理解する

通信フロー
👤 ユーザーのブラウザ→ HTTPS☁️ Cloudflare エッジ→ トンネル経由🔌 cloudflared(社内サーバー)🤖 Dify / n8n 等

ポイント: cloudflared デーモンが サーバー側から Cloudflare エッジへアウトバウンド接続を確立・維持する。インバウンドのポートは不要。ユーザーのリクエストはそのトンネルを逆流して社内サービスに届く。


準備するもの

  • Cloudflare アカウント(無料)— dash.cloudflare.com で作成
  • Cloudflare に登録済みのドメイン(必須)— ネームサーバーが Cloudflare を向いていること。ドメイン自体はどこで買っても可
  • 公開したいサービスが動いているサーバー(Linux / Docker)— この記事では Ubuntu 22.04 と Docker Compose を使用

🐝 ドメインがない場合 Cloudflare Tunnel の利用にはドメインが必要。Cloudflare Registrar で取得すると管理が一元化できて便利(.com で年約 $10)。すでに別のレジストラでドメインを持っている場合は、ネームサーバーを Cloudflare に変更するだけでよい。


Step 1 — ダッシュボードでトンネルを作成(推奨・最短経路)

ダッシュボードから作成する方法が最もシンプルで、設定ファイルの管理が不要だ。

① トンネルを作成する

  1. Cloudflare ダッシュボード にログイン
  2. 左サイドバー「Networking」→「Tunnels」をクリック
  3. Create a tunnel」→ トンネルタイプ「Cloudflared」を選択 → Continue
  4. トンネル名を入力(例: my-services)→「Save tunnel

② cloudflared をサーバーにインストール

トンネル作成後、OS を選択するとインストールコマンドが表示される(トークンが埋め込まれているのでそのままコピーして使う)。

Ubuntu/Debian の場合、手動でインストールするには以下のコマンドを使う。

# Cloudflare GPGキーの追加
sudo mkdir -p --mode=0755 /usr/share/keyrings
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 any main' \
  | sudo tee /etc/apt/sources.list.d/cloudflared.list

# インストール
sudo apt-get update && sudo apt-get install -y cloudflared

# バージョン確認
cloudflared --version

③ サービスとして登録・起動

ダッシュボードに表示されたトークンを使ってサービスに登録する。

# <TOKEN> をダッシュボードのコマンドからコピーしたトークンに置き換える
sudo cloudflared service install <TOKEN>
sudo systemctl enable cloudflared
sudo systemctl start cloudflared

# ステータス確認
systemctl status cloudflared

成功するとダッシュボードのトンネル一覧に「Healthy」と表示される。

④ 公開するサービスを追加(Public Hostname)

  1. ダッシュボードのトンネル詳細画面 → 「Public Hostname」タブ → 「Add a public hostname
  2. 以下を入力して「Save hostname」
設定項目入力値の例
Subdomaindify
Domainexample.com(Cloudflareに登録済みのドメイン)
Service TypeHTTP
URLlocalhost:80(Difyのポート)

✅ これだけで公開完了 DNSレコード(CNAMEエントリ)は Cloudflare が自動で作成する。数分後に https://dify.example.com でアクセスできるようになる。証明書(HTTPS)も自動で発行される。


Step 2 — Docker 環境での設定

n8n や Dify を Docker Compose で動かしている場合、cloudflared もコンテナで動かすのが管理しやすい。トークン方式を使えば config ファイルなしで動く。

# docker-compose.yml に追記
services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel --no-autoupdate run
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
    restart: unless-stopped
    networks:
      - app-network  # 他のサービスと同じネットワーク

.env ファイルにトークンを追記する。

# .env
CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoixxxx...(ダッシュボードのトークンをそのまま貼る)
# コンテナを起動
docker compose up -d cloudflared

# ログ確認
docker compose logs cloudflared
🐝 Docker ネットワーク内のサービスへの接続
  • cloudflared が 同じ Docker ネットワークにいる場合 → サービス名で指定: http://dify-nginx:80
  • cloudflared が 別ネットワーク or ホストの場合 → ホストのLAN IP: http://192.168.x.x:80
  • localhost はコンテナ自身を指すため、別コンテナのサービスには繋がらない(Docker localhost問題と同じ)

Step 3 — 複数サービスをまとめて公開する(config.yml)

複数のサービス(Dify・n8n・社内ポータルなど)を1つのトンネルで公開するには、config.yml にインgressルールを書く方法が柔軟だ。

① トンネルとクレデンシャルを準備する(CLIで作成する場合)

# Cloudflare にログイン(ブラウザが開いて認証)
cloudflared tunnel login

# トンネルを作成(~/.cloudflared/<TUNNEL-ID>.json が生成される)
cloudflared tunnel create my-services

# トンネルIDを確認
cloudflared tunnel list

② config.yml を作成する

# /etc/cloudflared/config.yml
tunnel: <TUNNEL-ID>         # cloudflared tunnel list で確認したID
credentials-file: /root/.cloudflared/<TUNNEL-ID>.json

ingress:
  # Dify(ポート80)
  - hostname: dify.example.com
    service: http://localhost:80
  # n8n(ポート5678)
  - hostname: n8n.example.com
    service: http://localhost:5678
  # 社内Wikiなど
  - hostname: wiki.example.com
    service: http://localhost:3000
  # ⚠️ 最後にキャッチオール(必須)
  - service: http_status:404

⚠️ キャッチオールルールは必須 インgressルールの最後- service: http_status:404 が必ず必要。これがないと cloudflared の起動時にエラーになる。

③ DNS レコードを追加してトンネルを起動

# DNSレコードを自動追加(ホスト名の数だけ実行)
cloudflared tunnel route dns my-services dify.example.com
cloudflared tunnel route dns my-services n8n.example.com
cloudflared tunnel route dns my-services wiki.example.com

# サービスとして登録・起動
sudo cloudflared service install
sudo systemctl enable --now cloudflared

Step 4 — Cloudflare Access で認証を追加する

トンネルを公開しただけだと、URLを知っている人なら誰でもアクセスできてしまう。社内限定にするには Cloudflare Access(ゼロトラストアクセス制御)で認証を追加する。

🐝 Cloudflare Access 無料プランでできること 最大50ユーザーまで無料(2026年7月時点)。Google / GitHub / Microsoft などの外部 IdP で SSO 認証が可能。小規模チームなら無料枠で十分。

① アプリケーションを作成する

  1. Cloudflare ダッシュボード → 「Zero Trust」→「Access」→「Applications
  2. Add an application」→「Self-hosted」を選択
  3. アプリ名・ドメイン(例: dify.example.com)を入力 → Next

② アクセスポリシーを設定する

設定項目
Policy name社内スタッフのみ
ActionAllow
Include ルールEmail ends in @yourcompany.co.jp

「Save policy」→「Save application」で完了。以後 dify.example.com にアクセスすると、まず Cloudflare の認証画面(Googleログインなど)が表示され、許可済みメールアドレスでないとアクセス拒否される。

✅ 設定後のアクセスフロー
  1. 社員が https://dify.example.com にアクセス
  2. Cloudflare Access が認証ページを表示(Google SSO 等)
  3. 社内ドメインのメールアドレスでログイン → JWT トークン発行
  4. 認証成功後のみ、Dify の画面が表示される
VPNも追加ソフトも不要。社員はブラウザだけで使える。

トラブルシュート

① トンネルが「Inactive」のまま

原因:cloudflared サービスが起動していない。

対処:systemctl status cloudflared でエラーを確認。journalctl -u cloudflared -n 50 でログを確認してエラーメッセージを特定する。

② ブラウザで「502 Bad Gateway」エラー

原因:cloudflared からバックエンドサービスへの接続が失敗している。URL / ポートの指定ミスが多い。

対処:サービスと同じサーバー上で curl http://localhost:ポート番号 を実行し、サービス自体が応答しているか確認する。Docker 環境ではコンテナ名(サービス名)とネットワーク設定を確認。

③ cloudflared が起動しない(ファイアウォールブロック)

原因:cloudflared は TCP/UDP ポート 7844 でアウトバウンド通信する。企業ファイアウォールがこのポートをブロックしている場合がある。

対処:cloudflared 2026.5.2 以降は起動時に自動で接続診断を実行し、ブロックされている場合はログにメッセージが出る。UDP 7844 が塞がれていても HTTP/2(TCP 7844)にフォールバックするため、通常は自動で回復する。

④ Docker コンテナで「permission denied」エラー

原因:config.yml や credentials JSON ファイルのパーミッションが cloudflared コンテナ内ユーザーから読めない。

対処:chmod 644 config.ymlchmod 600 tunnel-id.json を実行する。

⑤ config.yml を使っているのに「No ingress rules」エラー

原因:ingress ルールの末尾にキャッチオール行がない。

対処:config.yml の ingress セクション最後に - service: http_status:404 を追加する(hostname 指定なし)。


まとめ

Cloudflare Tunnel は「ポートを開けずに外部公開したい」情シスの課題にぴったりはまる。特に Dify や n8n などのセルフホストサービスと組み合わせると、社内に閉じていたAIツールを在宅社員にも安全に届けるインフラが1時間以内に構築できる。

まず試すなら
ダッシュボード方式

設定ファイル不要でGUI操作のみ。サービスを1〜2個公開するだけならこれで十分。最速15分でhttps化まで完成する。

Docker 環境なら
トークン + Compose

既存の docker-compose.yml に数行追記するだけ。環境変数でトークンを管理するのでgitにシークレットを残さない。

セキュリティを高めるなら
Cloudflare Access を追加

50ユーザーまで無料。社内メールドメインだけ許可する設定で、VPNなしに「社員だけが使えるサービス」が完成する。

✅ 次のステップ Access の認証をさらに本番仕様に仕上げたい場合は Cloudflare Access 設定編(IdP連携・WARP・VPN置換)へ進もう。Dify や n8n を Access で守った上でさらに活用するならDify FAQ ボットn8n × Dify 連携ワークフローも参照してほしい。