85 votes

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

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

dans le code source, il y a

"/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 n'en connais pas vraiment les implications.

91voto

Clowerweb Points 1576

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 n'est possible que si tous les mandataires qui se trouvent sur le chemin définissent le paramètre X-Forwarded-For l'en-tête.

73voto

gtd Points 7062

Demande.ip

request.ip est la détection d'IP de base fournie par Rack::Request en dehors de la boîte. Sa définition actuelle est disponible à l'adresse suivante https://github.com/rack/rack/blob/master/lib/rack/request.rb .

L'algorithme qu'il suit consiste à vérifier d'abord le REMOTE_ADDR à la recherche d'adresses IP non fiables, et s'il en trouve, il choisit l'adresse IP la plus fiable. premier une liste. Dans ce cas, les adresses IP "de confiance" sont des adresses IP provenant de la liste des adresses IP de l'Union européenne. plages de sous-réseaux privés réservés mais notez qu'il s'agit d'une correspondance par regex, ce qui n'est probablement pas la meilleure façon de procéder. S'il n'y a pas de REMOTE_ADDR puis il consulte le HTTP_X_FORWARDED_FOR et choisit l'en-tête dernier non fiable répertoriée. Si aucune de ces listes ne révèle la présence de quelqu'un, le système revient à la méthode brute. REMOTE_ADDR qui est probablement 127.0.0.1.

requête.remote_ip

request.remote_ip est une détection améliorée de l'IP fournie par ActionDispatch::Request (qui hérite de Rack::Request ). Il s'agit du code présenté dans la question. Comme vous pouvez le voir, il revient à request.ip sauf si action_dispatch.remote_ip est défini sur le @env . C'est ce que fait le RemoteIp qui est inclus dans la pile Rails par défaut. Vous pouvez consulter ses sources à l'adresse suivante https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rb .

En RemoteIp s'il est activé, offre ces fonctionnalités supplémentaires :

  • Détection facultative mais par défaut de l'usurpation d'adresse IP.
  • Permet de filtrer les adresses proxy de configuration au lieu de s'appuyer uniquement sur les valeurs par défaut.
  • Utilise le IPAddr pour tester correctement les plages d'adresses IP au lieu de s'appuyer sur des expressions rationnelles.
  • Utilisations HTTP_CLIENT_IP comme source de PI potentiels.

L'algorithme est similaire à request.ip mais légèrement différent. Il utilise HTTP_X_FORWARDED_FOR de la dernière à la première place, puis HTTP_CLIENT_IP de la dernière à la première, puis enfin la dernière entrée de REMOTE_ADDR . Il les place tous dans une liste et filtre les proxies, en choisissant le premier qui reste.

Détection de l'usurpation d'adresse IP

La détection de l'usurpation d'adresse IP fournie par RemoteIp n'est pas particulièrement puissant, tout ce qu'il fait est de lever une exception si la dernière valeur de 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 proxies utilisant des conventions différentes qui ne produisent pas un résultat cohérent.

Quels sont les choix à faire ?

Dans une configuration simple où vos serveurs mandataires sont tous locaux ou sur des sous-réseaux privés, vous pouvez probablement vous contenter de request.ip mais request.remote_ip devrait être considéré comme le meilleur choix en général. Si vous utilisez des proxys avec un routage internet public (comme c'est le cas pour de nombreux CDN), alors RemoteIp peut être configuré pour vous donner des adresses IP correctes dès le départ, alors que request.ip ne sera correcte que si vous parvenez à faire en sorte que votre proxy en amont définisse REMOTE_ADDR correctement.

Configuration sécurisée

Je réponds maintenant à la remarque de Tim Coulter sur le spoofing. Il a tout à fait raison de s'inquiéter, mais il a tort de dire que vous pouvez être spoofé si vous êtes derrière nginx ou haproxy par défaut. RemoteIp est conçu pour empêcher l'usurpation d'identité en choisissant l'option dernier IP dans la chaîne. Les X-Forwarded-For spécifie que chaque mandataire ajoute l'adresse IP du demandeur à la fin de la chaîne. En filtrant les mandataires figurant sur la liste blanche, la dernière entrée est garantie être l'IP du client écrite par votre premier mandataire figurant sur la liste blanche. Il y a bien sûr une mise en garde, à savoir que vous devez utiliser un proxy qui définit/ajoute toujours X-Forwarded-For Le conseil de Tim devrait donc être le contraire : n'utiliser que des request.remote_ip lorsque vous sont l'exécution d'un proxy.

Comment configurer des proxy IP publics ?

C'est bien beau, mais ActionDispatch::RemoteIp se trouve déjà dans la pile d'intergiciels par défaut. Comment la reconfigurer pour ajouter les CIDRs de mon 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

45voto

shime Points 3023

D'après 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 

Así que remote_ip donne la priorité à action_dispatch.remote_ip . Elle est fixée par ActionDispatch::RemoteIp logiciel intermédiaire. Vous pouvez voir dans la source de cet intergiciel qu'il vérifie les attaques par usurpation d'identité lorsqu'il est appelé, puisqu'il appelle GetIp.new pour définir cette variable env. C'est nécessaire puisque remote_ip lit l'adresse IP même à travers les proxies locaux, comme l'explique Clowerweb.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X