Какой лучший способ блокировать диапазоны CIDR в nginx при использовании proxy_protocol?
У меня есть небольшой пул экземпляров nginx, которые стоят за ELB в AWS. Этот ELB имеет выход в Интернет и говорит по протоколу PROXY, а не HTTP.
Вот соответствующий раздел моего main.vhost
server {
# speak only PROXY protocol
# Accept 80/443; we'll do the http -> https re-dir elsewhere in conf
# SSL is default mode
listen 443 default_server ssl proxy_protocol;
listen 80 proxy_protocol;
Я пытаюсь использовать deny
директива от ngx_http_access_module
для предотвращения доступа к ряду блоков CIDR.
Например: в .conf
файл, загружаемый nginx при запуске:
include /etc/nginx/ip_block/*.conf;
и в /etc/nginx/ip_block/
dir есть хотя бы один файл:
$ cat /etc/nginx/ip_block/some_cidr_ranges.conf | wc -l
361
$ head /etc/nginx/ip_block/some_cidr_ranges.conf
deny 2604:a880:1::/48;
<snip>
deny 208.68.36.0/22;
Тем не менее, кажется, что nginx deny
Директива работает только с $remote_addr
переменная и не работает с $proxy_protocol_addr
переменная. Это означает, что я не могу использовать оба deny
директива и proxy_protocol
все вместе.
Похоже, что ngx_stream_realip_module
Модуль может быть использован для настройки значений $remote_addr
к $proxy_protocol_addr
Однако, имеющаяся у меня сборка nginx не настроена на --with-stream_realip_module
встроенный флаг. Я сейчас бегу 1.10.3
но похоже, что with-stream_realip_module
флаг был введен в сборку 1.11.4
( https://github.com/nginx/nginx/commit/fe2774a9d689fa1bf201dd0e89449e3d9e4ad926)
Вариант 1. Создайте версию nginx из исходного кода с функциями, которые мне нужны.
Просматривая документацию для deny
Директива, я нашел эту заметку:
In case of a lot of rules, the use of the ngx_http_geo_module module variables is preferable.
От: https://nginx.org/en/docs/http/ngx_http_access_module.html
Что заставляет меня задуматься, есть ли лучший способ достичь моей цели - блокировать диапазоны CIDR, которые могут работать с двоичным файлом nginx, который у меня есть в настоящее время.
Могу ли я попробовать что-то вроде этого:
geo $proxy_protocol_addr $blocked_cidr {
default 01;
include conf/some_cidr_ranges_to_block.conf;
}
где файл conf/some_cidr_ranges_to_block.conf
похоже:
2604:a880:1::/48 02;
<snip>
208.68.36.0/22 02;
а затем в моей директиве сервера я мог бы сделать что-то вроде:
if ($blocked_cidr != 01) {
return 403;
}
Вариант 2: Попытка использовать geo
директива и пользовательский диапазон IP-адресов -> база данных "кода страны" для блокировки трафика.
Мои вопросы:
- Is *option 1* going to be a better use of time / is it worth it to build my own version of nginx with the necessary `stream_realip_module` compiled in or is it going to be more performant / effective to use the `geo` directive to map the `$proxy_protocol_addr` onto a set of ranges as shown above (*option 2*)
- Is there some other way to block or filter traffic in nginx by cidr block when using nginx in `proxy_protocol` mode that i have not yet considered?
2 ответа
Быстрое обновление / ответ на мой вопрос.
Благодаря предложению Тан Хон Тата мне больше не нужно собирать собственную версию nginx. Это убирает вариант 1 со стола и спасает меня от работы. Спасибо!
Я загрузил несколько сотен deny
правила в nginx, и я слежу за влиянием на производительность.
Кроме того, я реализовал что-то похожее на вариант 2 из моего OP, используя geo
директивы. Я так же отслеживаю влияние.
До сих пор мне не ясно, почему документация nginx выдает предложение об использовании deny
с "множеством" правил:
In case of a lot of rules, the use of the ngx_http_geo_module module variables is preferable.
geo
Директива позволяет мне более гибко, потому что я могу выбирать, куда отправлять пользователей. deny
Директива 403 и не может быть изменена.
Вы могли бы использовать -
if ($proxy_protocol_addr != a.b.c.d) {
return 403;
}