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
як джерело потенційних ІВ.
Алгоритм схожий на, 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
призначений для запобігання спуфінгу шляхом вибору останнього ІР у ланцюжку. Специфікація X-Forwarded-For вказує, що кожен проксі додає IP-адресу запитувача до кінця ланцюжка. Фільтруючи проксі-сервери з білого списку, останнім записом гарантовано буде IP-адреса клієнта, записана вашим першим проксі-сервером із білого списку. Існує один нюанс, звичайно, що це те , що ви повинні на насправді бути запущений проксі - сервер , який завжди набори / приєднує 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
request.remote_ip
на те, що він переглядає ланцюжок HTTP_X_FORWARDED_FOR, він все одно може бути підроблений, якщо у вас є Rails позаду nginx або haproxy. У nginx використовуйтеproxy_set_header X-Forwarded-For $remote_addr;
замістьproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
. В останньому випадкуcurl -H "X-Forwarded-For: 6.66.6.66" http://example.com
видастьrequest.remote_ip
6.66.6.66, який буде підробляти будь-яку перевірку ip, яку ви маєте в Rails.