Servlet でELB経由のアクセス元を判定する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。 今日もJavaとAWSでの小ネタです。

AWSではELBを利用することで簡単に冗長化や負荷分散の構成を作ることができます。

しかし、ELBを前段に置くため、リクエスト元のIPアドレスでアクセスを拒否したりと、アクセス元IPアドレスを判定してなんらかの処理を行いたい場合、リクエスト元IPアドレスがELBのIPアドレスとなってしまいます。 ApacheやNginxの設定などでは、検索してみればリクエストの「X-Forwarded-For」を参照すれば良いと多くの情報がヒットするでしょう。 今回は、Servletで行う場合の方法を紹介します。

ServletRequest#getRemoteAddr - Servletでリクエスト元のIPアドレスを取得する

ELBを経由しない場合など、直接アクセスされる場合は、ServletRequestクラスのgetRemoteAddrメソッドを利用します。

String remoteAddr = request.getRemoteAddr();

HttpServletRequest#getHeader - Servletでリクエストヘッダを取得する

ELBを経由した場合、リクエストの「X-Forwarded-For」ヘッダを参照します。 リクエストヘッダを取得するには、HttpServletRequestクラスのgetHeaderメソッドを利用します。

String xForwardedFor = ((HttpServletRequest) request).getHeader("X-Forwarded-For");

まとめ

ELBに対応するリモートIPアドレスは次のようなメソッドを定義して取得すれば良いでしょう。

private String getRemoteAddr(ServletRequest request) {
    String xForwardedFor = ((HttpServletRequest) request)
                                  .getHeader("X-Forwarded-For");
    if (xForwardedFor != null) return xForwardedFor;
    return request.getRemoteAddr();
}

この辺りの話題は、どちらもそれなりに理解していないと調査に時間がかかるかと思います。 Javaは得意だけどAWS環境は経験が浅くハマった人や、AWS環境は得意だけどJavaは苦手といった人に活用して貰えれば幸いです。