ELB や CloudFront を挟んだら ngx_http_realip_module / mod_remoteip も忘れずに設定する

Posted on

先日、キャッシュしない CloudFront とそのメリット・デメリットについて書きましたが、ELB や CloudFront を挟んだら nginx や Apache のクライアント IP に関する設定も忘れずにやっておいた方がいいです。

ELB や CloudFront に限らずですが、プロキシやロードバランサを挟むと Web サーバのログにはそれらの IP アドレスが記録されます。正確にはネットワーク上の直前の IP アドレスがクライアント IP として送られてきます。

Client 124.xx.xx.xx
 |
CloudFront 54.xx.xx.xx (Client IP = 124.xx.xx.xx)
 |
ELB 172.xx.xx.xx (Client IP = 54.xx.xx.xx)
 |
Web Server (Client IP = 172.xx.xx.xx)

こういうときは X-Forwarded-For ヘッダを見れば、もともとのクライアント IP がわかります。上の例だと X-Forwarded-For ヘッダは次のようになっています。

X-Forwarded-For: 124.xx.xx.xx, 54.xx.xx.xx, 172.xx.xx.xx

X-Forwarded-For はデフォルト設定のままだとログに吐かれません。また、IP アドレスでアクセス制御を行なっている場合も何かと都合が悪いです。

最近の Web サーバにはクライアント IP を取得する仕組みが備わっているので、ネットワーク構成を変更したら忘れずに設定しておきましょう。

nginx の ngx_http_realip_module

nginx は ngx_http_realip_module を使います。パッケージインストールの場合はデフォルトで有効になっていますが、コンパイルしてインストールする場合は --with-http_realip_module というパラメータが必要です。

$ nginx -v
nginx version: nginx/1.10.1

$ nginx -V 2>&1 | grep -o -e '--with-http_realip_module'
--with-http_realip_module

nginx.conf に設定を追加します。

real_ip_header X-Forwarded-For;
set_real_ip_from 172.31.0.0/16;

HTTP ヘッダは自由に書き換えられるので、信頼できるネットワークからの HTTP ヘッダのみ採用します。上の場合は ELB を想定して VPC のプライベート IP を指定しています。

Apache の mod_remoteip

Apache 2.4 から mod_remoteip が使えるようになり、nginx と同じような設定ができるようになりました。

$ httpd -v
Server version: Apache/2.4.23 (Amazon)
Server built:   Jul 29 2016 21:42:17

$ httpd -M | grep remoteip
 remoteip_module (shared)

設定もディレクティブ名が違うだけで nginx とほぼ同じです。

RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 172.31.0.0/16

CloudFront の IP レンジ

ELB の場合は自分で IP レンジを設計できますが、CloudFront の場合は AWS が持つグローバル IP になります。

AWS IP アドレスの範囲」を参考に CloudFront の IP レンジをコマンドで取得します。

$ curl https://ip-ranges.amazonaws.com/ip-ranges.json -o ip-ranges.json

$ jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' < ip-ranges.json
13.32.0.0/15
52.46.0.0/18
52.84.0.0/15
52.222.128.0/17
54.182.0.0/16
54.192.0.0/16
54.230.0.0/16
54.239.128.0/18
54.239.192.0/19
54.240.128.0/18
204.246.164.0/22
204.246.168.0/22
204.246.174.0/23
204.246.176.0/20
205.251.192.0/19
205.251.249.0/24
205.251.250.0/23
205.251.252.0/23
205.251.254.0/24
216.137.32.0/19

ELB と CloudFront をどちらも使っている場合は set_real_ip_from / RemoteIPTrustedProxy にこれらの IP アドレスを列挙すれば OK です。

real_ip_header X-Forwarded-For;

# ELB
set_real_ip_from 172.31.0.0/16;

# CloudFront
set_real_ip_from 13.32.0.0/15;
set_real_ip_from 52.46.0.0/18;
...

まとめ

この設定をしなくてもとりあえず動いてしまうので、あとでログを集計するときに初めて気づくパターンが多いです。あとから慌てないように、忘れずに設定しておきたいですね。