ALB配下のLaravelでクライアントのIPをログに記録する

多くのPHP製のフレームワークではMonologが標準のLoggerとして採用されています。Laravelでも例にもれず、LoggerとしてMonologが採用されています。

Monologについてはこちらの記事が参考になります。

https://qiita.com/iakio/items/7b8539db928d2b419921

上の記事にもありますが、MonologではProcessorを用いることでログのextraフィールドに情報を付与することができます。Monologのリポジトリには、標準でこれだけのProcessorがあります。

https://github.com/Seldaek/monolog/tree/main/src/Monolog/Processor

この中にある、WebProcessorを使うと、サーバーのアドレス、アクセスされたパス、メソッド、リファラー、クライアントのIPなどの情報を付与することができます。

こんな感じです。

$handler = new StreamHandler('php://stderr');
$webProcessor = new WebProcessor();
$logger = new Logger( 'app', [$handler], [$webProcessor]);

$logger->info('hoge');
[2021-03-24T11:58:43.973074+00:00] app.INFO: hoge [] {"url":"/","ip":"172.25.0.1","http_method":"GET","server":"0.0.0.0","referrer":null}

さて、こちらはローカル環境では正しく動きますが、AWSなどにデプロイし、ALBの配下で動かすと、クライアントのIPアドレスがALBのIPアドレスになってしまいます。

AWSのドキュメントを見ると、元々のクライアントIPはX-Forwarded-Forというヘッダーに格納されているようです。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-capture-client-ip-addresses/

また、PHPでは全てのヘッダーは$_SERVERというグローバル変数へ格納されます。

https://www.php.net/manual/ja/reserved.variables.server.php#89567

このとき、添字は以下のように変換します。

  • HTTP_ のプレフィックスを付ける
  • ハイフンはアンダースコアに変換
  • すべて大文字に変換

つまり、X-Forwarded-Forを取得するには、このようにします。

$myHeader = $_SERVER['HTTP_X_FORWARDED_FOR'];

クライアントのIPは取得できました。ではどうやってWebProcessorにIPの場所を教えれば良いのでしょうか。

答えはこうです。

$webProcessor = new WebProcessor();
$webProcessor->addExtraField('ip', 'HTTP_X_FORWARDED_FOR');
実装を見ればわかるのですが、WebProcessorは$_SERVERから各種情報を抜き出してextraフィールドにセットしています。

上のようにaddExtraField()メソッドを呼び出すことで、「ipの値は$_SERVERのHTTP_X_FORWARDED_FORキーから取得してね」というように伝えることができるのです。

これでALB配下でLaravelを動かした時も、クライアントのIPをログに出力することができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です