класс ActionDispatch::RemoteIp
Этот промежуточный слой вычисляет IP-адрес удалённого клиента, который производит запрос. Это делается путём проверки различных заголовков, которые могут содержать адрес, а затем выбора последнего установленного адреса, который не находится в списке доверенных IP-адресов. Это соответствует прецеденту, установленному, например, сервером Tomcat, с объяснением причины подробно @gingerlime. Более подробное объяснение алгоритма приведено по адресу GetIp#calculate_ip.
Некоторые серверы Rack объединяют повторяющиеся заголовки, как требует HTTP RFC 2616. Некоторые серверы Rack просто отбрасывают предыдущие заголовки и сообщают только значение, которое было задано в последнем заголовке. Если вы находитесь за несколькими прокси-серверами (например, NGINX к HAProxy к Unicorn), вы должны протестировать свой сервер Rack, чтобы убедиться в корректности данных.
ЕСЛИ ВЫ НЕ ИСПОЛЬЗУЕТЕ ПРОКСИ, ЭТО ДЕЛАЕТ ВАС УЯЗВИМЫМ К ПОДМЕНЕ IP-АДРЕСА. Этот промежуточный слой предполагает, что есть хотя бы один прокси, который устанавливает заголовки с удалённым IP-адресом клиента. Если вы не используете прокси, например, разместив приложение на Heroku без SSL, любой клиент может заявить о любом IP-адресе, установив заголовок X-Forwarded-For. Если это важно для вас, то вам нужно явно отбросить или проигнорировать эти заголовки до того, как этот промежуточный слой будет запущен.
Константы
- TRUSTED_PROXIES
-
Список доверенных IP-адресов по умолчанию просто включает IP-адреса, гарантированно являющиеся частными адресами в соответствии со спецификацией IP. Они не будут конечным IP-адресом клиента в производстве, поэтому отбрасываются. Подробности см. в en.wikipedia.org/wiki/Private_network.
Атрибуты
Публичные методы класса
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 60
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
ActiveSupport::Deprecation.warn(<<~EOM)
Setting config.action_dispatch.trusted_proxies to a single value has
been deprecated. 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 unlike passing a single argument, passing an enumerable
will *replace* the default set of trusted proxies.
EOM
Array(custom_proxies) + TRUSTED_PROXIES
end
end Создать новый RemoteIp экземпляр промежуточного слоя.
Опция ip_spoofing_check включена по умолчанию. При включенной опции, если клиент пытается скрыть свой IP-адрес, генерируется исключение. Логично выключить эту проверку для сайтов, предназначенных для клиентов, не использующих IP-адреса (например, WAP-устройств), или за прокси-серверами, которые устанавливают заголовки некорректно или запутанно (например, AWS ELB).
Аргумент custom_proxies может принимать перечислимый объект, который будет использоваться вместо TRUSTED_PROXIES. Любая настройка прокси поместит нужное значение в середину (или в начало) списка X-Forwarded-For, с вашими прокси-серверами после него. Если ваши прокси-серверы не удалены, передайте их через параметр custom_proxies. Таким образом, промежуточный слой проигнорирует эти IP-адреса и вернёт нужный вам.
Публичные методы экземпляра
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 90 def call(env) req = ActionDispatch::Request.new env req.remote_ip = GetIp.new(req, check_ip, proxies) @app.call(req.env) end
Так как IP-адрес может не потребоваться, мы сохраняем объект здесь без расчёта IP, чтобы не замедлять большинство запросов. Для тех запросов, которым нужен IP-адрес, метод GetIp#calculate_ip вычислит кешированный IP-адрес клиента.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.