Was ist der Unterschied zwischen request.remote_ip und request.ip in Rails?

75

Wie der Titel schon sagt, können Sie die IP des Clients mit beiden Methoden abrufen. Ich frage mich, ob es Unterschiede gibt. Vielen Dank.

im Quellcode geht es

/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

aber ich kenne die Implikationen wirklich nicht.

Minqi Pan
quelle

Antworten:

43

Aus der Quelle:

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

wo Rack :: Request so aussieht

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 

So remote_ipgibt den Vorrang action_dispatch.remote_ip. Das wird von der ActionDispatch::RemoteIpMiddleware eingestellt. Sie können in der Quelle dieser Middleware sehen, dass sie beim Aufrufen GetIp.newnach Spoofing-Angriffen sucht, da sie zum Festlegen dieser env-Variablen aufruft . remote_ipDies ist erforderlich, da die IP-Adresse auch über die lokalen Proxys gelesen wird, wie Clowerweb erklärt.

shime
quelle
11
Meiner Erfahrung request.remote_ipnach kann die HTTP_X_FORWARDED_FOR-Kette zwar gefälscht werden, sie kann jedoch gefälscht werden, wenn Sie Rails hinter nginx oder haproxy haben. Verwenden Sie in Nginx proxy_set_header X-Forwarded-For $remote_addr;anstelle von proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;. Im letzteren Fall curl -H "X-Forwarded-For: 6.66.6.66" http://example.comwird ein request.remote_ipWert von 6.66.6.66 erzeugt, der alle IP-Überprüfungen in Rails fälscht.
Tim Coulter
83

request.ipGibt den Client zurück, ipauch wenn dieser Client ein Proxy ist.

request.remote_ipist schlauer und bekommt den eigentlichen Kunden ip. Dies ist nur möglich, wenn alle Proxys auf dem Weg den X-Forwarded-For- Header festgelegt haben.

Clowerweb
quelle
55

request.ip

request.ipist die grundlegende IP-Erkennung, die standardmäßig bereitgestellt wird Rack::Request. Die aktuelle Definition finden Sie unter https://github.com/rack/rack/blob/master/lib/rack/request.rb .

Der Algorithmus, dem es folgt, besteht darin, zuerst den REMOTE_ADDRHeader auf nicht vertrauenswürdige IP-Adressen zu überprüfen und, falls er welche findet, die erste aufgelistete auszuwählen. "Vertrauenswürdige" IP-Adressen sind in diesem Fall IP-Adressen aus den reservierten privaten Subnetzbereichen. Beachten Sie jedoch, dass sie mit Regex übereinstimmen, was wahrscheinlich nicht der beste Weg ist, dies zu tun. Wenn kein nicht vertrauenswürdiger Benutzer vorhanden ist, wird REMOTE_ADDRder HTTP_X_FORWARDED_FORHeader angezeigt und der zuletzt aufgelistete nicht vertrauenswürdige ausgewählt. Wenn keiner von beiden jemanden enthüllt, fällt er auf den Rohwert zurück, der REMOTE_ADDRwahrscheinlich 127.0.0.1 ist.

request.remote_ip

request.remote_ipist eine verbesserte IP-Erkennung, die von ActionDispatch::Request(die von erbt Rack::Request) bereitgestellt wird . Dies ist der in der Frage gezeigte Code. Wie Sie sehen können, fällt es auf zurück, request.ipes action_dispatch.remote_ipsei denn , es ist auf dem eingestellt @env. Dies geschieht durch die RemoteIpMiddleware, die im Standard-Rails-Stack enthalten ist. Sie finden die Quelle unter https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rb .

Die RemoteIpaktivierte Middleware bietet folgende zusätzliche Funktionen:

  • Bietet optionale, aber standardmäßige IP-Spoofing-Erkennung.
  • Ermöglicht das Filtern von Konfigurations-Proxy-Adressen, anstatt sich nur auf Standardeinstellungen zu verlassen.
  • Verwendet die IPAddrKlasse, um IP-Bereiche tatsächlich richtig zu testen, anstatt sich auf einen spröden regulären Ausdruck zu verlassen.
  • Wird HTTP_CLIENT_IPals Quelle für potenzielle IPs verwendet.

Der Algorithmus ist ähnlich, request.ipaber etwas anders. Es verwendet HTTP_X_FORWARDED_FORvon zuletzt nach zuerst, dann HTTP_CLIENT_IPvon zuletzt nach zuerst, dann schließlich den letzten Eintrag von REMOTE_ADDR. Es fügt alle in eine Liste ein und filtert Proxys, wobei der erste verbleibende ausgewählt wird.

IP-Spoofing-Erkennung

Die von bereitgestellte IP-Spoofing-Erkennung RemoteIpist nicht besonders leistungsfähig. Sie löst lediglich eine Ausnahme aus, wenn die letzte HTTP_CLIENT_IPnicht aktiviert ist HTTP_X_FORWARDED_FOR. Dies ist nicht unbedingt ein Symptom eines Angriffs, aber es ist wahrscheinlich ein Symptom einer Fehlkonfiguration oder einer Mischung von Proxys, die unterschiedliche Konventionen verwenden und kein kohärentes Ergebnis liefern.

Welche zu verwenden

In einer einfachen Konfiguration, in der Ihre Proxys alle lokal oder in privaten Subnetzen sind, können Sie wahrscheinlich davonkommen request.ip, request.remote_ipsollten aber im Allgemeinen als die überlegene Wahl angesehen werden. Wenn Sie Proxys mit öffentlichem Internet-Routing verwenden (z. B. viele CDNs), RemoteIpkönnen Sie diese so konfigurieren, dass Sie sofort die richtigen Client-IPs erhalten. Dies ist jedoch request.ipnur dann der Fall, wenn Sie Ihren Upstream-Proxy REMOTE_ADDRkorrekt einstellen können.

Sichere Konfiguration

Nun zu Tim Coulters Kommentar zum Spoofing. Er hat definitiv Recht, dass Sie sich Sorgen machen sollten, aber er hat Unrecht, dass Sie gefälscht werden können, wenn Sie standardmäßig hinter Nginx oder Haproxy stehen. RemoteIpwurde entwickelt, um Spoofing durch Auswahl der letzten IP in der Kette zu verhindern. Die X-Forwarded-For- Spezifikation gibt an, dass jeder Proxy die IP des Anforderers an das Ende der Kette anfügt. Durch Herausfiltern von Whitelist-Proxys wird garantiert, dass der letzte Eintrag die Client-IP ist, die von Ihrem ersten Whitelist-Proxy geschrieben wurde. Es gibt eine Einschränkung natürlich die , dass Sie tatsächlich einen Proxy laufen muss , ist , dass immer Sätze / Appends X-Forwarded-For, so Tim Rat eigentlich umgekehrt sein sollte: nur verwenden , request.remote_ipwenn Sie sind ein Proxy ausgeführt wird .

So konfigurieren Sie öffentliche IP-Proxys

Das ist alles in Ordnung und gut, befindet sich aber ActionDispatch::RemoteIpbereits im Standard-Middleware-Stack. Wie konfiguriere ich es neu, um meine Proxy-CIDRs hinzuzufügen?!

Fügen Sie dies zu Ihrem hinzu 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
gtd
quelle