ELB配下のEC2(Web/Appサーバー)へのアクセスは、全てELB経由のアクセスとなるため、ELBがつけるX-Forwardes-Forヘッダーを参照することで、アクセス元のIPアドレスを確認出来ます。これをX-Forwarded-Forではなく、Remote-Addrを書き換える事によって解決しようとするのが、mod_extract_forwarded(apache 2.2系)でした。このモジュールは、各種ディストリビューションの標準パッケージに入っていないことが多く、ソースからコンパイル、もしくは拡張パッケージリポジトリからインストールします。Apache2.4系からは、mod_remoteipというモジュールがこれに相当します。どうやら標準パッケージ扱いとなり、AmazonLinux でも Httpd24 というパッケージでインストールすると入ります。
設定は、既存設定の流儀に従い、/etc/httpd/conf.modules.d/00-remoteip.conf とでもします。(httpd.confに書いてもいいです。)
LoadModule remoteip_module modules/mod_remoteip.so
<IfModule remoteip_module>
RemoteIPHeader x-forwarded-for
RemoteIPProxiesHeader Remote_Addr <- 書き換えるヘッダー名RemoteIPTrustedProxy 10.1.0.0/24 <- ELBの内側IP(だけど書けないので、SubnetかVPC)
</IfModule>
RemoteIPTrustedProxyについては、ELBの内側(ローカルIP)を指定します。これはHealthCheckに来るIPアドレスのはずですが、ELBそもそもIPアドレス固定ではないので、VPCやSubnetなど、レンジで指定するしかなさそうです。これで Apache再起動で完了です。きちんと反映されているかを確かめるには、phpが使えるなら phpinfoが楽です。
<?php
phpinfo();
?>
また、DNS逆引きをしたい場合ですが、この場合はApache側ではなんともなりません。一見 Remote_Addrを書き換えたのだから、HostnameLookups on とすれば、X-Forwardes-Forのアドレスによる逆引きが出来そうですが、Apacheの環境変数REMOTE_HOSTは、Remote_Addrのヘッダー(環境変数)書き換えとは別に実行されるので、ホスト名は必ずELBのホスト名になります。(Apacheモジュールでなんとかすることは出来ましたが、HostnameLookups on による決定を覆すことは出来ず、汎用性もないです。)
ELB越しのX-Forwarded-Forについては、さらに注意点があります。
Http Headerはブラウザ側でいくらでもでっち上げられるので、ELBを通る前から X-Forwarded…がついていたらどうなるのか。こうなります。
$ curl -H "X-Forwarded-For:a.b.c.d" [httpヘッダーを出すURL]
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Connection: keep-alive
X-Forwarded-For: a.b.c.d, 153.142.14.238
カンマ区切りでELBが通るごとに追加されていきます。よって一番右がELBが出したヘッダーなので、これを信用します。アプリ側でアクセス制限をかける場合は、カンマ区切りになることを想定したアクセス設定などが必要になります。
参考
http://blog.suz-lab.com/2011/06/x-forwarded-forhttpelb.html
http://blog.suz-lab.com/2010/05/apacheremoteaddrelbcentos.html