AWSの公式ドキュメント見たらええよ、というだけの話ではあるんですが。
背景
こんな構成の場合。
※ちょっと図が微妙ですが、アプリケーションログはEC2インスタンス内に存在するファイルです。
EC2インスタンス内のアプリケーションで出力するログで「リクエスト元の情報がほしいな」と思い、
リクエストヘッダに入っているホストをそのまま出力すると、当然ながらALBのIPが出力されます。
一応、ALBでもアクセスログを出しておけばリクエストの送信元のIPはわかるし
それとアプリケーション側で出したログを突き合わせれば、そのままでも欲しい情報を調べることはできなくもないです。
しかし実際にログを調べたくなるような場面において、都度そんな作業をするのは手間なので
ALBにリクエストを送信してきたホスト情報をそのままEC2インスタンス内でも使用したい。
ALBではX-Forwarded-Forがそのまま取れる
公式ドキュメントによると、X-Forwarded-ForをALBが渡してくれるのでそれを使ってくれよな!とのこと。
デフォルトではオリジナルのリクエストに含まれているX-Forwarded-Forに、リクエスト元のIPを追加する仕様になっています。
ちょびっと設定を変更すれば、オリジナルのリクエストのものをそのまま送らせたり、逆に削除させるといったことも可能です。
具体例
今回はTomacatのログでこれを出力したく、下記のような設定を記述しました。
Tomcat8での設定はこんな感じです。
<Server>
〜中略〜
<Service name="Catalina">
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="false">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="access.log"
fileDateFormat=".yyyyMMdd"
renameOnRotate="true"
pattern='{ "host":"%{X-Forwarded-For}i","user":"%u","time":"%{yyyy-MM-dd'T'HH:mm:ss.SSSZ}t","method":"%m","path":"%U%q","protocol":"%H","status":%s,"size":"%b","referer":"%{Referer}i","location":"%{Location}o","agent":"%{User-Agent}i","cookie":"%{cookie}i","set_cookie":"%{Set-Cookie}o","authorization":"%{Authorization}i","response_time":%D }' />
…
JSON形式にしたくてpattern指定しているのですが、そこで"host":"%{X-Forwarded-For}i"
と書いているのが該当箇所です。
この結果出力されるのが下記の様な感じ。
{ "host":"60.127.230.44","user":"-","time":"2023-02-20T10:17:12.738+0900","method":"GET", ...
無事出力されていてニッコリ ほっこり
ということで、特別なことはなくすんなり欲しい情報が取れました。
ちなみにALBからターゲットグループへのヘルスチェックなど、ALB自身からのアクセスの場合X-Forwarded-Forの値はないので-
と出力されていました。
{ "host":"-","user":"-","time":"2023-02-20T12:08:45.396+0900","method":"GET","path":"/","protocol":"HTTP/1.1","status":200,"size":"-","referer":"-","location":"-","agent":"ELB-HealthChecker/2.0","cookie":"-","set_cookie":"-","authorization":"-","response_time":0 }
他のフィールドでヘルスチェックだとがわかるし、特に必要な情報でもないのでこれは問題なさそう。