跳到內容 跳到搜尋

Action Dispatch RemoteIp

這個中間件計算提出請求的遠端用戶端 IP 位址。它會檢查可能包含位址的各種標頭,然後選取不在受信任 IP 清單中的最後設定位址。這遵循先例設定,例如 Tomcat 伺服器。演算法的更詳細說明在 GetIp#calculate_ip 中提供。

有些 Rack 伺服器會串接重複的標頭,就像 HTTP RFC 2616 所要求的。有些 Rack 伺服器只會捨棄前面的標頭,只回報在 最後標頭中給定的值。如果您在多個代理伺服器之後(例如 NGINX 到 HAProxy 到 Unicorn),您應該測試您的 Rack 伺服器以確保您的資料是好的。

如果您不使用代理,這會讓您容易受到 IP 欺騙。這個中間件假設至少有一個代理伺服器在執行,並設定標頭包含用戶端的遠端 IP 位址。如果您不使用代理,因為您是在沒有 SSL 的 Heroku 上架,任何用戶端都可以透過設定 X-Forwarded-For 標頭來宣稱擁有任何 IP 位址。如果您在意這一點,那麼您需要在這個中間件執行之前,明確捨棄或忽略那些標頭。或者,移除這個中間件以避免無意間依賴它。

命名空間
方法
C
N

常數

TRUSTED_PROXIES = [ "127.0.0.0/8", # RFC-3330 中的本機端 IPv4 範圍 "::1", # 本機端 IPv6 "fc00::/7", # 私有 IPv6 範圍 fc00::/7 "10.0.0.0/8", # 私有 IPv4 範圍 10.x.x.x "172.16.0.0/12", # 私有 IPv4 範圍 172.16.0.0 .. 172.31.255.255 "192.168.0.0/16", # 私有 IPv4 範圍 192.168.x.x ].map { |proxy| IPAddr.new(proxy) }
 

預設信任的 IP 清單僅包含保證為私人地址的 IP 位址。在實際運作中,這些不會是最終的客戶端 IP,因此會被捨棄。有關詳細資訊,請參閱 zh.wikipedia.org/wiki/%E7%A7%81%E5%AF%86%E7%BD%91%E7%BB%9C

屬性

[R] check_ip
[R] proxies

類別公共方法

new(app, ip_spoofing_check = true, custom_proxies = nil)

建立新的 RemoteIp 中介軟體執行個體。

ip_spoofing_check 選項預設為開啟。開啟時,如果看起來客戶端試圖謊報其自己的 IP 位址,則會引發例外狀況。對於針對非 IP 客戶端(例如 WAP 裝置)的網站,或在以不正確或令人混淆的方式設定標頭的代理程式(例如 AWS ELB)之後,關閉此檢查是有意義的。

custom_proxies 參數可以接受一個可列舉的項目,它將用於取代 TRUSTED_PROXIES。任何代理程式設定都會將您想要的數值置於 X-Forwarded-For 清單的中間(或開頭),其後會是您的代理伺服器。如果您的代理程式未移除,請透過 custom_proxies 參數傳遞它們。這樣,中介軟體會忽略那些 IP 位址,並傳回您想要的 IP 位址。

# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 61
    def initialize(app, ip_spoofing_check = true, custom_proxies = nil)
      @app = app
      @check_ip = ip_spoofing_check
      @proxies = if custom_proxies.blank?
        TRUSTED_PROXIES
      elsif custom_proxies.respond_to?(:any?)
        custom_proxies
      else
        raise(ArgumentError, <<~EOM)
          Setting config.action_dispatch.trusted_proxies to a single value isn't
          supported. Please set this to an enumerable instead. For
          example, instead of:

          config.action_dispatch.trusted_proxies = IPAddr.new("10.0.0.0/8")

          Wrap the value in an Array:

          config.action_dispatch.trusted_proxies = [IPAddr.new("10.0.0.0/8")]

          Note that passing an enumerable will *replace* the default set of trusted proxies.
        EOM
      end
    end

執行個體公共方法

call(env)

由於可能不需要 IP 位址,我們在此儲存物件,而不會計算 IP,以避免減慢大多數要求的速度。對於確實需要知道 IP 的要求,GetIp#calculate_ip 方法將計算已暫存的客戶端 IP 位址。

# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 89
def call(env)
  req = ActionDispatch::Request.new env
  req.remote_ip = GetIp.new(req, check_ip, proxies)
  @app.call(req.env)
end