Action Cableのオリジンチェックがリバースプロキシ環境でも正しく動作するよう修正

rails/rails

リバースプロキシ環境でAction CableのオリジンチェックがHTTP_HOSTヘッダーを直接参照していたため、X-Forwarded-Hostが使用される構成では接続が拒否される問題がありました。本PRではrequest.host_with_portrequest.ssl?を使用するよう修正し、Railsの他の部分と一貫したホスト解決が行われるようになります。

背景

Action Cableの allow_same_origin_as_host チェックは、ブラウザが送信するOriginヘッダーとサーバー側のホスト情報を比較することでCSRF攻撃を防ぐ仕組みです。しかし従来の実装では、比較対象のホストとして生のHTTP_HOSTヘッダーを直接参照していました。

リバースプロキシ構成では、プロキシが内部サーバーへリクエストを転送する際にHTTP_HOSTがプロキシの内部ホスト名になる一方、公開ホストはX-Forwarded-Hostヘッダーで伝達されます。この場合、ブラウザが送信するOrigin(公開ホスト名ベース)とHTTP_HOST(内部ホスト名)が一致せず、正当なリクエストでもRequest origin not allowedエラーが発生します。

Railsの他の部分ではrequest.hostrequest.host_with_portを通じてX-Forwarded-Hostを考慮したホスト解決が行われており、Action Cableのオリジンチェックだけが生のRackヘッダーを直接参照するという不一致が生じていました。

技術的な変更

actioncable/lib/action_cable/connection/base.rballow_request_origin? メソッドで、ホストとプロトコルの解決方法が変更されました。

変更前:

proto = Rack::Request.new(env).ssl? ? "https" : "http"
if server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}"

変更後:

proto = request.ssl? ? "https" : "http"
if server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{request.host_with_port}"

変更は2点です。まず Rack::Request.new(env).ssl?request.ssl? に置き換えられました。connection/base.rb内ではすでにrequestメソッドが定義されており、その再利用です。次に env['HTTP_HOST']request.host_with_port に置き換えられました。request.host_with_portActionDispatch::Requestのメソッドであり、X-Forwarded-Hostヘッダーが存在する場合にその値を優先して返します。

テストも大幅に拡充されており、以下のシナリオが追加されています:

  • X-Forwarded-Hostが設定された場合に同一オリジンを許可すること
  • X-Forwarded-HostHTTP_HOSTより優先されること
  • プロキシチェーン(proxy1.example.com, proxy2.example.com)では末尾のホストが使用されること
  • 非標準ポート(:3000付き)の場合もポートを含めた完全一致が行われること
  • X-Forwarded-ProtoによるHTTPS判定が機能すること

設計判断

最小限の変更でRails全体との一貫性を確保する方針 が採用されました。

オリジンチェックのロジック自体は変更されておらず、ホストとプロトコルの取得元をRackレベルの生ヘッダーからAction Dispatchのrequestオブジェクト経由に切り替えるだけの修正です。requestオブジェクトへの委譲によって、ActionDispatch::Requestがすでに実装しているX-Forwarded-*ヘッダーの処理ロジックをそのまま活用できます。PRの説明にも「consistent with how the rest of Rails resolves the host」と明記されており、独自実装を排除してフレームワーク内の既存の仕組みに統一することが意図的な設計判断として示されています。

まとめ

本PRは2行の変更で、Action Cableのオリジンチェックをリバースプロキシ環境に対応させたものです。独自ロジックを排除してrequestオブジェクトに委譲することで、X-Forwarded-*ヘッダーの扱いがRails全体で統一され、プロキシ環境特有の追加設定なしに正常な接続が可能になります。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
c4db5cc9

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術的変更・設計判断(各論)→まとめ(結論)という「総論→各論→結論」の3部構成が明確に守られています。各セクションの役割も適切です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライト(```ruby:ファイルパス)およびPR番号のリンク記法([PR #56775](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

リバースプロキシ、`X-Forwarded-Host`、`Origin`ヘッダーといった専門用語を前提として解説しており、対象読者であるエンジニアに適した技術レベルと表現になっています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションの冒頭に要旨が述べられ、各段落はトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が遵守されています。可読性が非常に高いです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

actioncable/lib/action_cable/connection/base.rbに対する変更前後のコード引用がDiffと完全に一致しています。また、テストの拡充に関する説明もテスト用Diffの内容を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`HTTP_HOST`, `X-Forwarded-Host`, `request.host_with_port`などの技術用語がPRの文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

リバースプロキシ環境で`HTTP_HOST`が問題になる理由や、`request.host_with_port`が`X-Forwarded-Host`を考慮する仕組みの説明が技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(問題の背景、変更内容、設計方針)が、提供されたPRのDescriptionやDiff内容によって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#56775)やファイルパス(actioncable/lib/action_cable/connection/base.rb)が正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトル「Action Cableのオリジンチェックがリバースプロキシ環境でも正しく動作するよう修正」は、PRタイトル「Update Action Cable origin check to respect X-Forwarded-Host」の内容を的確に要約しており、主題に一貫性があります。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PRに記載のないバージョン情報やサポート状況などの外部知識は含まれていません。`request.host_with_port`の挙動説明は、PR内の「consistent with how the rest of Rails resolves the host」という記述を補足するものであり、許容範囲です。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「従来の実装」といった時間表現は、変更の前後関係を正しく示しており、PRの内容と矛盾しません。