web-dev-qa-db-fra.com

Quelle est la différence entre request.remote_ip et request.ip dans Rails?

Comme le titre l'indique, vous pouvez obtenir l'ip du client avec les deux méthodes. Je me demande s'il y a des différences. Merci.

dans le code source, il va

"/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

mais je ne connais vraiment pas les implications.

64
Minqi Pan

De la source:

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

où Rack :: Request ressemble à ceci

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 

Alors remote_ip donne la priorité à action_dispatch.remote_ip. Cela est défini par ActionDispatch::RemoteIp middleware. Vous pouvez voir dans la source de ce middleware qu'il vérifie les attaques d'usurpation lors de son appel, car il appelle GetIp.new pour définir cette variable env. Cela est nécessaire depuis remote_ip lit l'adresse IP même via les proxys locaux, comme l'explique Clowerweb.

38
shime

request.ip renvoie le client ip même si ce client est un proxy.

request.remote_ip est plus intelligent et obtient le client réel ip. Cela ne peut être fait que si tous les mandataires en cours de route définissent l'en-tête X-Forwarded-For .

75
Clowerweb

request.ip

request.ip Est la détection IP de base fournie par Rack::Request Hors de la boîte. Sa définition actuelle peut être trouvée à https://github.com/rack/rack/blob/master/lib/rack/request.rb .

L'algorithme qu'il suit consiste à vérifier d'abord l'en-tête REMOTE_ADDR Pour toutes les adresses IP non fiables, et s'il en trouve, il choisit d'abord le un répertorié. Les adresses IP "approuvées" dans ce cas sont des adresses IP des plages de sous-réseaux privés réservés , mais notez qu'elles correspondent par expression régulière qui n'est probablement pas la meilleure façon de le faire. S'il n'y a pas de REMOTE_ADDR Non approuvé, il examine l'en-tête HTTP_X_FORWARDED_FOR Et sélectionne le dernier non approuvé de la liste. Si aucun de ceux-ci ne révèle personne, cela revient au brut REMOTE_ADDR Qui est probablement 127.0.0.1.

request.remote_ip

request.remote_ip Est une détection IP améliorée fournie par ActionDispatch::Request (Qui hérite de Rack::Request). C'est le code affiché dans la question. Comme vous pouvez le voir, il revient à request.ip Sauf si action_dispatch.remote_ip Est défini sur le @env. Cela se fait par le middleware RemoteIp, qui est inclus dans la pile par défaut Rails. Vous pouvez voir sa source sur https://github.com/Rails /rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rb .

Le middleware RemoteIp s'il est activé fournit ces fonctionnalités supplémentaires:

  • Fournit une détection d'usurpation d'adresse IP facultative mais par défaut.
  • Permet de filtrer les adresses proxy de configuration au lieu de se fier uniquement aux valeurs par défaut.
  • Utilise la classe IPAddr pour tester correctement les plages IP au lieu de s'appuyer sur une expression rationnelle fragile.
  • Utilise HTTP_CLIENT_IP Comme source d'adresses IP potentielles.

L'algorithme est similaire à request.ip Mais légèrement différent. Il utilise HTTP_X_FORWARDED_FOR Du dernier au premier, puis HTTP_CLIENT_IP Du dernier au premier, puis enfin la dernière entrée de REMOTE_ADDR. Il met tous ces éléments dans une liste et filtre les proxys, en choisissant le premier restant.

Détection d'usurpation d'adresse IP

La détection d'usurpation d'adresse IP fournie par RemoteIp n'est pas particulièrement puissante, elle ne fait que lever une exception si le dernier HTTP_CLIENT_IP N'est pas dans HTTP_X_FORWARDED_FOR. Ce n'est pas nécessairement le symptôme d'une attaque, mais c'est probablement le symptôme d'une mauvaise configuration ou d'un mélange de mandataires utilisant différentes conventions qui ne produisent pas un résultat cohérent.

À utiliser

Dans une configuration simple où vos mandataires sont tous locaux ou sur des sous-réseaux privés, vous pouvez probablement vous en tirer avec request.ip, Mais request.remote_ip Devrait être considéré comme le choix supérieur en général. Si vous utilisez des proxys avec un routage Internet public (tels que de nombreux CDN), RemoteIp peut être configuré pour vous donner des IP client correctes, tandis que request.ip Ne sera correct que si vous le pouvez demandez à votre proxy en amont de définir correctement REMOTE_ADDR.

Configuration sécurisée

Maintenant, pour répondre au commentaire de Tim Coulter sur l'usurpation d'identité. Il a certainement raison, vous devriez vous inquiéter, mais il a tort que vous puissiez être usurpé si vous êtes derrière nginx ou haproxy par défaut. RemoteIp est conçu pour empêcher l'usurpation d'identité en choisissant la dernière IP de la chaîne. La spécification X-Forwarded-For spécifie que chaque proxy ajoute l'IP du demandeur à la fin de la chaîne. En filtrant les proxys sur liste blanche, la dernière entrée est garantie comme l'adresse IP du client écrite par votre premier proxy sur liste blanche. Il y a bien sûr une mise en garde, à savoir que vous devez en fait exécuter un proxy qui définit/ajoute toujours X-Forwarded-For, Donc les conseils de Tim devraient en fait être opposés: utilisez uniquement request.remote_ip Lorsque vous exécutent un proxy.

Comment configurer pour les proxys IP publics

C'est bien beau, mais ActionDispatch::RemoteIp Est déjà dans la pile middleware par défaut. Comment le reconfigurer pour ajouter mes CIDR proxy?!

Ajoutez ceci à votre 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
36
gtd