84

タイトルが進むにつれて、両方の方法でクライアントのIPを取得できます。違いはあるのでしょうか。ありがとうございました。

ソースコードには

"/usr/local/rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action _dispatch / http / request.rb" 257L、8741C

def ip
  @ip ||= super
end

# Originating IP address, usually set by the RemoteIp middleware.
def remote_ip
  @remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end

しかし、私は本当にその意味を知りません。

4

3 に答える 3

90

request.ipipそのクライアントがプロキシであっても、クライアントを返します。

request.remote_ipよりスマートで、実際のクライアントを取得しますip。これは、途中のすべてのプロキシがX-Forwarded-Forヘッダーを設定した場合にのみ実行できます。

于 2012-06-12T12:56:10.163 に答える
70

request.ip

request.ipRack::Requestは、箱から出して提供される基本的なIP検出です。現在の定義はhttps://github.com/rack/rack/blob/master/lib/rack/request.rbにあります。

従うアルゴリズムは、最初にREMOTE_ADDRヘッダーに信頼できないIPアドレスがないかチェックし、見つかった場合は、リストされている最初のIPアドレスを選択します。この場合の「信頼できる」IPアドレスは、予約済みのプライベートサブネット範囲のIPアドレスですが、正規表現で一致するため、おそらく最善の方法ではないことに注意してください。信頼できないものがない場合は、ヘッダーをREMOTE_ADDR調べて、リストされている最後の信頼できないものを選択します。それらのどちらも誰かを明らかにしない場合、それはおそらく127.0.0.1であるrawにフォールバックします。HTTP_X_FORWARDED_FORREMOTE_ADDR

request.remote_ip

request.remote_ipActionDispatch::Request(から継承する)によって提供される拡張IP検出Rack::Requestです。これは質問に示されているコードです。ご覧のとおり、に設定されていrequest.ipない限り、にフォールバックします。これは、デフォルトのRailsスタックに含まれているミドルウェアによって行われます。ソースはhttps://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rbで確認できます。action_dispatch.remote_ip@envRemoteIp

RemoteIpミドルウェアを有効にすると、次の追加機能が提供されます。

  • オプションですがデフォルトのIPスプーフィング検出を提供します。
  • デフォルトのみに依存するのではなく、構成プロキシアドレスをフィルタリングできるようにします。
  • IPAddr脆弱な正規表現に依存する代わりに、クラスを使用して実際にIP範囲を適切にテストします。
  • HTTP_CLIENT_IP潜在的なIPのソースとして使用します。

アルゴリズムは似てrequest.ipいますが、わずかに異なります。HTTP_X_FORWARDED_FOR最後から最初、HTTP_CLIENT_IP最後から最初、最後にの最後のエントリを使用しREMOTE_ADDRます。それらすべてをリストに入れ、プロキシをフィルタリングして、最初に残っているプロキシを選択します。

IPスプーフィングの検出

によって提供されるIPスプーフィング検出RemoteIpは特に強力ではありません。最後のHTTP_CLIENT_IPものがにない場合は、例外を発生させるだけHTTP_X_FORWARDED_FORです。これは必ずしも攻撃の兆候ではありませんが、構成の誤り、または一貫した結果を生み出していないさまざまな規則を使用したプロキシの組み合わせの兆候である可能性があります。

どちらを使用するか

プロキシがすべてローカルまたはプライベートサブネット上にある単純なセットアップでは、おそらく回避できますがrequest.iprequest.remote_ip一般的には優れた選択肢と見なす必要があります。パブリックインターネットルーティング(多くのCDNなど)でプロキシを使用している場合RemoteIpは、すぐに正しいクライアントIPを提供するように構成できますrequest.ipが、アップストリームプロキシを正しく設定できる場合にのみREMOTE_ADDR正しくなります。

安全な構成

次に、なりすましに関するTimCoulterのコメントについて説明します。彼はあなたが心配すべきことは間違いなく正しいですが、デフォルトでnginxまたはhaproxyの背後にいる場合、あなたがなりすまされる可能性があるというのは間違っています。 チェーンの最後のIPをRemoteIp選択することにより、なりすましを防ぐように設計されています。X-Forwarded-For仕様は、各プロキシがリクエスターのIPをチェーンの最後に追加することを指定します。ホワイトリストに登録されたプロキシを除外することにより、最後のエントリは、最初のホワイトリストに登録されたプロキシによって書き込まれたクライアントIPであることが保証されます。もちろん、注意点が1つあります。それは、常に設定/追加するプロキシを実際に実行する必要があるということです。したがって、Timのアドバイスは実際には反対である必要があります。つまり、プロキシを実行している場合にのみ使用してください。X-Forwarded-Forrequest.remote_ip

パブリックIPプロキシを構成する方法

これはすべて問題ありませんActionDispatch::RemoteIpが、すでにデフォルトのミドルウェアスタックに含まれています。プロキシCIDRを追加するためにどのように再構成しますか?!

これをあなたに追加してくださいapplication.rb

check_spoofing = true
proxies = ["23.235.32.0/20", "203.57.145.0/24"]
proxies += ActionDispatch::RemoteIp::TRUSTED_PROXIES
config.middleware.swap ActionDispatch::RemoteIp,
                       ActionDispatch::RemoteIp,
                       true,
                       proxies
于 2017-03-25T08:37:46.653 に答える
45

ソースから:

module ActionDispatch
  class Request < Rack::Request

    # ...

    def ip
      @ip ||= super
    end

    def remote_ip
      @remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
    end

    # ...

  end
end

ここで、Rack::Requestは次のようになります

module Rack
  class Request
     def ip
      remote_addrs = split_ip_addresses(@env['REMOTE_ADDR'])
      remote_addrs = reject_trusted_ip_addresses(remote_addrs)

      return remote_addrs.first if remote_addrs.any?

      forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR'])

      if client_ip = @env['HTTP_CLIENT_IP']
        # If forwarded_ips doesn't include the client_ip, it might be an
        # ip spoofing attempt, so we ignore HTTP_CLIENT_IP
        return client_ip if forwarded_ips.include?(client_ip)
      end

      return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"]
    end
  end
end 

したがってremote_ip、を優先しaction_dispatch.remote_ipます。それはActionDispatch::RemoteIpミドルウェアによって設定されています。GetIp.newそのミドルウェアのソースでは、そのenv変数を設定するために呼び出しているため、呼び出されたときにスプーフィング攻撃をチェックしていることがわかります。remote_ipClowerwebが説明しているように、ローカルプロキシを介してもIPアドレスを読み取るため、これが必要になります。

于 2012-06-12T13:06:10.513 に答える