【Play Framework】 ELB 経由のアクセス元IPアドレスを取得する
Play Framework に対するアクセスから ELB や nginx(リバースプロキシ)を経由した アクセス元IPアドレス を取得するには、少し工夫が必要です。
本記事におけるバージョン情報は下記の通りです。
- Play Framework 2.4
- Scala 2.11.4
- nginx 1.6.2
下準備: IP確認するアプリケーションを用意する
アクセス元IPアドレスをどのように取得すればいいかを知るために、まず、アクセス元IPを確認するアプリケーションを作成しましょう。
ipcheck.scala.html
@(remoteAddr: String, xForwardedFor: String, xRealIp: String) @main("IP Check") { <dl> <dt>Your remoteAddress</dt> <dd>@remoteAddr</dd> <dt>Your X-Forwarded-For</dt> <dd>@xForwardedFor</dd> <dt>Your X-Real-IP</dt> <dd>@xRealIp</dd> </dl> }
remoteAddress として取得できるIPアドレス、 X-Forwarderd-For として取得できるIPアドレス、 X-Real-IP として取得できるIPアドレスをそれぞれ表示させます。
Application.scala
class Application extends Controller { def check = Action { req => val remoteAddr = req.remoteAddress val xForwardedFor = req.headers.get("x-forwarded-for").getOrElse("Empty!") val xRealIp = req.headers.get("x-real-ip").getOrElse("Empty!") Ok(views.html.ipcheck(remoteAddr, xForwardedFor, xRealIp)) } }
remoteAddress, X-Forwarded-For, X-Real-IP をそれぞれ取得して、レンダリングさせます。 X-Forwarderd-For や X-Real-IP は、 リバースプロキシを介してアクセスされる際に、プロキシサーバによって追加されるヘッダのため、値が設定されていない可能性がある ことに留意してください。 今回は、値が設定されていなかった場合に Empty! と表示することにします。
自分で管理しているリバースプロキシを介する場合は、プロキシサーバの設定ファイルにこれらのヘッダを追加するよう記述する必要があります。
routes.conf
# IP check GET /check controllers.Application.check
上記で作成したIPアドレス確認ページへアクセスできるようルーティングします。
これで下準備は完了です。実際に EC2 インスタンスにデプロイし、アクセスしてみましょう!
実際に試してみる
確認のために IP確認用のアプリケーションをデプロイしたEC2インスタンス と ELB を用意しました。
また、上記の EC2 インスタンス内には nginx をインストール済であり、ローカル内でリバースプロキシをかませてアプリケーションにアクセスさせるパターンも試してみます。 nginx の設定は、 Play Framework 公式の記述 に従っています。
実際にいろいろなルートからアクセスしてみると、結果は次のようになります。
IPアドレス一覧表
- | IPアドレス |
---|---|
アクセス元IP | XXX.AAA.BBB.CCC |
ELBのPrivate IP | 10.128.0.46 |
EC2インスタンスのPrivate ID | 10.128.0.168 |
表示結果
- | remoteAddress | X-Forwarderd-For | X-Real-IP |
---|---|---|---|
EC2インスタンスに直接アクセス | XXX.AAA.BBB.CCC | Empty! | Empty! |
nginxを経由してEC2インスタンスにアクセス | XXX.AAA.BBB.CCC | XXX.AAA.BBB.CCC | XXX.AAA.BBB.CCC |
ELBを経由してEC2インスタンスにアクセス | XXX.AAA.BBB.CCC | XXX.AAA.BBB.CCC | Empty! |
ELBとnginxを経由してEC2インスタンスにアクセス | 10.128.0.46 | XXX.AAA.BBB.CCC, 10.128.0.46 | 10.128.0.46 |
上記から、次の二点がわかります。
- X-Forwarded-For には、カンマ区切りのIPアドレスが渡される。そのうちの先頭の要素は、アクセス元IPアドレス。
- ELB は X-Forwarded-For を追加してくれるが、 X-Real-IP は追加してくれない。
まとめ
以上のことなどから、ELB や Nginx を介したアクセスのIPアドレスを取得するためには、次のように取得するのが安全と考えられます。
- X-Forwarded-For が設定されている場合は、カンマ区切りで先頭の要素をIPとして使用する。
- X-Forwarded-For が設定されていない場合は、remoteAddress をそのまま使用する。
このように取得しておけば、いつかアプリケーションサーバー周りのインフラ構成が変更されることになっても、問題なくアクセス元IPアドレスを取得することができるはずです! Have a nice day!