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_ip6.66.6.66, який буде підробляти будь-яку перевірку ip, яку ви маєте в Rails.