ウェブサーバー(HTTP サーバー)を使う場合、なんらかのアクセスログを残すことになります。例えば Apache HTTPD の場合、デフォルトでアクセスログは /var/log/httpd/access_log に残ります。そのフォーマットは /etc/httpd/conf/httpd.conf 内で設定/カスタマイズできます。
2015012200


デフォルトの httpd.conf では、以下の様なログフォーマットが指定されています:
LogFormat "%h %l %u %t \"%r\" %>s %b common

暗号のような記述ですが、左から順にこのような意味があります:
 %h : 接続元のリモートホスト名(IPアドレス)
 %l : クライアント識別子(取得できない場合は - )
 %u : 認証時のユーザー名(取得できない場合は - )
 %t : 時刻
 %r : リクエストの最初の行の値
 %s : レスポンスステータス
 %b : 送信バイト数(0バイトの場合は - )

このログフォーマットであれば、以下の様なログが取得できることになります:
192.168.1.101 - - [20/Jan/2015:11:32:29 +0900] "GET / HTTP/1.1" 200 -


最初の値がアクセス元のホストになります。つまりこれで(プロクシが使われている場合はプロクシのアドレスになりますが)どこからのアクセスがあったのか、という情報が分かります。


ところが、このアクセス元ホストが分からなくなる場合があります。それは HTTP サーバーがロードバランサ経由で使われていた場合です。サーバーの負荷軽減などの目的で、サーバーを複数台構成にしてロードバランサ経由で利用する、というケースは珍しくないと思います(クラウド環境によっては1台構成でもロードバランサ経由になることもあります)。ただその場合、この設定だとアクセス元ホストは必ずロードバランサの IP アドレスになってしまい、結果として常に同じホストからのアクセスがあったとログに記録されることになります。

これを避けるには httpd.conf をカスタマイズする必要があります。具体的にはこんな感じに:
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b common


%h の代わりに %{X-Forwarded-For}i という記述に変えました。この意味ですが、まず %{XXX}i という記述は「リクエストヘッダに含まれるヘッダー名 XXX の値」です。つまりこの記述は「リクエストヘッダに含まれる X-Forwarded-For ヘッダの値」をログに書き出すよう指示していることになります。

そしてリクエストヘッダの X-Forwarded-For ですが、これはプロクシやロードバランサなどのキャッシングサーバーに接続するクライアントの送信元 IP アドレスです。つまりキャッシングサーバーから見た時の %h の値がこのヘッダ値に入ってくるので、その値を取り出してログに記録すればよい、ということになるわけです。 そこで上記のような設定をすることでロードバランサ経由であっても、元のクライアントの IP アドレスを記録できるようになるのでした。

なお、この方法は HTTP プロトコルに限って有効です。HTTPS では暗号化によって HTTP ヘッダに送信元 IP アドレスが記録できるかどうか、ロードバランサによって変わってきてしまいます。お使いのロードバランサが HTTPS をサポートしているか、サポートしていない場合の対応方法などはお使いのクラウド業者に問い合わせる必要があると思っています。