В данном руководстве мы рассмотрим как реализовать концепцию большого динамического черного или белого списка с помощью веб-сервера Nginx, сервера Redis и скрипта расширения Nginx, реализованного на Lua.
В данном руководстве все программное обеспечение будет устанавливаться в Ubuntu 16.04 или 18.04. Практически без изменений данные решения можно применить и в других дистрибутивах, основанных на Debian.
Nginx содержит встроенный механизм обработки черных или белых списков, который подходит в случае использования небольших списков. Однако, этот механизм неудобен, когда требуется работать с большими списками адресов, когда списки формируются динамически.
К счастью, Nginx поддерживает модули расширения на языке Lua, которые совместно с кэшу в памяти Redis позволяют реализовать требуемую функциональность черных и белых списков.
Установка Nginx и Redis в Ubuntu Linux
Установка всех компонентов будет производиться с помощью APT:
$ sudo apt update $ sudo apt install redis-server nginx nginx-extras lua-nginx-redis
Проверяем доступность Nginx, открыв страницу по ip-сервера в браузере:
Проверим доступность Redis:
$ redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> quit $
Если вы настраиваете сервер для боевого использования, обязательно настройте безопасность Redis по нашему руководству.
Перейдем к настройке белого или черного списков.
Настройка белого списка
Мы будем использовать рецепт скрипта белого списка, который приведет в GitHub. Для его использования внесем несколько директив в Nginx:
В файл /etc/nginx/nginx.conf добавим строку, приведенную ниже:
http { ## # Basic Settings ## lua_shared_dict ip_whitelist 1m;
и в секцию server или location сам обработчик по белому списку. В нашем примере добавим в файл /etc/nginx/sites-enabled/default:
# Default server configuration # server { listen 80 default_server; listen [::]:80 default_server; access_by_lua_file /etc/nginx/lua/ip_whitelist.lua; ....
Скачаем сам Lua-скрипт:
$ sudo mkdir /etc/nginx/lua $ cd /etc/nginx/lua $ sudo wget https://gist.githubusercontent.com/itbdw/bc6c03f754cc30f66b824f379f3da30f/raw/a655713ecbe676558244d44dc78c875d7a84f8d1/ip_whitelist.lua
Проверим, конфигурацию Nginx и перезапустим его:
$ sudo nginx -t && sudo service nginx restart
Если теперь вы попытаетесь открыть сайт, то получите страницу с ошибкой вида:
Теперь добавьте в Redis свой IP с помощью консоли Redis:
$ redis-cli SADD ip_whitelist A.B.C.D
и снова проверьте доступ к сайту, должна открываться страница Nginx, которую мы уже видели раньше:
Опять удалите запись для вашего IP с помощью консоли Redis:
$ redis-cli SREM ip_whitelist 148.77.35.49
Результатом доступа к сайту снова будет ошибка.
Таким образом, мы успешно настроили белый список, используя Nginx, Redis и скрипт Lua, который подходит для динамического управления записями и работы с большими списками. Список реализован с помощью высокопроизводительных множеств Redis, скорость доступа к которым подчиняется закону трудоемкости O(1), то есть работает быстро, если по-русски.
Настройка черного списка
Черный список настраивается аналогично с точностью до замены white на black:
- lua_shared_dict ip_blacklist 1m;
- access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;
- скрипт.
Модифицируйте скрипт для использования правильного сервера Redis и правильного модуля Lua для него (автор использует для этого скрипта resty.redis, а не nginx.redis):
$ sudo sed -i 's|your.redis.server.here|127.0.0.1|' ip_blacklist.lua $ sudo sed -i 's| \= require "resty.redis"| \= require "nginx.redis"|' ip_blacklist.lua
Добавление и удаление записей в черный список осуществляется следующими командами:
$ redis-cli SADD ip_blacklist A.B.C.D $ redis-cli SREM ip_blacklist A.B.C.D
Заключение
Динамические черные и белые списки являются более универсальным решением в случае необходимости использования больших списков с необходимостью изменения записей на лету, что может быть востребовано при наличии средств диагностики злоумышленников.
Хранение списков в Redis позволяет обеспечить высочайшую производительность решения, которая не деградирует с ростом списка адресов в списке. Доступность Redis через API подходит для интеграции со сторонними поставщиками записей для списков.
В том случае, если необходимо сохранение списков между перезагрузками Redis, то в файл конфигурации /etc/redis/redis.conf необходимо изменить строку:
appendonly no на appendonly yes
Скрипт на Lua достаточно прост и легко может быть адаптирован для более специфических задач.