Глава 7. Управления безопасностью
Содержание
- Глава 7. Управления безопасностью
- Введение
- Основанный на IP доступ
- Разрешение обмена ресурсами между источниками
- Шифрование стороны клиента
- Восходящее шифрование
- Безопасность местоположения
- Генерация безопасного соединения при помощи ключа безопасности
- Безопасность местоположения при помощи ограниченной даты
- Генерация ссылки с ограниченным сроком
- Перенаправление HTTPS
- Перенаправление на HTTPS когда SSL/ TLS прекращается до NGINX
- Строгая безопасность доставки HTTP
- Удовлетворение любого числа методов безопасности
- Динамичное ослабление DDoS
Мероприятия по безопасности выполняются на различных уровнях и для её истинной прочности следует иметь множество уровней в вашей модели безопасности. В данной главе мы пройдём множество различных способов по осуществлению мероприятий безопасности для ваших веб приложений при помощи NGINX и NGINX Plus. Вы можете применять в сочетании друг с другом многие из этих методов для содействия упрочению безопасности. Далее приводится целый ряд разделов по безопасности, которые рассматривают свойства NGINX и NGINX Plus, способные содействовать упрочнению вашего приложения. Вам следует обратить внимание на то, что эта глава не касается одной из самых крупных функциональностей безопасности NGINX, модуля NGINX ModSecurity 3.0, который превращает NGINX в Веб приложение межсетевого экрана (WAF, Web Application Firewall). Для изучения дополнительных возможностей WAF выгрузите ModSecurity 3.0 and NGINX: Quick Start Guide
Задача
Вам требуется контролировать доступ клиента на основе значения IP адреса самого клиента.
Решение
Воспользуйтесь методом доступа HTTP для управления доступом к защищаемым ресурсам:
location /admin/ {
deny 10.0.0.1;
allow 10.0.0.0/20;
allow 2001:0db8::/32;
deny all;
}
Данный конкретный блок location разрешает доступ со всех адресов IPv4 в 10.0.0.0/20
за исключением 10.0.0.1
, допускает доступ с адресов IPv6 из подсети
2001:0db8::/32
и возвращает 403 для всех поступающих с прочих адресов запросов.
Такие директивы allow
и deny
допустимы в
контекстах HTTP, server и location. Правила проверяются последовательно пока не будет найдено соответствие для удалённого
адреса запрашивающей стороны.
Обсуждение
Защита значимых ресурсов и служб в Интернете должна выполняться на разных уровнях. NGINX предоставляет такую возможность
быть одним из подобных уровней. его директива deny
блокирует доступ к некому
заданному контексту, в то время как директива allow
может применяться для допуска
подмножеств в имеющемся заблокированном доступе. Вы можете применять IP адреса, причём IPv4 и IPv6, диапазоны блоков CIDR,
ключевое слово all
, а также сокет Unix. Обычно при защите некого ресурса следует
разрешат некий блок внутренних IP адресов и запрещать доступ для all
.
Задача
Вы обслуживаете ресурсы из одного домена и вам требуется разрешить совместное использование ресурсов между источниками (CORS, Cross-Origin Resource Sharing) чтобы позволить браузерам применять эти ресурсы.
Решение
Для включения CORS измените заголовки на основе метода request
:
map $request_method $cors_method {
OPTIONS 11;
GET 1;
POST 1;
default 0;
}
server {
...
location / {
if ($cors_method ~ '1') {
add_header 'Access-Control-Allow-Methods'
'GET,POST,OPTIONS';
add_header 'Access-Control-Allow-Origin'
'*.example.com';
add_header 'Access-Control-Allow-Headers'
'DNT,
Keep-Alive,
User-Agent,
X-Requested-With,
If-Modified-Since,
Cache-Control,
Content-Type';
}
if ($cors_method = '11') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
}
В данном методе происходит много чего, что было сокращено при помощи некого map
группе приводимых методов GET
и POST
всем сразу. Приводимый метод запроса OPTIONS
возвращает некий
предполётный
запрос для запрашивающего клиента относительно этих правил
CORS. Под CORS разрешены методы OPTIONS
, GET
и POST
. Установка значения заголовка
Access-Control-Allow-Origin
делает возможным обслуживание содержимого с данного
сервера, также применимым для страниц, происходящих с тех ,которые соответствуют данному заголовку. Такой предполётный
запрос может быть кэширован для данного клиента на протяжении 1 728 000 секунд, или 20 дней.
Обсуждение
Подобные JavaScript ресурсы применяют CORS когда запрашиваемые ими ресурсы расположены в отличающихся от из собственных
доменах. Когда некий запрос рассматривается как предполагающий совместное применение источников, его браузеру требуется
следовать правилам CORS. Браузер запрашивающей стороны не будет применять такой ресурс если у него нет заголовков, которые
именно это ему предписывают делать. Для того чтобы разрешить использование наших ресурсов с прочих поддоменов, нам требуется
установить необходимые заголовки CORS, что может быть выполнено при помощи директивы add_header
Если таким запросом являетс некий GET
, HEAD
или POST
со стандартным типом содержимого, и такой запрос не имеет особых заголовков,
его браузер сделает соответствующий запрос и проверит только его происхождение. Прочие методы заставят этот браузер выполнять
необходимый предполётный запрос для проверки условий того сервера, которому подчинён такой ресурс. Если у вас не установлен
надлежащий заголовок, браузер запроса получит некое сообщение об ошибке когда попытается воспользоваться данным ресурсом.
Задача
Вам требуется шифровать обмен между своим сервером NGINX и его клиентом.
Решение
Для шифрования обмена воспользуйтесь одним из имеющихся модулей SSL, например, ngx_http_ssl_module
или ngx_stream_ssl_module
:
http { # All directives used below are also valid in stream
server {
listen 8433 ssl;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_certificate /etc/nginx/ssl/example.pem;
ssl_certificate_key /etc/nginx/ssl/example.key;
ssl_certificate /etc/nginx/ssl/example.ecdsa.crt;
ssl_certificate_key /etc/nginx/ssl/example.ecdsa.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
}
Данная конфигурация настраивает сервер на ожидание по порту с шифрованием SSL, 8443. Данный сервер принимает протоколы SSL версий TLSv1.2 и TLSv1.3. Для применения данным сервером раскрываются два набора местоположений сертификата и пар ключей. Данному серверу предписывается применять наивысшую предлагаемую его клиентом неприступность при ограничении небольшим числом не являющихся безопасными. Поскольку мы предоставили некую пару ключей ECC (Elliptic Curve Cryptopgraphy), наивысшим приоритетом обладает именно шифрование ECC. Имеющиеся кэш SSL сеанса и таймаут делают для исполнителей возможным кэшировать и сохранять параметры сеанса на заданный промежуток времени. Существует большое число прочих параметров кэширования сеанса, которые способствуют производительности и безопасности для любых видо вариантов применения. Вы можете использовать параметры кэширования сеанса совместно друг с другом. Однако если определять параметр без значения по умолчанию отключит то значение по умолчанию, которое встроено в кэширование сеанса.
Обсуждение
Безопасный транспортный уровень является наиболее распространённым способом шифрования информации при передаче. На момент написания данной книги протокол TLS более предпочтителен нежели протокол SSL. Это обусловлено тем, что версии SSL с 1 по 3 теперь рассматриваются как лишённые защищённости. Хотя само название протокола и может быть иным, TLS всё- таки устанавливает secure socket layer (протокол защищённых сокетов). NGINX позволяет вашей службе защищать информацию между вами и вашими клиентами, что в свою очередь защищает и самого клиента и ваш бизнес. При применении подписанного сертификата вам требуется прицеплять свой сертификат к имеющейся цепочке, причём ваш сертификат должен пребывать в надлежащем файле над этой цепочкой. Если ваш центр сертификации предоставил множество файлов в вашей цепочке, он также может предоставить и порядок их следования. Кэширование SSL сеанса расширяет производительность через отсутствие потребности согласования версий SSL/ TLS и шифра.
При тестировании было установлено, что сертификаты ECC быстрее сертификатов RSA с той же строгостью. Его размер ключа меньше, что в результате приводит к возможности обслуживания большего числа подключений SSL/ TLS, причём с более быстрым квитированием. NGINX позволяет настраивать несколько сертификатов и ключей, а затем обслуживать оптимальный для браузера клиента сертификат. Это делает для вас возможным использовать преимущества новой технологии, но при этом обслуживать и старых клиентов.
Также ознакомьтесь
Задача
Вам требуется шифровать обмен между NGINX и конкретной службой восходящего потока, а также устанавливать особые правила согласования для регулировок надёжности или когда данный восходящий поток пребывает вне вашей безопасной сетевой среды.
Решение
Для задания правил SSL вам следует применить директивы SSL для своего модуля посредника HTTP:
location / {
proxy_pass https://upstream.example.com;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_protocols TLSv1.2;
}
Эти директивы посредника устанавливают особые правила SSL чтобы подчиняться NGINX. Эти настраиваемые директивы
гарантируют что NGINX удостоверяет что данный сертификат и цепочка в данной службе восходящего потока подтверждён до
двух сертификатов в глубину. Соответствующая директива proxy_ssl_protocols
определяет что этот NGINX будет применять только TLS с версией 1.2. По умолчанию NGINX не проверяет сертификаты
восходящего потока и применяет все версии TLS.
Обсуждение
Имеющиеся директивы для нашего модуля посредника HTTP очень многочисленны, а если вам требуется шифровать обмен
восходящего потока, вам следует по крайней мере включить установление подлинности. Вы можете выступать посредником поверх
HTTPS изменяя протокол в том значении, которое передаётся в соответствующую директиву proxy_pass
.
Тем не менее, это не подтверждает имеющийся сертификат восходящего потока. Прочие директивы, такие как
proxy_ssl_certificate
и proxy_ssl_certificate_key
,
позволяют вам ограничивать шифрование восходящего потока расширенной безопасностью. Вы также можете предписать
proxy_ssl_crl
или некий список аннулированных сертификатов, который перечисляет
сертификаты, которые более не рассматриваются как допустимые. Такие директивы посредника SSL помогают упрочнять каналы
взаимодействия вашей системы внутри вашей собственной сетевой среды или поверх общедоступного интернета.
Задача
Вам требуется при помощи ключа безопасности защитить некий блок location.
Решение
secure_link_secret
:
location /resources {
secure_link_secret mySecret;
if ($secure_link = "") { return 403; }
rewrite ^ /secured/$secure_link;
}
location /secured/ {
internal;
root /var/www;
}
Данная конфигурация создаёт некий внутренний и повёрнутый в общедоступную стороны блоки location. Развёрнутый в сторону
общей доступности блок location /resources
будет возвращать 403 Forbidden всякий раз
когда URI его запроса содержит некую строку хэширования md5
, которая не может быть
проверена тем кодом безопасности, который предоставляется в установленной директиве secure_link_secret
.
Значение переменной $secure_link
является некой пустой строкой пока значение
хэша URI не удостоверено.
Обсуждение
Предоставление безопасности при помощи кода безопасности является великолепным способом гарантии того что ваши файлы
защищены. Такой код безопасности применяется в сочетании со значением URI. Данная строка далее хэшируется посредством
md5
, и в получаемом URI применяются шестнадцатеричные цифры данного хэша
md5
. Этот хэш помещается в надлежащую ссылку и вычисляется NGINX. NGINX обладает
информацией относительно значений запрашиваемых пути и файла, поскольку они пребывают в URI после значения хэша. NGINX
также знает ваш код безопасности (secret), поскольку он предоставляется через соответствующую директиву
secure_link_secret
. NGINX имеет возможность быстро удостоверивать значение хэша
md5
и сохранять получаемый URI в значении переменной
$secure_link
. Если же значение хэша не подтверждается, значение переменной
устанавливается в некую пустую строку. Важно отметить, что те аргументы, которые передаются в
secure_link_secret
обязаны быть статической строкой; они не могут быть некой
переменной.
Задача
Вам требуется сгенерировать в своём приложении некую безопасную ссылку при помощи какого- то кода безопасности.
Решение
Имеющийся в NGINX модуль безопасной ссылки принимает значения шестнадцатеричных цифр некой хэшированной
md5
строки, причём такая строка представляет собой сцепление значение URI пути
и сам код безопасности (secret). Отталкиваясь от своего последнего рецепта, Безопасность местоположения, мы создадим защищённую ссылку, которая будет работать с предыдущим примером
конфигурации с учётом того что имеется некий файл, представленный в
/var/www/secured/index.html
. Для выработки требуемых
значений шестнадцатеричных цифр md5
мы можем применить команду Unix
openssl
:
$ echo -n 'index.htmlmySecret' | openssl md5 -hex
(stdin)= a53bee08a4bf0bbea978ddf736363a12
Здесь мы показываем значение защищаемого нами URI, index.html
,
сцепляемого с нашим кодом безопасности, mySecret
. Эта строка передаётся в
соответствующую команду openssl
для вывода шестнадцатеричных цифр
md5
.
Ниже приводится некий пример построения в Python тех же самых шестнадцатеричных цифр с применением библиотеки
hashlib
, которая входит в состав Стандартной библиотеки Python:
import hashlib
hashlib.md5.(b'index.htmlmySecret').hexdigest()
'a53bee08a4bf0bbea978ddf736363a12'
Теперь, когда у нас имеются данные шестнадцатеричные цифры, мы можем применять их в неком URL. Нашим примером будет
www.example.com, выполняющий некий запрос для своего файла /var/www/secured/index.html
через location /resources
. Нашим полным URL будет следующее:
www.example.com/resources/a53bee08a4bf0bbea978ddf736363a12/\
index.html
Обсуждение
Выработка цифровых значений может выполняться множеством способов, причём на множестве языков программирования. Что следует
помнить: значение пути URI следует перед самим кодом безопасности, в этой строке нет никаких символов перехода на новую строку,
а также применяются шестнадцатеричные цифры из соответствующего хэширования md5
.
Задача
Вам требуется защитить некое местоположение при помощи ссылки, которая имеет срок истечения в будущем и является специфичной для некого клиента.
Решение
Для настройки срока истечения действия воспользуйтесь прочими включёнными в обсуждаемый модуль безопасных ссылок директивами и применяйте переменные в своей защищённой ссылке:
location /resources {
root /var/www;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr mySecret";
if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
Приводимая директива secure_link
получает два разделяемые запятой параметра.
Значением первого параметра является переменная, которая содержит значение хэша md5
.
Данный пример использует некий аргумент HTTP md5
. Вторым параметром является
переменная, которая содержит значение времени истечения срока данной ссылки, исчисляемого в формате времени эпохи Unix.
Следующая директива secure_link_md5
получает некий отдельный параметр,
объявляющий значение формата той строки, которая применяется для построения значения хэша
md5
. Как и для прочих конфигураций, когда это значение хэша не проходит
процедуру удостоверения, значение переменной $secure_link
устанавливается в некую
пустую строку. Тем не менее, при данном применении, в случае соответствия значения хэша, но при истечении срока действия
значение переменной $secure_link
будет установлено в
0
.
Обсуждение
Данное применение защищённой ссылки является более гибким и выглядит более понятным чем тот
secure_link_secret
, который показан в рецепте
Безопасность местоположения. При помощи этих директив мы способны
применять любое число доступных для NGINX переменных, в своей хэшируемой строке. Использование специфичных для пользователя
переменных в такой строке хэша усилит вашу безопасность, поскольку у пользователей не будет возможности выставлять на продажу
ссылки к защищённым ресурсам. Рекомендуется применять переменные, подобные $remote_addr
или $http_x_forwarded_for
, либо некий заголовок куки сеанса, вырабатываемый вашим
приложением. Значения аргументов для secure_link
может поступать из любых предпочитаемых
вами переменных, и они могут именоваться так чтобы лучше соответствовать вашим потребностям. Значения условий относительно
значения переменной $secure_link
устанавливаются для возврата известных кодов HTTP для
Forbidden и Gone. Значение 410 HTTP, Gone прекрасно подходит для просроченных ссылок, так как данное условие рассматривается
как неизменное.
Задача
Вам требуется выработать ссылку со сроком истечения.
Решение
Сгенерируйте некий временной штамп (timestamp) для значения срока истечения в формате эпохи Unix. В некой системе Unix вы можете выполнить проверку применив значение даты, мкак это демонстрируется следующим примером:
$ date -d "2020-12-31 00:00" +%s --utc
1609372800
Далее вам требуется сцепить строку своего хэша для установления значения строки, настраиваемой при помощи директивы
secure_link_md5
. В данном случае нашей используемой строкой будет
1293771600/resources/index.html127.0.0.1 mySecret
. Значение хэша
md5
слегка отличается от просто шестнадцатеричных цифр. Это некий хэш
md5
в двоичном формате, кодированный base64, причём символы плюса
(+
) транслируются в дефисы (-
),
слэши (/
) транслируются в подчёркивания (_
),
а символы равенства (=
) удаляются. Вот некий пример в какой-то системе Unix:
$ echo -n '1609372800/resources/index.html127.0.0.1 mySecret' \
| openssl md5 -binary \
| openssl base64 \
| tr +/ -_ \
| tr -d =
TG6ck3OpAttQ1d7jW3JOcw
Теперь, когда мы имеем свой хэш, мы можем воспользоваться им в качестве некого аргумента совместно с датой истечения срока:
'/resources/index.html?md5=TG6ck3OpAttQ1d7jW3JOcw&expires=1609372800'
Далее приводится более практичный пример на Python, применяющий относительное время для срока истечения, устанавливающий значение срока истечения ссылки на один час с момента его выработки. На момент написания данной книги этот пример работал с Python 2.7 b 3.x с использванием их Стандартной библиотеки Python:
from datetime import datetime, timedelta
from base64 import b64encode
import hashlib
# Set environment vars
resource = b'/resources/index.html'
remote_addr = b'127.0.0.1'
host = b'www.example.com'
mysecret = b'mySecret'
# Generate expire timestamp
now = datetime.utcnow()
expire_dt = now + timedelta(hours=1)
expire_epoch = str.encode(expire_dt.strftime('%s'))
# md5 hash the string
uncoded = expire_epoch + resource + remote_addr + mysecret
md5hashed = hashlib.md5(uncoded).digest()
# Base64 encode and transform the string
b64 = b64encode(md5hashed)
unpadded_b64url = b64.replace(b'+', b'-')\
.replace(b'/', b'_')\
.replace(b'=', b'')
# Format and generate the link
linkformat = "{}{}?md5={}?expires={}"
securelink = linkformat.format(
host.decode(),
resource.decode(),
unpadded_b64url.decode(),
expire_epoch.decode()
)
print(securelink)
Обсуждение
При наличии данного шаблона мы имеем возможность вырабатывать некую защищённую ссылку в особом формате, которая может применяться в
URI. Данный код безопасности (secret) предоставляет защиту при помощи использования переменных, которые никогда не отправляются
определённому клиенту. У вас есть возможность применять столько переменных, сколько вам потребуется чтобы сделать свое
местоположение безопасным. Хэширование md5
и кодирование base64 являются распространёнными,
оюладают малым весом и доступны почти во всех языках программирования.
Задача
Вам требуется перенаправлять не зашифрованные запросы в HTTPS.
Решение
Воспользуйтесь повторной записью для отправки всего обмена HTTP в HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
данная конфигурация выполняет ожидание по порту 80 в качестве её сервера по умолчанию как для IPv4, так и для IPv6, а
также для любых названий хостов. Оператор return
возвращает некий код 301,
постоянно выполняя перенаправление в имеющийся в том же самом хосте сервер HTTP и подставляя URI запроса.
Обсуждение
Важно всегда выполнять перенаправление в HTTPS, когда он доступен. Вы можете обнаружить что вам не требуется
перенаправлять все запросы, а только те, которые содержат чувствительную информацию, подлежащую передачу между
клиентом и сервером. В данном случае вы можете пожелать поместить в оператор return
только конкретные расположения, например, /login
.
Задача
Вам требуется выполнять перенаправление в HTTPS, однако у вас истёк срок SSL/ TLS на уровне перед NGINX.
Решение
Для выяснения того что вам требуется выполнить перенаправление воспользуйтесь стандартным заголовком
X-Forwarded-Proto
:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
}
Эта конфигурация во многом схожа с перенаправлением HTTPS. Тем не менее, в данной конфигурации мы выполняем
перенаправление только когда значение заголовка X-Forwarded-Proto
эквивалентно
HTTP.
Обсуждение
Достаточно распространённым случаем является когда у вас может завершится срок действия SSL/ TLS на неком уровне перед NGINX. Одной из причин может быть то что вы делаете нечто подобное сбережению затрат на вычисления. Тем не менее, вам требуется быть уверенным что все запросы являются HTTPS, но при этом сам уровень с прекращённым SSL/ TLS не имеет возможности перенаправления. Он способен, однако, устанавливать заголовки посредника. Эта конфигурация работает с такими уровнями как Amazon Web Services Elastic Load Balancer, который выполняет разгрузку SSL/ TLS без дополнительных затрат. Это удобный трюк для обеспечения защиты для вашего обмена HTTP.
Задача
Вам требуется проинформировать браузеры что им никогда не следует отправлять запросы поверх HTTP.
Решение
Воспользуйтесь расширением HSTS (HTTP Strict Transport Security) устанавливая заголовок
Strict-Transport-Security
:
add_header Strict-Transport-Security max-age=31536000;
Данная конфигурация устанавливает значение заголовка Strict-Transport-Security
на максимальный возраст в один год. Он будет инструктировать соответствующий браузер всегда осуществлять некое
внутреннее перенаправление при попытке выполнения к данному домену запросов HTTP, чтобы все запросы выполнялись поверх
HTTPS.
Обсуждение
Для некоторых приложений один перехваченный атакой с человеком в середине запрос HTTP может стать концом всей компании. Если сообщение некой содержащей чувствительную информацию формы отправляется по HTTP, перенаправление HTTPS из NGINX не спасёт вас; взлом уже произошёл. Данный вариант улучшения безопасности информирует браузер запросов никогда не делать никаких запросов HTTP, а следовательно они никогда не отправляются в незащищённом виде.
Также ознакомьтесь
Задача
Вам требуется предоставить множество способов передачи безопасности закрытой площадке.
Решение
Для указания того что вы желаете удовлетворять неким или даже всем применяемым методам безопасности, для выдачи NGINX
инструкции об этом примените директиву satisfy
:
location / {
satisfy any;
allow 192.168.1.0/24;
deny all;
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;
}
Данная конфигурация сообщает NGINX что запрашивающий location /
пользователь должен удовлетворять одному из установленных методов безопасности: либо эти запросы должны происходить с блока CIDR
192.168.1.0/24
, либо быть способными поддерживать некие имя пользователя и пароль,
которые могут быть найдены в обозначенном файле conf/htpasswd
. Данная
директива satisfy
имеет всего два варианта:
any
или all
.
Обсуждение
Описанная директива satisfy
является великолепным способом предложения
множества способов аутентификации для вашего веб приложения. Определяя any
для директивы satisfy
, данный пользователь обязан соответствовать одной из
предоставленных защит. Определяя в директиве satisfy
значение
all
, запрашивающий пользователь должен соответствовать всем выставленным
требованиям безопасности. Данная директива может применяться совместно с http_access_module
,
описанном в рецепте Основанный на IP доступ,
http_auth_basic_module
, детализированном в рецепте
Базовая аутентификация HTTP,
http_auth_request_module
,
описанном в рецепте Подзапросы аутентификации и
описанном в рецепте JWT подтверждение
http_auth_jwt_module
. Обсуждаемая директива satisfy
поможет вам достигать этого для местоположений и серверов, которые требуют глубоких правил защиты.
Задача
Вам необходимо некое динамичное решение смягчения DDoS (Distributed Denial of Service).
Решение
Для построения некого осведомлённого о кластере ограничения частот запросов и автоматического чёрного списка воспользуйтесь NGINX Plus:
limit_req_zone $remote_addr zone=per_ip:1M rate=100r/s sync;
# Cluster-aware rate limit
limit_req_status 429;
keyval_zone zone=sinbin:1M timeout=600 sync;
# Cluster-aware "sin bin" with
# 10-minute TTL
keyval $remote_addr $in_sinbin zone=sinbin;
# Populate $in_sinbin with
# matched client IP addresses
server {
listen 80;
location / {
if ($in_sinbin) {
set $limit_rate 50; # Restrict bandwidth of bad clients
}
limit_req zone=per_ip;
# Apply the rate limit here
error_page 429 = @send_to_sinbin;
# Excessive clients are moved to
# this location
proxy_pass http://my_backend;
}
location @send_to_sinbin {
rewrite ^ /api/3/http/keyvals/sinbin break;
# Set the URI of the
# "sin bin" key-val
proxy_method POST;
proxy_set_body '{"$remote_addr":"1"}';
proxy_pass http://127.0.0.1:80;
}
location /api/ {
api write=on;
# directives to control access to the API
}
}
Обсуждение
Это решение использует некий синхронизируемый предел частот обращений и синхронизируемое хранилище ключ- значение для
динамических откликов на DDoS атаки и смягчения их действия. Параметр sync
предоставляет директивам limit_req_zone
и keyval_zone
синхронные зоны разделяемой с прочими машинами памяти в имеющемся активный- активный кластере NGINX Plus. Данный пример
выявляет клиентов, которые отправляют более 100 запросов в секунду вне зависимости от того какой из узлов NGINX Plus получает
такой запрос. После того как некий клиент превышает установленный предел частот, его IP адрес добавляется в некое хранилище
ключ- значение "sin bin" (Скамейка штрафников) через выполнение запроса API NGINX Plus. Эта Скамейка штрафников
синхронизируется по всему кластеру. Последующие запросы от попадающих на Скамейку штрафников клиентов являются предметом
очень низкого ограничения полосы пропускания, причём вне зависимости от того какой из узлов NGINX Plus получает их. Ограничение
полосы пропускания более предпочтительно чем полное отклонение запросов, ибо оно не становится очевидным сигналом для
такого клиента что смягчение DDoS атаки вступило в действие. После 10 минут данный клиент автоматически удаляется со
Скамейки штрафников.