Как использовать модуль map в Nginx

Продвинутое тестирование в Python: как писать доктесты

Модуль map позволяет создавать в конфигурационном файле Nginx переменные, значения которых являются условными, то есть зависят от значений других переменных. В этом руководстве вы узнаете, как использовать модуль map Nginx. Для этого мы попробуем выполнить два примера: настроить список перенаправлений старых URL-адресов сайтов на новые и создать список разрешенных стран для управления трафиком сайта.

Требования

  • Сервер Ubuntu 20.04 и пользователь с привилегиями sudo. Вы можете подготовить свой сервер, следуя этому руководству по начальной настройке.
  • Веб-сервер Nginx, установленный на вашем сервере. Чтобы установить его, следуйте этим инструкциям.

1: Создание тестовой веб-страницы

Сначала мы создадим тестовый файл, который будет представлять собой свежий веб-сайт. В дальнейшем мы будем использовать этот файл для проверки нашей конфигурации веб-сервера.

Давайте создадим в каталоге веб-сайта Nginx по умолчанию простую страницу index.html. В этом файле будет текст, описывающий страницу – «Home».

sudo sh -c 'echo "Home" > /var/www/html/index.html'

Давайте с помощью curl проверим, правильно ли обслуживается этот файл. Нам не нужно указывать index.html в этой команде, потому что этот файл обслуживается по умолчанию, если точное имя файла не указано:

curl http://localhost/

В результате вы должны увидеть одно слово Home.

Теперь давайте попробуем получить доступ к файлу, которого нет в /var/www/html/, например old.html:

curl -L http://localhost/old.html

В ответ вы увидите сообщение об ошибке 404 Not Found, что означает, что страница не существует:

404 Not Found

nginx/1.18.0 (Ubuntu)
В этом руководстве мы используем ненастоящий веб-сайт, но если бы файл old.html был страницей реального сайта, которую удалили, результат 404 означал бы, что все ссылки на эту страницу не работают. Это не очень хорошо, поскольку эти ссылки могли быть проиндексированы Google, пользователи могли сохранить их или поделиться с кем-нибудь, а теперь они не работают.

В следующем разделе мы будем использовать модуль map, чтобы этот старый адрес снова стал работать – путем автоматического перенаправления пользователей на новые страницы.

2: Настройка перенаправления

Для настройки редиректа на небольших веб-сайтах подойдут и простые условные операторы if. Однако на большом сайте такую конфигурацию нелегко поддерживать или расширять в долгосрочной перспективе, поскольку список условий будет быстро расти.

Модуль map – более простое и лаконичное решение. Он позволяет сравнивать значения переменных Nginx со списком условий, а затем связывать новое значение с переменной в зависимости от совпадения. В этом примере мы будем сравнивать запрошенный URL со списком старых страниц, которые нужно перенаправить на их новые версии. Каждый старый адрес мы свяжем с новым.

Модуль map является встроенным модулем Nginx, то есть его не нужно устанавливать отдельно. Чтобы создать необходимую конфигурацию перенаправления, откройте в текстовом редакторе конфигурационный файл блока server по умолчанию:

sudo nano /etc/nginx/sites-available/default

Найдите конфигурацию server, она выглядит так:


# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
. . .

Мы добавим два новых раздела: один перед блоком server, второй – внутри него. Раздел перед блоком server – это новый блок map, который определяет соответствие между старыми и новыми URL-адресами с помощью модуля map. Раздел внутри блока server – это сам редирект:

. . .
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .

Директива map $uri $new_uri принимает содержимое системной переменной $uri, которая содержит URL-адрес запрашиваемой страницы, и затем сравнивает его со списком условий в фигурных скобках. Каждый элемент в списке условий имеет два раздела: значение для сопоставления и новое значение, которое будет присвоено переменной, если первое значение совпадает.

Строка /old.html /index.html внутри блока map означает, что если значение $uri равно /old.html, значение $new_uri будет изменено на /index.html. Если значение не совпадает – ничего не меняется. В этом примере мы определяем только одно условие, но вы можете определить в блоке map любое количество условий.

Используя условный оператор if внутри блока server, мы проверяем, установлено ли значение переменной $new_uri. Если значение установлено, это означает, что условие блока map было выполнено, и веб-сервер должен перенаправить посетителя на новый веб-сайт с помощью команды rewrite. Ключевое слово permanent делает перенаправление постоянным (HTTP-перенаправление 301, Moved Permanently) – это означает, что старый адрес больше не действителен и не будет использоваться.

Сохраните и закройте файл.

Чтобы включить новую конфигурацию, перезапустите Nginx:

sudo systemctl restart nginx

Чтобы протестировать новую конфигурацию, выполните тот же запрос, что и раньше:

curl -L http://localhost/old.html

На этот раз в выводе не будет ошибки 404 Not Found. Вместо этого вы увидите домашнюю страницу, которую мы создали в разделе 1.

Это значит, что блок map настроен правильно, и вы можете использовать его для перенаправления URL-адресов. Позже вы сможете добавить в него и другие записи.

Перенаправление URL-адресов – одна из полезных функций модуля map. Вторая функция, которую мы рассмотрим в следующем разделе, – это фильтрация трафика на основе географического расположения посетителей.

3: Ограничение доступа к сайту

Иногда сервер может получать чрезмерное количество автоматизированных вредоносных запросов. Это может быть DDoS-атака, подбор паролей к панели администратора или попытка использовать известные уязвимости в программном обеспечении для атаки на сайт и использования его для рассылки спама или размещения другого контента.
Такие автоматические атаки могут исходить с распределенных серверов, находящихся в разных странах, что затрудняет блокировку. Один из методов смягчения последствий такой атаки – это список разрешенных стран, которые могут получить доступ к веб-сайту.

Это не идеальное решение, но в отдельных ситуациях ограничение доступа к веб-сайту по географическому положению посетителя является разумным выбором и не ограничивает аудиторию веб-сайта. Преимущество этого метода в том, что он быстрый и менее подвержен ошибкам.

Фильтрация трафика на уровне сервера происходит быстрее, чем на уровне веб-сайта, также она охватывает все запросы (включая статические файлы, например, изображения). Этот вид фильтрации также предотвращает попадание запросов непосредственно в программное обеспечение веб-сайта, что затруднит использование уязвимостей.

Чтобы использовать географическую фильтрацию, мы должны сначала установить модуль Nginx GeoIP, а также базу данных GeoIP, содержащую сопоставления между IP-адресами посетителей и странами. Для этого нужно запустить команду:

sudo apt install libnginx-mod-http-geoip geoip-database

Теперь давайте создадим новый конфигурационный файл:

sudo nano /etc/nginx/conf.d/geoip.conf

Вставьте в файл следующие строки. Эти параметры сообщат Nginx, где найти базу данных GeoIP для определения стран по IP-адресам посетителей:

# GeoIP database path
#
geoip_country /usr/share/GeoIP/GeoIP.dat; 

Следующим шагом является создание необходимой конфигурации ограничений и блока map. Откройте блок server по умолчанию:

sudo nano /etc/nginx/sites-available/default

Найдите блок server, который после изменений, внесенных в разделах 1 и 2, выглядит так:

. . .
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .

Давайте добавим два раздела: один перед блоком server и один внутри него. Раздел перед блоком – это новый блок map, который определяет действие по умолчанию (в данном случае – доступ запрещен), а также список кодов стран, которым разрешен доступ к сайту. Раздел внутри блока server запрещает доступ к сайту, если так говорит блок map.

. . .
# Default server configuration
#
# Allowed countries
#
map $geoip_country_code $allowed_country {
default no;
country_code_1 yes;
country_code_2 yes;
}
# Old website redirect map
#
map $uri $new_uri {
/old.html /index.html;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Disallow access based on GeoIP
if ($allowed_country = no) {
return 444;
}
# Old website redirect
if ($new_uri) {
rewrite ^ $new_uri permanent;
}
. . .

Сохраните и закройте файл.

Здесь в качестве заполнителей мы использовали country_code_1 и country_code_2. Замените эти условные значения двухсимвольным кодом стран, трафик из которых вы хотите разрешить. Полный список кодов стран вы найдете здесь.

В отличие от блока map, в этом блоке переменная $allowed_country всегда будет иметь какое-то значение. По умолчанию для нее установлено значение “no”; если переменная $geoip_country_code соответствует одному из кодов страны в блоке, переменной allowed_country присваивается значение yes. Если переменная $allowed_country имеет значение no, пользователь получит ответ 444 Connection Closed Without Response и не сможет попасть на сайт.

Чтобы включить новую конфигурацию, перезапустите Nginx:

sudo systemctl restart nginx

Если вы не добавили свою страну в список разрешенных, при попытке посетить http://your_server_ip вы увидите сообщение об ошибке, например The page isn’t working или The page didn’t send any data. Если вы добавили свою страну в список разрешенных, вы увидите то же, что и раньше: страницу Home.

Заключение

Модуль map не только позволяет выполнять простые сравнения, но также поддерживает регулярные выражения, благодаря чему он может обрабатывать более сложные сопоставления. Это позволяет сделать сложные конфигурационные файлы более понятными.

Более подробную информацию о модуле можно найти в официальной документации Nginx.

Читайте также: Алгоритмы выбора блоков server и location в Nginx

Tags: ,

Добавить комментарий