Posted at

LAN内でリバースプロキシを使用した場合の request.remote_ip

More than 5 years have passed since last update.

はまったのん…


環境


  • Rails 4.0.1

  • nginx + Unicorn


リバースプロキシを利用した場合のアクセス元アドレス

通常、リバースプロキシ (nginxなどのウェブサーバを含む; 以下単にプロキシ) を利用した場合、アクセス元はプロキシ側のIPアドレスとなるため実際のアドレスを知ることが出来ない。このため、プロキシ側ではリクエストヘッダ (Client-IP: など) にアクセス元のアドレスを含めることが多い。Webサーバはこの値を読んで本来のアドレスを知ることが出来る。

Railsでは request.env 中の情報を利用して、実際のリモートホストを取得することが出来る。ただし、request.remote_ip でヘッダの情報を処理した "正しい" リモートホストを参照することができるため、直接ヘッダの情報を参照するメリットはあまり無い。(この機能は ActionPack 中の ActionDispatch で提供されており、Client-IP: または X-Forwarded-For: に含まれるアドレスがリモートアドレスとして取り扱われる。)


問題点

LAN (プライベートIPアドレスを使用したネットワーク) 内にあるサーバにアクセスした場合には request.remote_ip がプロキシ側のアドレスとなってしまう。

※プロキシ側では Client-IP: または X-Forwarded-For: が設定されるものとする。


原因

ActionDispatch::RemoteIp::TRUSTED_PROXIES にマッチするアドレス (ループバックアドレスとプライベートアドレス) は、プロキシサーバと見なされ、Client-IP: や X-Forwarded-For: に含まれていても無視されるため。(ActionDispatch::RemoteIp::GetIp.filter_proxies で処理している。)


actionpack-4.0.1/lib/action_dispatch/middleware/remote_ip.rb

TRUSTED_PROXIES = %r{

^127
\.0\.0\.1$ | # localhost IPv4
^::1$ | # localhost IPv6
^fc00: | # private IPv6 range fc00
^10
\. | # private IPv4 range 10.x.x.x
^172
\.(1[6-9]|2[0-9]|3[0-1])\.| # private IPv4 range 172.16.0.0 .. 31.255.255
^192
\.168\. # private IPv4 range 192.168.x.x
}x



対策

プロキシのみにマッチする正規表現を Rails.configuration.action_dispatch.trusted_proxies に設定する。


config/environments/production.rb

Hoge::Application.configure do

...
config.action_dispatch.trusted_proxies = /^127\.|^::1$/
end

ここでは、ループバックアドレスのみをプロキシサーバとして扱うよう設定した。


まとめ


  • ドキュメントをサガしたけど直接書かれているものが見つからず、ソースコードを読むことに。オープンソースはありがたいけど、初心者には辛い。

  • デフォルトで Client-IP: や X-Forwarded-For: を処理したり、プライベートアドレスをプロキシ扱いにするのは、あまり筋が良くないと思う。

  • こまちゃん可愛い