mod_remoteip を使って LB 配下の Apache もアクセス元 IP を正しく認識できる

LB やリバースプロキシが Web サーバーの前段にいる場合、アクセス元 IP はそれらの IP に変わってしまう事がほとんどだと思います。(AWS ELB もそうですね。)

なので、このままだと

  • ログに本当のアクセス元 IP が記録されない
  • IP アドレスによるアクセス制限ができない

といった辺りで支障をきたす事になります。

Apache 2.2 までは LB で(たいてい)付与される X-Forwarded-For を使ってロギングやアクセス制限を実装していましたが、Apache 2.4 からは mod_remoteip という便利モジュールが導入されました。
https://httpd.apache.org/docs/current/mod/mod_remoteip.html

このモジュールを使うと、リクエストを開始したユーザーの IP をリモート IP として Apache に認識させる事ができて、ロギングやアクセス制限にサクッと利用する事が可能になります。

設定方法

RemoteIPHeader X-Forwarded-For

Server コンテキストや VirtualHost にこんな感じで設定を追加すると、これ以降 Apache は X-Forwarded-For に格納されていた IP をリモート IP として認識するようになります。

なお、RemoteIPInternalProxyRemoteIPTrustedProxy の設定はせず、単純に上記設定だけ行うと、X-Forwarded-For 一番先頭のアドレス (通常はリクエストを開始したユーザーのアドレス) をリモート IP として認識するようです。
↑ 挙動からの推測です。

利用方法1 : ロギング

LogFormat でログのフォーマットを指定する際に %a を利用すればリモートIPが書き込まれます。

combined の互換?として combined-remote-ip というフォーマットを定義する例

LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined-remote-ip

利用方法2 : アクセス制限

例えば、WordPress の管理者ログイン画面 (wp-login.php) に特定の IP からしかアクセスさせたくない時は

RemoteIPHeader X-Forwarded-For

<LocationMatch ^/wp-login\.php$>
    Require ip 111.222.333.444
</LocationMatch>

こんな感じで、X-Forwarded-For を意識しないといけなかった 2.2 以前と比べて、だいぶ直感的にリモート IP アドレスを取得・利用できるようになりました。便利。

(参考にさせて頂いた記事)
ELB配下のApacheでのアクセス制御 | Developers.IO
http://dev.classmethod.jp/cloud/aws/access-limit-behind-elb/