Nginx proxy_set_header関連のモジュール、ヘッダ | onox blog

onox blog

Nginx proxy_set_header関連のモジュール、ヘッダ

February 11, 2019

nginxのproxysetheader関連のモジュール(realipheader)、ヘッダ(X-Forwarded-For、X-Real-IP)あたりの設定方法を記載する。

環境

nginx: 1.14.1

構成はロードバランサーを挟んだ以下だとする。

client <-> ALB(SSL終端) <-> nginx <-> backend

登場人物

nginxのこの辺のパラメータ

set_real_ip_from 0.0.0.0/0;
real_ip_header   X-Forwarded-For;

proxy_set_header X-Real-IP $remote_addr;

remote_addr

nginxの組み込み変数。client(アクセス元)のIPアドレスを表す。

このように、前段のIPが参照される。

client
↓
ALB: remote_addr is client
↓
nginx: remote_addr is ALB
↓
backend: remote_addr is nginx

real_ip_header

nginxのモジュール。remote_addrを書き換える。X-Forwarded-Forは後述。

real_ip_header   X-Forwarded-For;

X-Forwarded-For

client(アクセス元)のIPアドレスが記載されたHTTPヘッダ。remote_addrとは異なり、前段がどこから転送されてきたか?の情報がのっている。ALBにアクセスがきた時点では中身は空で、ALBの仕様(機能)としてX-Forwarded-Forを付与してnginxに転送している。何のヘッダを付与するかは使用しているロードバランサーの設定次第となる。

なお今回の例だと、X-Forwarded-Forの値は単数だが、

client
↓
ALB: X-Forwarded-For: ""nginx: X-Forwarded-For: client

多段proxyの場合は、X-Forwarded-Forは以下のよう増えていく。特定clientのIPを取得するには、real_ip_recursiveを使用する。(今回は省略)

client
↓
ALB: X-Forwarded-For: ""nginx: X-Forwarded-For: client
↓
nginx: X-Forwarded-For: client, nginx

話戻って、以下のよう設定することでremote_addrの値をX-Forwarded-Forの値(clientのIPアドレス)に書き換える。

set_real_ip_from 0.0.0.0/0;
real_ip_header   X-Forwarded-For;

以下は、real_ip_headerモジュールの使用(remote_addrの書き換え)を許可するアクセス元IPアドレス範囲。前段がALBだけなら所属するVPCのアドレス帯を指定しておく。(アドレス範囲が特定できないサービスからアクセスがある場合は、0.0.0.0/0でALL許可する)

set_real_ip_from 0.0.0.0/0;

X-Real-IP

client(アクセス元)のIPアドレスが記載されたHTTPヘッダ。X-Forwarded-Forとは異なり、proxyを経由するたびに増えはしない。

ALBが付与しているヘッダについて

ALBは以下ヘッダを付与してproxy(nginx)に転送している。Elastic Load Balancing

  • X-Forwarded-For
  • X-Forwarded-Prot
  • X-Forwarded-Port

Application Load Balancer と クラシックロードバランサー は [X-Forwarded-For]、[X-Forwarded-Prot]、[X-Forwarded-Port] ヘッダーをサポートします。

nginx側で変更が必要ない場合はディレクティブとして記載不要。

clientがHTTPSでアクセスした場合、付与されるヘッダは以下の通りとなる。

X-Forwarded-For: client IP
X-Forwarded-Prot: HTTPS
X-Forwarded-Port: 443

その他X-xxxヘッダシリーズ

proxyを経由してきたclient(アクセス元)の何らかの情報が入ってるヘッダだと思えばOK。

proxy_set_headerをbackend側でどう利用するか

Railsを例に説明すると、Rackのscheme判定とかport判定とかが挙げられる。

その他の例

  • deviseでSNS認証(e.g. Google)を実装する場合、callback先のURLに、HTTP_HOSTヘッダが利用されるようなので、正しいHOSTヘッダを付与する必要がある。何もしない場合はHTTP_HOSTがnginxのupstream名(e.g. backend)になってしまい正しくリダイレクトできない。
proxy_set_header HOST $host

まとめ

# remote_addr書き換えを許可するアクセス元IP帯
set_real_ip_from 0.0.0.0/0;
# remote_addrをclientIPに書き換える
real_ip_header   X-Forwarded-For;

# clientIPをX-Real-IPヘッダに付与
proxy_set_header X-Real-IP $remote_addr;

情報ソース

Nginx ポケットリファレンス