本文へ移動
技術を、自社の仕事に。
判断と実行を助けるメディア

記事を検索

Cloudflare TunnelのURL正規化 管理画面だけ保護は要確認

目次 · 6項目

社内の管理画面や業務ツールをCloudflare Tunnelで公開し、/admin/ のようにパスを区切って、その部分だけCloudflare Accessのログインを求めている。そうした構成を運用しているなら、今回の変更は一度確認しておくべきものです。パスの書き方次第では、保護したはずのルールではなく、保護のない別のルールに振り分けられる可能性があるためです。

Cloudflareは2026年10月22日、Tunnelの接続ソフト cloudflared の2026.10.0以降で、ingressルール(どのホスト名・パスをどのサービスへ流すかの規則)を選ぶ前にURLを正規化できるようになったと告知しました。変更履歴には、Accessの検証を求めるルールがあるトンネルの安全性を高めるためと書かれています。

Starting from version 2026.10.0, Cloudflare Tunnel can normalize URLs before matching ingress rules. This improves security for tunnels with rules that require Cloudflare Access validation. The URL path sent to your origin stays the same.

この設定は今は既定でオフです。2027年1月25日以降に出る新しい版から、既定でオンになります。

何が起きうるのか

cloudflared は、ingressルールを上から順に見て、最初に一致したルールでリクエストを処理します。管理画面だけを保護する構成は、たとえば次のように書きます(説明用の設定です)。

ingress:
  - hostname: app.example.com
    path: ^/admin/
    service: http://localhost:8080
    originRequest:
      access:
        required: true   # cloudflaredがAccessのJWTを確かめてから転送する
        teamName: example-team
        audTag:
          - <AccessアプリケーションのAUDタグ>
  - hostname: app.example.com
    service: http://localhost:8080   # それ以外は検証なしで同じアプリへ
  - service: http_status:404

ここに /x/../admin/users のようなパスが届くと、文字列としては ^/admin/ に一致しないため、2番目の「検証なし」のルールに振り分けられます。一方、転送先のアプリやWebサーバーが .. を解決すれば、実際に開かれるのは /admin/users です。

cloudflared の変更履歴(リポジトリの RELEASE_NOTES)では、2026.10.0の項目が「VULN-141859: Normalize request path when using access rules」となっており、脆弱性の管理番号が付いています。追加された起動オプションの説明にも、正規化しないことの危険が書かれています。

An unnormalized request path could bypass Cloudflare Access rules and reach a protected origin.

正規化で変わること、変わらないこと

公式ドキュメント(設定ファイルの「How traffic is matched」)によると、正規化は次の3つです。

  • . と .. を、RFC 3986の手順で取り除く
  • バックスラッシュ(\)をスラッシュに変える
  • 連続するスラッシュを1つにまとめる

正規化したパスは、ルールを選ぶためだけに使われます。転送先(オリジン)に送るパスは変わりません。ドキュメントの例では、/hello/../path はルールの判定には /path を使い、オリジンには /hello/../path のまま送ります。

また、正規化がかかるのは、Accessの検証を求めるルール(access.required: true)が設定にあるトンネルだけです。リポジトリのソース(ingress/ingress.go)でも、検証を求めるルールがない場合はパスに手を加えない作りになっています。変更履歴は「Accessの検証を求めるルールがない設定は影響を受けない」としています。

今回の方式は2回目の対応です。2026.8.0で一度パスの正規化を入れたあと、2026.8.2で取り消しています。取り消しの後で入った2026.10.0の修正のコミットには、前回の方式で転送先のパスまで書き換えたため、Next.jsのルートグループやWordPressの末尾のスラッシュで不具合が出たと書かれています。今回は転送先のパスを変えない方式にし、互換性を壊す可能性があるため既定ではオフにした、という経緯です。

2つの版で確かめた結果

編集部の検証環境(Ubuntu 24.04.5、x86_64)で、GitHubのリリースから取得した cloudflared 2026.9.3と2026.10.0の公式バイナリを使い、上の設定ファイルに対して cloudflared tunnel ingress rule を実行しました。このコマンドは、指定したURLがどのルールに一致するかを、トンネルを起動せずに表示します。

cloudflared tunnel --config admin-first.yml ingress rule "https://app.example.com/x/../admin/users"
試したパス2026.9.32026.10.0
/admin/usersルール0(Access検証あり)ルール0(Access検証あり)
/x/../admin/usersルール1(検証なし)ルール0(Access検証あり)
/x/%2e%2e/admin/usersルール1(検証なし)ルール0(Access検証あり)
//admin/usersルール1(検証なし)ルール0(Access検証あり)
/x\..\admin/usersルール1(検証なし)ルール0(Access検証あり)

2026.9.3では、/admin/ を含むのに保護のないルールへ振り分けられる書き方が4通りありました。2026.10.0では、いずれもAccessの検証があるルールに一致しました。Accessの検証を求めるルールを外した設定で同じ確認をすると、2026.10.0でも /x/../admin/users はルール1のままでした。

2つのcloudflaredの版で、/x/../admin/users へのリクエストがどのingressルールに一致するかを比べた図。2026.9.3では、文字列として ^/admin/ に一致しないため、Access検証のないルール1に振り分けられる。2026.10.0の ingress rule コマンドでは、判定用に /admin/users へ正規化され、Access検証のあるルール0に一致する。オリジンへ送るパスはどちらも変わらない

確認コマンドは「正規化した後」の結果を出す

ここで1点、注意があります。2026.10.0の ingress rule コマンドは、起動オプションの --disable-path-normalization=true(既定値)や環境変数 TUNNEL_DISABLE_PATH_NORMALIZATION=true を付けても、正規化した後の結果を表示しました。リポジトリのソース(cmd/cloudflared/tunnel/ingress_subcommands.go)を見ると、このコマンドは設定ファイルを読んでそのまま判定しており、起動オプションの値を渡していません。オプションの値が反映されるのは、トンネルを動かすときの処理(orchestration)です。

つまり、2026.10.0で ingress rule を実行して「保護されたルールに一致する」と出ても、既定のまま cloudflared tunnel run で動かしているトンネルは、正規化せずにルールを選んでいます。確認コマンドの結果を、稼働中のトンネルの挙動と読み替えないでください。正規化を有効にした後の振り分けを事前に確かめる用途には使えます。

有効にする前に見ておくこと

ここからは編集部の整理です。Accessの検証を求めるルールを使っているトンネルでは、既定が変わる2027年1月25日を待たずに、次の順で確かめておくと安全です。

  1. 版を上げる:cloudflared --version で版を確かめ、2026.10.0以降にします。2026年10月27日時点の最新は、10月26日に公開された2026.10.4です。2026.10.4には別の脆弱性の修正(VULN-176088)も入っています。修正のコミットによると、メトリクスサーバーの /debug/vars から、コマンドラインで渡した --token などの起動時の引数が読めた問題です(編集部では未検証)。上げるなら2026.10.4以降を選びます
  2. 振り分けを確かめる:設定ファイルの各ルールについて、正規化した後にどのルールに一致するかを ingress rule で確かめます。特に、パスで別のサービスに分けている構成や、正規表現で細かく分けている構成は、一致するルールが変わる可能性があります
  3. 有効にする:起動時に --disable-path-normalization=false を付けるか、各レプリカで環境変数 TUNNEL_DISABLE_PATH_NORMALIZATION=false を設定して再起動します。複数のレプリカで動かしている場合は、すべてに設定します
  4. パスの書き方を見直す:今回の検証では、/admin(末尾のスラッシュなし)は ^/admin/ に一致せず、最後の404のルールに落ちました。保護したい範囲は ^/admin(/|$) のように境界まで意識して書きます

あわせて、保護をパスの区切りだけに頼らない構成も検討に値します。管理画面を別のホスト名に分け、そのホスト名全体をAccessで保護すれば、パスの書き方による振り分けの違いを考える必要がなくなります。また、転送先のアプリ側でも、AccessのJWTを検証する、管理画面のルーティングで認証を必須にする、といった多層の防御を残しておきます。

パスの書き方の違いで保護をすり抜ける問題は、ほかのソフトでも起きています。OpenNext Cloudflareの認証すり抜けでは、エンコードしたパスでミドルウェアの判定を外れる条件を扱いました。Accessで社内のMCPサーバーをまとめて保護する構成は、社内MCPサーバーの入口を1つにで整理しています。

確認した範囲

2026年10月23日に、Cloudflareの変更履歴「Cloudflare Tunnel supports URL normalization」(2026年10月22日)、設定ファイルのドキュメント(How traffic is matched)、起動オプションと接続先の設定のリファレンスを、公式ドキュメントのソースリポジトリ(cloudflare/cloudflare-docs)で確認しました。あわせて、cloudflare/cloudflared リポジトリの RELEASE_NOTES、2026.10.0の修正コミット、ingress/ingress.go などのソースを確認しました(資料調査)。編集部の検証環境(Ubuntu 24.04.5、x86_64)で、公式バイナリの2026.9.3と2026.10.0を使い、説明用の設定ファイルに対して cloudflared tunnel ingress rule を実行しました(実機検証)。実際のトンネルの起動、Cloudflareのエッジを通ったリクエストが cloudflared にどの形で届くか、Accessの認証の動作、転送先のアプリが .. をどう解決するかは確認していません。公開前の2026年10月27日に、変更履歴とドキュメントの公開ページ、cloudflared のリリースとソースを見直し、2026.10.4の公開を追記しました。2026.10.4での ingress rule の再実行はしていません。

社内ツールの公開経路や認証の設計・見直しは、開発・AI・自動化のご相談からお問い合わせください。

参考資料

この記事を共有XFacebook
鈴木 翔

技術の可能性に魅了され、学生時代からプログラミングとデジタルアートの分野に深い関心を持つ

この記事のテーマを、自社の次の一歩へ

自社での進め方を、具体的に。

つくりたい仕組み、既存システム、運用の条件を整理し、実現に向けた次の一歩を考えます。

  • 実現したい仕組み
  • 既存環境との接続
  • 運用の条件
開発・運用の構想を相談する

構想段階からご相談いただけます。この記事の情報を相談フォームに引き継ぎます。

最新記事をメールで受け取る