Подтвердить что ты не робот

Какая разница между request.remote_ip и request.ip в Rails?

Как говорится в заголовке, вы можете получить клиентский ip с обоими методами. Интересно, есть ли какие-то различия. Спасибо.

в исходном коде идет

"/USR/локальные/RVM/драгоценные камни/рубин-1.9.3-Р194/драгоценные камни/actionpack-3.2.3/Library/акция _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

но я действительно не знаю последствий.

4b9b3361

Ответ 1

Из источника:

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_ip читает ip-адрес даже через локальные прокси, как объясняет Clowerweb.

Ответ 2

request.ip возвращает ip, является ли он локальным прокси-адресом ip (адрес localhost) или нет. request.remote_ip умнее и получает IP-адрес клиента за пределами локальных прокси.

Ответ 3

request.ip

request.ip - это базовое ip-обнаружение, предоставляемое Rack::Request из коробки. Его текущее определение можно найти на https://github.com/rack/rack/blob/master/lib/rack/request.rb.

Следующим алгоритмом является проверка заголовка REMOTE_ADDR для любых ненадежных IP-адресов, и если он найдет какой-либо, он выбирает указанный первый. "Надежные" IP-адреса в этом случае являются IP-адресами из зарезервированных диапазонов частных подсети, но обратите внимание, что это соответствует регулярному выражению, которое, вероятно, не является лучшим способ сделать это. Если нет ненадежного REMOTE_ADDR, то он смотрит на заголовок HTTP_X_FORWARDED_FOR и выбирает последний ненадежный. Если ни один из них не показывает никому, он возвращается к необработанному REMOTE_ADDR, который, вероятно, 127.0.0.1.

request.remote_ip

request.remote_ip - улучшенное обнаружение IP, предоставляемое ActionDispatch::Request (которое наследуется от Rack::Request). Это код, указанный в вопросе. Как вы можете видеть, он возвращается к request.ip, если action_dispatch.remote_ip не установлен на @env. Это выполняется с помощью промежуточного программного обеспечения RemoteIp, которое включено в стек Rails по умолчанию. Вы можете увидеть его источник в https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rb.

Вредоносная программа 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.ip, но request.remote_ip следует считать лучшим выбором в целом. Если вы используете прокси с общедоступной интернет-маршрутизацией (например, многие CDN), тогда RemoteIp может быть настроен так, чтобы дать вам правильные клиентские IP-адреса из коробки, тогда как request.ip будет только верным, если вы сможете установить свой прокси-сервер вверх REMOTE_ADDR правильно.

Защищенная конфигурация

Теперь обратимся к комментарию Тима Коултера о спуфинге. Он определенно прав, вы должны быть обеспокоены, но он не прав, что вы можете быть подделаны, если по умолчанию вы находитесь за nginx или haproxy. RemoteIp предназначен для предотвращения спуфинга, выбирая IP-адрес last в цепочке. Спецификация X-Forwarded-For указывает, что каждый прокси присоединяет IP-адрес реквестера к концу цепочки. Отфильтровывая прокси-серверы с белыми списками, последней записью гарантируется IP-адрес клиента, написанный вашим первым whitelisted-прокси. Конечно, есть одно предостережение, которое заключается в том, что вы действительно должны запускать прокси-сервер, который всегда устанавливает/добавляет X-Forwarded-For, поэтому совет Тима должен быть фактически противоположным: используйте request.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