概要
AWS の ALB 配下に apache を置いた場合、apache へのアクセス元 IP は ALB のアドレスになります。多くの場合、これは嬉しくなく、ALB へのアクセス元の IP が欲しくなります。
ALB はアクセス元 IP を X-Forwared-For ヘッダに設定してくれるので、ここからアクセス元 IP を抽出し、apache 側でアクセス元 IP として利用することができます。それには mod_remoteip を使用します。
この通り、ただそれだけの簡単な話なのですが、意外と設定に手間どってしまったので、設定方法を書いておきます。もちろん、mod_remoteip のドキュメントに記載してあるわけですが・・・少なくとも私には分かり辛かったです。
ここで解説するのは internet 向けの ALB での設定方法です。LAN 内で使用する ALB の場合は別の設定になりますので注意ください。
設定方法
httpd.conf にて mod_remoteip を読み込むようにします。
LoadModule remoteip_module modules/mod_remoteip.so
X-Forwarded-For ヘッダの値でアクセス元IP を上書くように設定します。
# Overwrite remoteip with X-Forwarded-For header value
<IfModule remoteip_module>
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxyList conf/trusted-proxies.lst
</IfModule>
RemoteIPTrustedProxyList を以下のように設定します。
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
これにて設定完了です。#反映には apache を restart する必要があります。
apache のアクセスログに "%a" で出力設定できる client ip が ALB の IP でなく、ALB へのアクセス元の IP になります。やったね!
ポイント解説
RemoteIPTrustedProxyList conf/trusted-proxies.lst
をちゃんと設定するのが肝要です。
信頼できる proxy ということですが、これを理解するには X-Forwarded-For が信頼できるのか、ということを考えると良いと思います。
X-Forwarded-For はただの HTTP header です。これは送信者が自由に設定することができます。
例えば、あなたのブラウザからリクエストを送信する際、X-Forwarded-For: XXX.XXX.XXX.XXX
みたいな感じに header を設定しておけば、受信サーバ側に XXX.XXX.XXX.XXX からアクセスが来たと思わせることができます。これでは受信サーバは騙されホーダイなので、RemoteIPTrustedProxyList を設定して、そこにない IP によって設定された X-Forwarded-For を信頼しない(辿るのをやめる)ようにします。
例えば、X-Forwarded-For: XXX.XXX.XXX.XXX, YYY.YYY.YYY.YYY, ZZZ.ZZZ.ZZZ.ZZZ
が送られて来たとします。RemoteIPTrustedProxyList を設定していない場合、アクセス元 IP として XXX.XXX.XXX.XXX が利用されます。右から順に走査して、一番左の IP まで辿り着いた、ということです。RemoteIPTrustedProxyList を設定している場合(かつ、それが X-Forwarded-For に設定している IP を含まない場合)、アクセス元 IP として ZZZ.ZZZ.ZZZ.ZZZ が利用されます。
internet 向けの ALB のアクセス元 IP が欲しい場合、通常、X-Forwarded-For header の最後に付与された値(=最も右の値)が欲しいと思うので、上で記載したように、trusted-proxies.lst に private IP を指定すれば良いと思います。#ALB と apache が同一の LAN 内に存在している(ALB → apache の通信のアクセス元 IP はALB の private IP になる)ことを仮定しています。
ちなみにですが、ローカル開発環境などで、本設定の動作確認をする際の注意点があります。X-Forwarded-For に private IP を設定していると、うまくいかない可能性があります。なぜなら、X-Forwarded-For を右から順に走査していって private IP に行き当たると、mod_remoteip は X-Forwarded-For header を丸ごと無視してしまうからです。internet 向けの LB の場合、このようなケースは存在しない(ことが期待される)からだと思います。#mod_remoteip は internet 向けと internal 向けで設定内容が異なりますので、internal 向けの場合は本記事は参考にできません。
終わりに
やりたいことは単純でも、設定に手間取ることってありますよねー。