TomcatのServletでクライアントIPを取得すると 127.0.0.1 になる現象

TomcatのServletでクライアントIPを取得するために HttpServletRequest の getRemoteAddr() メソッドを使っているのですが、取得するIPがいつも 127.0.0.1 となってしまうので調べてみました。環境は以下の構成です。NginxとTomcatは相乗りです。

ServletでのクライアントIP取得のソースコードです。


//IPアドレスの取得
String ip = request.getHeader("X-FORWARDED-FOR");
if ( ip == null || "".equals(ip) )
	ip = request.getRemoteAddr();
if ( ip == null )
	ip = "0.0.0.0";

このロジックだと request.getRemoteAddr(); がいつも 127.0.0.1 になってしまいます。ループバックアドレスなので自身のIPアドレスとなっているようです。つまり、TomcatからみたクライアントはNginxとなっています。

これを解消するにはNginx側の設定ファイルに proxy_set_header ディレクティブの追加が必要だとわかりました。以下のようにします。


location / {
	 :
	proxy_set_header X-Forwarded-for $remote_addr;
	proxy_pass http://localhost:8080/test/;
	 :
}

Nginxはデフォルトでは X-Forwarded-For ヘッダを付けてくれないので、付加する設定がいるようです。Servlet側でも request.getHeader("X-FORWARDED-FOR"); の処理を入れておく必要があります。こうするとクライアントIPの取得ができました。

X-Forwarded-For ヘッダはプロキシサーバーを通過した際に、送信元IPアドレスを特定するために使われます。HTTPヘッダには以下のような形で付与されます。

X-Forwarded-For: <client>, <proxy1>, <proxy2>

リクエストが複数のプロキシサーバーを通過する場合、それぞれの通過するプロキシサーバーのIPアドレスが右側に付け足されていきます。つまり、左端のIPアドレスが元のクライアントのIPアドレスになります。

なお、1つ手前のプロキシサーバー(一番最後に経由したプロキシサーバー)のIPアドレスは X-Forwarded-For ヘッダには記載されないので そのIPアドレスを取得するには request.getRemoteAddr() メソッドで取得します。

2025/01/06 補足
今回のケースではNginxは多段プロキシとなっておらず X-Forwarded-For を付与する一番最初のサーバーとなっています。ですので、$proxy_add_x_forwarded_for は使用しませんでした。仮にNginxとTomcatを相乗りさせず別サーバーとした場合は以下のようになります。

・送信元のクライアントIPアドレスは、X-Forwarded-For から取得。
・NginxのIPアドレスは、request.getRemoteAddr() メソッドで取得。

LightsailにDNSゾーンを作成してドメインのDNSレコード管理を委任する。

ドメインにサブドメインを作成して、サブドメインの管理をLightsailの権威DNSサーバーに委任をします。

さくらインターネットの権威DNSサーバーで example.com を管理しています。サブドメイン sub.example.com を作成して、サブドメインの管理はLightsailの権威DNSサーバーのほうで行うようにします。Lightsailで稼働しているwebサーバーに sub.example.com のドメインを割り当てます。

まずはLightsail側でサブドメインのDNSレコードのゾーン作成をします。

Lightsailの管理画面から「ドメインとDNS」を選び「DNSゾーンの作成」を押下します。

ドメイン設定の画面になるので「別のレジストラからドメインを使用」にチェックを入れてドメイン名を入力します。ここに記載するのはサブドメインです。

ドメイン設定の画面の下部に「DNSゾーンの作成」のボタンがあるので押下します。LightsailではDNSゾーンの管理に料金はかかりません。

ゾーンを管理するネームサーバーが割り当てられるので、表示されたネームサーバーをメモしておきます。

ドメインタブからDNSレコードタブの方に切り替えます。「レコードの追加」をクリックします。

DNSレコードの登録画面になるので、レコードタイプは「Aレコード」、レコード名には「@」、解決先にはLightsailで稼働しているwebサーバーのIPアドレスを入力します。下部にある「保存」をクリックします。

同様にレコードタイプが「AAAAレコード」の登録も行えます。こちらは任意です。なお、AレコードはIPv4での名前解決、AAAAレコードはIPv6での名前解決となります。

DNSレコードを保存すると以下のように表示されます。Aレコード、および、AAAAレコードを登録しています。

割り当てタブのほうです。解決先にLightsailのインスタンス名が表示されています。

以上でLightsail側でのゾーン作成は終わりです。次にさくらインターネット側でネームサーバーの登録作業を行います。

さくらインターネットの管理画面にある「契約中のドメイン一覧」から「ドメインコントロールパネル」をクリックします。

利用しているドメインの一覧が表示されるので該当するドメイン(サブドメインを作るドメイン)の行の「ゾーン」をクリックします。

ゾーン情報のレコード設定を行います。編集ボタンを押下します。

レコード追加の画面になるので、エントリ名は「sub」、タイプは「NS」、データには「Lightsailのネームサーバー」を入力します。Lightsailのネームサーバーは先ほどメモしたものです。4つを入力します。このときネームザーバー名の最後には「.」をつけます。右側の追加ボタンを押すと行が追加されます。DNSチェックはデフォルトではついていますが、外しておきます。入力ができたら保存ボタンを押下します。

nsレコードを登録した後の状態です。Lightsail側のネームサーバーが追加されています。

ウェブブラウザから「http://sub.example.com」を入力してLightsailで稼働しているWEBサーバーにアクセスします。ウェブページが表示されれば完了です。