Какой лучший способ блокировать диапазоны 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;
}

Другие вопросы по тегам