背景
Discourse は、エンドユーザーの実際の IP アドレスを把握する必要があります。
ただし、Discourse コンテナ内で動作する nginx などの 1 つ以上の上流 Web サーバーが常にあるため、エンドユーザーは Discourse に直接接続することはありません。したがって、この情報を信頼できる方法で Discourse に渡す仕組みが必要です。
x-forwarded-for ヘッダーがその解決策です。このトピックでは、この情報を適切に処理するための具体的なメカニズムと、その伝播方法について説明します。
テンプレート
上流のプロキシを信頼するための各種テンプレート(例:cloudflare.template.yml や fastly.template.yml)は、テキスト置換(これは脆弱です)に依存するのではなく、アウトレットで予測可能なファイル名を使用するように更新されています。
ファイル名
server/real-ip-header.conf
このファイルには、コンテナ内で動作する nginx が信頼の基準として使用するヘッダーが含まれています。例えば:
real_ip_header x-forwarded-for;
または Cloudflare テンプレートで設定されている通り:
real_ip_header cf-connecting-ip;
server/real-ip-recursive.conf
このファイルが存在する場合、“実際の IP” ヘッダーの処理における再帰を制御します。Discourse コンテナ の前に複数のプロキシがある場合は、これを有効にする必要があります。
real_ip_recursive on;
例:
Cloudflare → ロードバランサー → Discourse コンテナ(nginx と Discourse 本体を含む)
この構成では、ロードバランサーの IP からの接続において、nginx は以下のような x-forwarded-for を受け取ります:
x-forwarded-for: real_end_user_ip, cloudflare_ip
これを処理するには、まず nginx が接続の送信元アドレス(ロードバランサーの IP)が信頼できるか(set_real_ip_from を参照)を判定し、信頼できる場合は x-forwarded-for ヘッダーの最後の IP を処理します。
その IP アドレスが cloudflare_ip であるため、nginx は次に cloudflare_ip が信頼できるかを確認し、次の IP アドレスである real_end_user_ip を使用するために、この処理を再度実行する必要があります。
server/set-real-ip-from-ENVIRONMENT.conf
このファイルには、nginx がどの IP アドレスを信頼するかを指示するディレクティブが含まれており、必要に応じて複数のファイルやディレクティブを持つことができます。
discourse_docker のテンプレートは必要に応じてこれらのファイルを作成します(例:set-real-ip-from-cloudflare.conf)。追加のニーズがある場合は、独自にファイルを追加できます。
例:
AWS 環境で Discourse コンテナの前に ALB(Application Load Balancer)を配置している場合、以下をコンテナ定義に追加することで(環境に合わせて調整)、追加のファイルを作成できます:
run:
- file:
path: /etc/nginx/conf.d/outlets/server/set-real-ip-from-aws.conf
chmod: 644
# AWS VPC は 10.42.0.0/16、ALB ネットワークからの接続をすべて信頼
contents: |
set_real_ip_from 10.42.66.0/24;
set_real_ip_from 10.42.67.0/24;
- file:
path: /etc/nginx/conf.d/outlets/server/real-ip-header.conf
chmod: 644
contents: |
real_ip_header x-forwarded-for;