はまったのん…
環境
- 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
で処理している。)
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 に設定する。
Hoge::Application.configure do
...
config.action_dispatch.trusted_proxies = /^127\.|^::1$/
end
ここでは、ループバックアドレスのみをプロキシサーバとして扱うよう設定した。
まとめ
- ドキュメントをサガしたけど直接書かれているものが見つからず、ソースコードを読むことに。オープンソースはありがたいけど、初心者には辛い。
- デフォルトで Client-IP: や X-Forwarded-For: を処理したり、プライベートアドレスをプロキシ扱いにするのは、あまり筋が良くないと思う。
- こまちゃん可愛い