Rails の request.remote_ip には何の値が入っているのか
表題の通り Rails 3.2.X 系の request.remote_ip に入っている値について調べました。
最初に結論
リクエストヘッダを読み HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR の順にセットされていた値を取得してきます。
ソースコード
http://api.rubyonrails.org/classes/ActionDispatch/RemoteIp/GetIp.html
上記 API にも記載されていますが calculate_ip が該当のメソッドです。
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 47 def calculate_ip client_ip = @env['HTTP_CLIENT_IP'] forwarded_ips = ips_from('HTTP_X_FORWARDED_FOR') remote_addrs = ips_from('REMOTE_ADDR') check_ip = client_ip && @middleware.check_ip if check_ip && !forwarded_ips.include?(client_ip) # We don't know which came from the proxy, and which from the user raise IpSpoofAttackError, "IP spoofing attack?!" "HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}" "HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}" end not_proxy = client_ip || forwarded_ips.last || remote_addrs.first # Return first REMOTE_ADDR if there are no other options not_proxy || ips_from('REMOTE_ADDR', :allow_proxies).first end
そんなわけで、いくら HTTP_X_FORWARDED_FOR の値をセットしてあげても HTTP_CLIENT_IP の値が書き変わっていたら正しいアドレスは取得できず、ログにはすべてのリクエストが 127.0.0.1 からとして記録されたりします。
ウェブサーバ側の設定
ここでは Nginx の場合の追加ヘッダー設定を記載します(Apache の場合については調査していませんが、大体同じような方法で設定可能だと思います)。コンフィグファイルを開いて、次のような設定を行います。
server { # 略 proxy_set_header Client-IP $remote_addr; }
もちろん HTTP_X_FORWARDED_FOR 等の設定もきちんと行わないといけませんが Rails の場合はこれが最優先のようなので、うまくアドレスがログに表示されていない場合はこのあたりの設定を見直すといいと思います。
ActionDispatch::RemoteIp::IpSpoofAttackError への対処
上の設定で HTTP_CLIENT_IP と HTTP_X_FORWARDED_FOR にプライベート IP の値や、異なる値を設定した場合などに ActionDispatch::RemoteIp::IpSpoofAttackError が起きる事があります。
どうしてもそうした設定を行いたい場合は Rails 側のコンフィグでチェックを行わないように設定する事ができます。
config/application.rb または任意の環境向けのコンフィグファイルで次の設定を行ってください。
Hoge::Application.configure do config.action_dispatch.ip_spoofing_check = false end