Hello! On Mon, Jun 12, 2023 at 02:31:04AM +0300, Gena Makhomed wrote:
> On 09.06.2023 9:29, Maxim Dounin wrote: > > >> (1) client ==> vps_server ==> main_server > >> > >> (2) client ==> cloudflare => vps_server ==> main_server > > > Если у вас в обоих случаях vps_server проксирует всё через stream > > с proxy_protocol, то на принимающей стороне вам в любом случае > > надо сначала достать реальный адрес клиента из proxy_protocol. > > А уже потом смотреть в заголовки (или не смотреть, если на > > vps_server пришли не с IP-адресов Cloudflare). > > > > То есть, фактически, для корректной работы такой схемы - нужен > > "real_ip_recursive on;" (http://nginx.org/r/real_ip_recursive) > > и заголовок со списком нужных адресов. > > > > Сейчас из коробки такое можно сделать дополнительным > > проксированием с установкой заголовка. Для стандартного заголовка > > X-Forwarded-For, благо Cloudflare его ставит, конфигурация будет > > выглядеть как-то так: > > > > server { > > listen 8080 proxy_protocol; > > > > set_real_ip_from <vps>; > > real_ip_header proxy_protocol; > > > > location / { > > proxy_pass http://127.0.0.1:8081; > > proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; > > } > > } > > > > server { > > listen 8081; > > > > set_real_ip_from 127.0.0.1; > > set_real_ip_from <cloudflare>; > > > > real_ip_header X-Forwarded-For; > > real_ip_recursive on; > > > > ... > > } > > Это будет работать только в том случае, если система защиты от DDoS > указывает IP адрес клиента в заголовке X-Forwarded-For. Если же какая-то > экзотическая система защиты от DDoS будет указывать реальный IP клиента > в каком-то другом заголовке, например, только в загловке X-Real-IP - > тогда этот метод работать не будет, потому что в nginx есть переменная > $proxy_add_x_forwarded_for но в nginx нет перменной $proxy_add_x_real_ip > > Что же нам делать в том случае, если какая-то система защиты от DDoS > передает реальный IP клиента в заголовке отличном от X-Forwarded-For ? Если нужно работать с нестандартными заголовками - это можно сделать с помощью модуля map, благо сейчас его возможностей с лихвой хватает для реализации логики, аналогичной работе переменной $proxy_add_x_forwarded_for. Не говоря уже о том, что, по большому счёту, в данной конкретной задаче полная логика $proxy_add_x_forwarded_for не важна, и вполне можно обойтись безусловным добавлением адреса через запятую: proxy_set_header X-Real-IP "$http_x_real_ip, $remote_addr"; В вырожденном случае пустого $http_x_real_ip будет лишняя запятая в начале, но на работоспособность это не влияет. > >> Или существует какой-то еще лучший вариант решения этой задачи? > > > > Я периодически думаю о том, чтобы научить модуль realip брать > > список IP-адресов не из заголовка, а непосредственно из > > переменной. Тогда необходимость в дополнительном проксировании в > > подобных странных конфигурациях отпадёт. > > Каким же образом тут можно будет обойтись без двойного проксирования, > если необходимо будет сначала указывать real_ip_header proxy_protocol; > чтобы узнать реальный IP сервера cloudflare, который подключился к VPS, > и при этом - несколько директив real_ip_header нельзя указывать в одном > контексте. А если указать одну директиву real_ip_header одновременно > и в контексте server и одну в контексте location, то согласно правил > наследования директив в nginx - директива real_ip_header в контексте > location будет выполняться, а директива real_ip_header в контексте > server выполняться не будет, и всегда будет просто проигнорирована. > > Максим, можете пояснить в чем тут моя ошибка и что я не так понял? Идея состоит в том, что вместо указания названия заголовка в директиве real_ip_header - указать непосредственно адреса. Тогда вместо real_ip_header proxy_protocol; можно будет написать что-то вроде: real_ip_address $proxy_protocol_addr; А для последующего рекурсивного поиска в заголовке X-Forwarded-For (если он получен с доверенного адреса), соответственно, будет достаточно написать: real_ip_address "$http_x_forwarded_for, $proxy_protocol_addr"; И, соответственно, полная конфигурация будет выглядеть как: server { listen 8080 proxy_protocol; set_real_ip_from <vps>; set_real_ip_from <cloudflare>; real_ip_address "$http_x_forwarded_for, $proxy_protocol_addr"; real_ip_recursive on; ... } То есть ровно то, что в примере выше делается с помощью дополнительного проксирования - в такой схеме будет сделано с помощью установки переменной. [...] > Максим, вопрос в том, можно ли будет в основной ветке nginx заменить > текущую версию модуля ngx_http_realip_module новой версией модуля, > в которой будет реализован вариант директивы set_real_ip_from > с одним, тремя и пятью параметрами? Я не вижу решительно никаких причин переусложнять работу модуля подобным образом. Имеющиеся задачи вполне решаются с помощью существующих возможностей модуля, что и было продемонстрировано в исходном ответе. С помощью минимальных (в первую очередь с точки зрения пользователя) доработок можно сделать так, чтобы подобные задачи решались эффективнее - однако, как уже было сказано, острой необходимости в этом пока не прослеживается. [...] -- Maxim Dounin http://mdounin.ru/ _______________________________________________ nginx-ru mailing list nginx-ru@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-ru