Настройка страницы блокировки и кода ошибки (NGINX)¶
Данная инструкция описывает способ настройки страницы и кода ошибки, которые возвращаются клиенту в ответ на запрос, заблокированный по следующим причинам:
-
В запросе обнаружены признаки атак на проверку входных данных, атак типа vpatch или атак на основе регулярных выражений, и WAF‑нода работает в режиме блокировки.
-
Запрос с признаками атак из списка выше отправлен с IP-адреса из серого списка, и WAF‑нода работает в режиме мягкой блокировки.
-
Запрос отправлен с IP-адреса из черного списка.
Ограничения настройки¶
Настройка страницы блокировки и кода ошибки поддерживается во всех формах деплоя WAF-ноды на основе NGINX.
Способы настройки¶
По умолчанию, в ответ на заблокированный запрос возвращаются код ошибки 403 и стандартная страница блокировки NGINX. Вы можете изменить настройки по умолчанию, используя следующие директивы NGINX:
-
wallarm_block_page
-
wallarm_block_page_add_dynamic_path
Директива NGINX wallarm_block_page
¶
В директиве wallarm_block_page
можно передать следующие параметры страницы блокировки и кода ошибки:
-
Путь до HTM- или HTML-файла со страницей блокировки. В качестве страницы блокировки вы можете использовать как собственную страницу, так и страницу, которую предоставляет Вебмониторэкс.
-
Текст сообщения, который необходимо вернуть в ответе на заблокированный запрос.
-
URL, на который необходимо перенаправить клиента.
-
respose_code
: код ответа на заблокированный запрос. -
type
: тип заблокированного запроса, в ответе на который необходимо вернуть заданную конфигурацию. Параметр может принимать одно или несколько значений (через запятую) из списка:attack
(по умолчанию): для запросов с признаками атак, которые были заблокированы WAF-нодой в режиме блокировки или мягкой блокировки (при условии, что источник запроса добавлен в серый список).acl_ip
: для запросов с IP-адресов, которые добавлены в черный список как одиночные адреса или в составе подсети.acl_source
: для запросов с IP-адресов, которые зарегистрированы в стране, регионе или дата-центре из черного списка.
Перечисленные параметры можно задать в директиве wallarm_block_page
следующими способами:
-
Путь до HTM- или HTML-файла со страницей блокировки, код ошибки (опционально) и тип заблокированного запроса (опционально)
wallarm_block_page &/<PATH_TO_FILE/HTML_HTM_FILE_NAME> response_code=<CUSTOM_CODE> type=<BLOCKED_REQUEST_TYPE>;
Вы можете использовать переменные NGINX на странице блокировки. Для этого вставьте в код страницы имя переменной в
{}
, начиная с символа$
. Например,${remote_addr}
отобразит на странице блокировки IP‑адрес, с которого отправлен запрос.Вебмониторэкс предоставляет пример страницы блокировки. Чтобы ее использовать, необходимо скопировать пример и задать в директиве путь к копии.
Важная информация для пользователей Debian и CentOS
Если вы используете NGINX версии ниже 1.11, установленный из репозиториев CentOS/Debian, для корректного отображения страницы блокировки необходимо удалить из кода страницы переменную
request_id
:
UUID ${request_id}
Удаление переменной требуется при использовании как собственного шаблона динамической страницы, так и
wallarm_blocked.html
. -
URL для перенаправления клиента и тип заблокированного запроса (опционально)
wallarm_block_page /<REDIRECT_URL> type=<BLOCKED_REQUEST_TYPE>;
-
Именованный
location
NGINX и тип заблокированного запроса (опционально)wallarm_block_page @<NAMED_LOCATION> type=<BLOCKED_REQUEST_TYPE>;
-
Переменная, в которой будет передан путь до HTM- или HTML-файла со страницей блокировки, код ошибки (опционально) и тип заблокированного запроса (опционально)
wallarm_block_page &<VARIABLE_NAME> response_code=<CUSTOM_CODE> type=<BLOCKED_REQUEST_TYPE>;
Инициализация страницы блокировки с переменными NGINX
Если вы задаете страницу блокировки через переменную и внутри страницы блокировки также используются переменные NGINX, необходимо инициализировать страницу блокировки с переменными с помощью директивы
wallarm_block_page_add_dynamic_path
.
Директива wallarm_block_page
может быть передана в блоках http
, server
, location
конфигурационного файла NGINX.
Директива NGINX wallarm_block_page_add_dynamic_path
¶
Директива wallarm_block_page_add_dynamic_path
используется для инициализации страницы блокировки, если внутри страницы используются переменные NGINX и путь до страницы блокировки также задан с помощью переменной. В остальных случаях директива не используется.
Директива wallarm_block_page_add_dynamic_path
может быть передана только в блоке http
конфигурационного файла NGINX.
Кастомизация примера страницы блокировки¶
Вебмониторэкс предоставляет пример страницы блокировки, он доступен по путям /usr/share/nginx/html/wallarm_blocked.html
, /opt/wallarm/usr/share/nginx/html/wallarm_blocked.html
и выглядит следующим образом:
Вы можете скопировать пример и кастомизировать его следующим образом:
-
Добавить логотип вашей компании – по умолчанию логотипа на странице нет.
-
Преобразовать фразу
contact us
в ссылку на электронную почту вашей службы поддержки – по умолчанию данная фраза является обычным текстом. -
Изменить любые представленные элементы HTML или добавить собственные.
Варианты создания собственной страницы
Вместо модификации примера страницы блокировки Вебмониторэкс, вы можете создать собственную страницу с нуля.
Порядок действий¶
Если вы будете изменять саму страницу-пример, внесенные изменения могут быть потеряны при обновлении компонентов Вебмониторэкс. Поэтому рекомендуется скопировать страницу-пример, дать копии новое имя и кастомизировать ее. Необходимые для кастомизации шаги для разных вариантов установки описаны в разделах ниже.
Страница-пример для копирования
Вы можете скопировать страницу-пример /usr/share/nginx/html/wallarm_blocked.html
из исходных файлов ноды или из блока ниже:
Показать код страницы-примера
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>You are blocked</title>
<link href="https://fonts.googleapis.com/css?family=Poppins:700|Roboto|Roboto+Mono&display=swap" rel="stylesheet">
<style>
html {
font-family: 'Roboto', sans-serif;
}
body {
margin: 0;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
min-height: 100%;
}
.logo {
margin-top: 32px;
}
.message {
display: flex;
margin-bottom: 100px;
}
.alert {
padding-top: 20px;
width: 246px;
text-align: center;
}
.alert-title {
font-family: 'Poppins', sans-serif;
font-weight: bold;
font-size: 24px;
line-height: 32px;
}
.alert-desc {
font-size: 14px;
line-height: 20px;
}
.info {
margin-left: 76px;
border-left: 1px solid rgba(149, 157, 172, 0.24);
padding: 20px 0 20px 80px;
width: 340px;
}
.info-title {
font-weight: bold;
font-size: 20px;
line-height: 28px;
}
.info-text {
margin-top: 8px;
font-size: 14px;
line-height: 20px;
}
.info-divider {
margin-top: 16px;
}
.info-data {
margin-top: 12px;
border: 1px solid rgba(149, 157, 172, 0.24);
border-radius: 4px;
padding: 9px 12px;
font-size: 14px;
line-height: 20px;
font-family: 'Roboto Mono', monospace;
}
.info-copy {
margin-top: 12px;
padding: 6px 12px;
border: none;
outline: none;
background: rgba(149, 157, 172, 0.08);
cursor: pointer;
transition: 0.24s cubic-bezier(0.24, 0.1, 0.24, 1);
border-radius: 4px;
font-size: 14px;
line-height: 20px;
}
.info-copy:hover {
background-color: rgba(149, 157, 172, 0.24);
}
.info-copy:active {
background-color: rgba(149, 157, 172, 0.08);
}
.info-mailto,
.info-mailto:visited {
color: #fc7303;
}
</style>
<script>
// Place your support email here
const SUPPORT_EMAIL = "";
</script>
</head>
<body>
<div class="content">
<div id="logo" class="logo">
<!--
Place you logo here.
You can use an external image:
<img src="https://example.com/logo.png" width="160" alt="Company Name" />
Or put your logo source code (like svg) right here:
<svg width="160" height="80"> ... </svg>
-->
</div>
<div class="message">
<div class="alert">
<svg width="207" height="207" viewBox="0 0 207 207" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M88.7512 33.2924L15.6975 155.25C14.1913 157.858 13.3943 160.816 13.3859 163.828C13.3775 166.84 14.1579 169.801 15.6494 172.418C17.141 175.035 19.2918 177.216 21.8877 178.743C24.4837 180.271 27.4344 181.092 30.4462 181.125H176.554C179.566 181.092 182.516 180.271 185.112 178.743C187.708 177.216 189.859 175.035 191.351 172.418C192.842 169.801 193.623 166.84 193.614 163.828C193.606 160.816 192.809 157.858 191.303 155.25L118.249 33.2924C116.711 30.7576 114.546 28.6618 111.963 27.2074C109.379 25.7529 106.465 24.9888 103.5 24.9888C100.535 24.9888 97.6206 25.7529 95.0372 27.2074C92.4538 28.6618 90.2888 30.7576 88.7512 33.2924V33.2924Z"
stroke="#F24444" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
<path d="M103.5 77.625V120.75" stroke="#F24444" stroke-width="16" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M103.5 146.625V146.668" stroke="#F24444" stroke-width="16" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
<div class="alert-title">Malicious activity blocked</div>
<div class="alert-desc">Your request is blocked since it was identified as a malicious one.</div>
</div>
<div class="info">
<div class="info-title">Why it happened</div>
<div class="info-text">
You might have used symbols similar to a malicious code sequence, or uploaded a specific file.
</div>
<div class="info-divider"></div>
<div class="info-title">What to do</div>
<div class="info-text">
If your request is considered to be legitimate, please <a id="mailto" href="" class="info-mailto">contact us</a> and provide your last action description and the following data:
</div>
<div id="data" class="info-data">
IP ${remote_addr}<br />
Blocked on ${time_iso8601}<br />
UUID ${request_id}
</div>
<button id="copy-btn" class="info-copy">
Copy details
</button>
</div>
</div>
<div></div>
</div>
<script>
// Warning: ES5 code only
function writeText(str) {
const range = document.createRange();
function listener(e) {
e.clipboardData.setData('text/plain', str);
e.preventDefault();
}
range.selectNodeContents(document.body);
document.getSelection().addRange(range);
document.addEventListener('copy', listener);
document.execCommand('copy');
document.removeEventListener('copy', listener);
document.getSelection().removeAllRanges();
}
function copy() {
const text = document.querySelector('#data').innerText;
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text);
}
return writeText(text);
}
document.querySelector('#copy-btn').addEventListener('click', copy);
const mailto = document.getElementById('mailto');
if (SUPPORT_EMAIL) mailto.href = `mailto:${wallarm_dollar}{SUPPORT_EMAIL}`;
else mailto.replaceWith(mailto.textContent);
</script>
</body>
Пакеты DEB/RPM
Скопируйте страницу-пример /usr/share/nginx/html/wallarm_blocked.html
под новым именем в ту же или любую другую директорию, где NGINX имеет права на чтение.
Docker-контейнер
Для загрузки кастомизированной страницы-примера или собственной страницы в Docker-контейнер с нодой, вы можете использовать опцию Docker bind mount. Технология позволяет скопировать страницу блокировки и конфигурационный файл NGINX с вашей машины в контейнер. Созданные копии связываются ссылками с оригинальными файлами, так что при изменении оригинальных файлов копии в контейнере также изменяются и наоборот.
Для кастомизации страницы блокировки:
-
До первого запуска контейнера подготовьте кастомизированную страницу
wallarm_blocked_renamed.html
. -
Подготовьте конфигурационный файл NGINX с путем к вашей странице. Смотрите пример конфигурации.
-
Примонтируйте подготовленную страницу блокировки и конфигурационный файл NGINX в контейнер при его запуске.
-
Если позднее вам понадобится обновить страницу блокировки в запущенном контейнере, на вашей машине обновите
wallarm_blocked_renamed.html
, затем перезапустите NGINX в контейнере.
Ingress-контроллер
Для кастомизации страницы блокировки:
-
Подготовьте кастомизированную страницу
wallarm_blocked_renamed.html
. -
Создайте ConfigMap из файла
wallarm_blocked_renamed.html
. -
Примонтируйте созданный ConfigMap в pod с Ingress‑контроллером Вебмониторэкс. Для этого необходимо изменить объект Deployment Ingress‑контроллера Вебмониторэкс по инструкции.
Директория для монтирования ConfigMap
Рекомендуется использовать отдельную директорию для файлов, примонтированных с помощью ConfigMap. При монтировании файлов в существующую директорию, предыдущие файлы в этой директории могут быть удалены.
-
Настройте pod для использования страницы блокировки путем добавления аннотации к Ingress:
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/wallarm-block-page="<PAGE_ADDRESS>"
Стандартные элементы для кастомизации¶
Чтобы добавить логотип вашей компании, снимите комментарии и задайте путь до логотипа в следующей секции файла wallarm_blocked_renamed.html
:
<div class="content">
<div id="logo" class="logo">
<!--
Place you logo here.
You can use an external image:
<img src="https://example.com/logo.png" width="160" alt="Company Name" />
Or put your logo source code (like svg) right here:
<svg width="160" height="80"> ... </svg>
-->
</div>
Чтобы преобразовать фразу contact us
в ссылку на электронную почту, задайте в файле wallarm_blocked_renamed.html
значение переменной SUPPORT_EMAIL
:
<script>
// Place your support email here
const SUPPORT_EMAIL = "support@company.com";
</script>
Примеры настройки¶
Ниже приведены примеры настройки страницы блокировки и кода ошибки через директивы wallarm_block_page
и wallarm_block_page_add_dynamic_path
.
В каждом примере в явном виде передается параметр type
с типом запроса, в ответе на который возвращается заданная конфигурация. Если требуется, вы можете удалить параметр type
. Тогда заданная конфигурация вернется только в ответе на запросы с признаками атак, заблокированные в режиме блокировки или мягкой блокировки (при условии, что источник запроса добавлен в серый список).
Путь до HTM- или HTML-файла со страницей блокировки и код ошибки¶
В примере приведены настройки для возвращения клиенту:
-
Кастомизированной страницы-примера блокировки
/usr/share/nginx/html/wallarm_blocked_renamed.html
и кода ошибки 445 в ответ на запрос, заблокированный WAF-нодой в режиме блокировки или мягкой блокировки (при условии, что источник запроса добавлен в серый список). -
Собственной страницы блокировки
/usr/share/nginx/html/block.html
и кода ошибки 445 в ответ на запрос, отправленный с любого IP-адреса из черного списка.
Конфигурационный файл NGINX¶
wallarm_block_page &/usr/share/nginx/html/wallarm_blocked_renamed.html response_code=445 type=attack;
wallarm_block_page &/usr/share/nginx/html/block.html response_code=445 type=acl_ip,acl_source;
Чтобы применить настройку к Docker-контейнеру, необходимо примонтировать в контейнер конфигурационный файл NGINX с необходимыми настройками, а также страницы wallarm_blocked_renamed.html
и block.html
. Запуск контейнера с примонтированным конфигурационным файлом →
Аннотация Ingress¶
Перед добавлением аннотации Ingress, необходимо:
-
Создать ConfigMap из файлов
wallarm_blocked_renamed.html
иblock.html
. -
Примонтировать созданный ConfigMap в pod с Ingress‑контроллером Вебмониторэкс. Для этого необходимо изменить объект Deployment Ingress‑контроллера Вебмониторэкс по инструкции.
Директория для монтирования ConfigMap
Рекомендуется использовать отдельную директорию для файлов, примонтированных с помощью ConfigMap. При монтировании файлов в существующую директорию, предыдущие файлы в этой директории могут быть удалены.
Аннотация Ingress:
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/wallarm-block-page="&/usr/share/nginx/html/wallarm_blocked_renamed.html response_code=445 type=attack;&/usr/share/nginx/html/block.html response_code=445 type=acl_ip,acl_source"
Аннотации пода приложения (если установлен Sidecar-контроллера)¶
Страницу блокировку можно настроить на уровне пода приложения с помощью аннотации sidecar.wallarm.io/wallarm-block-page
, например:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
wallarm-sidecar: enabled
annotations:
sidecar.wallarm.io/wallarm-mode: block
sidecar.wallarm.io/wallarm-block-page: "&/path/to/block/page1.html response_code=403 type=attack;&/path/to/block/page2.html response_code=403 type=acl_ip,acl_source"
spec:
containers:
- name: application
image: kennethreitz/httpbin
ports:
- name: http
containerPort: 80
URL для перенаправления клиента¶
В примере приведены настройки для перенаправления клиента на страницу host/err445
, если запрос отправлен с IP-адреса, который зарегистрирован в стране, регионе или дата-центре из черного списка.
Конфигурационный файл NGINX¶
wallarm_block_page /err445 type=acl_source;
Чтобы применить настройку к Docker-контейнеру, необходимо примонтировать в контейнер конфигурационный файл NGINX с необходимыми настройками. Запуск контейнера с примонтированным конфигурационным файлом →
Аннотация Ingress¶
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/wallarm-block-page="/err445 type=acl_source"
Именованный location
NGINX¶
В примере приведены настройки для возвращения клиенту сообщения The page is blocked
и кода ошибки 445 вне зависимости от причины блокировки запроса (режим блокировки, режим мягкой блокировки и источник из серого списка или источник из черного списка).
Конфигурационный файл NGINX¶
wallarm_block_page @block type=attack,acl_ip,acl_source;
location @block {
return 445 'The page is blocked';
}
Чтобы применить настройку к Docker-контейнеру, необходимо примонтировать в контейнер конфигурационный файл NGINX с необходимыми настройками. Запуск контейнера с примонтированным конфигурационным файлом →
Аннотация Ingress¶
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/server-snippet="location @block {return 445 'The page is blocked';}"
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/wallarm-block-page="@block type=attack,acl_ip,acl_source"
Переменная и код ошибки¶
В зависимости от значения заголовка User-Agent
, клиенту, который отправил запрос с одиночного IP-адреса или подсети из черого списка, возвращаются разные страницы блокировки:
-
По умолчанию — кастомизированная страницы-примера блокировки
/usr/share/nginx/html/wallarm_blocked_renamed.html
. Страница содержит переменные NGINX, поэтому ее необходимо инициализировать в директивеwallarm_block_page_add_dynamic_path
. -
Для пользователей Firefox —
/usr/share/nginx/html/block_page_firefox.html
(при установке Ingress‑контроллера рекомендуется создать отдельную директорию для примонтированных файлов, например,/usr/custom-block-pages/block_page_firefox.html
):You are blocked! IP ${remote_addr} Blocked on ${time_iso8601} UUID ${request_id}
Страница содержит переменные NGINX, поэтому ее необходимо инициализировать в директиве
wallarm_block_page_add_dynamic_path
. -
Для пользователей Chrome —
/usr/share/nginx/html/block_page_chrome.html
(при установке Ingress‑контроллера рекомендуется создать отдельную директорию для примонтированных файлов, например,/usr/custom-block-pages/block_page_chrome.html
):You are blocked!
Страница не содержит переменные NGINX, поэтому ее не нужно инициализировать.
Также, вне зависимости от значения заголовка User-Agent
, возвращается код 445.
Конфигурационный файл NGINX¶
wallarm_block_page_add_dynamic_path /usr/share/nginx/html/block_page_firefox.html /usr/share/nginx/html/wallarm_blocked_renamed.html;
map $http_user_agent $block_page {
"~Firefox" &/usr/share/nginx/html/block_page_firefox.html;
"~Chrome" &/usr/share/nginx/html/block_page_chrome.html;
default &/usr/share/nginx/html/wallarm_blocked_renamed.html;
}
wallarm_block_page $block_page response_code=445 type=acl_ip;
Чтобы применить настройку к Docker-контейнеру, необходимо примонтировать в контейнер конфигурационный файл NGINX с необходимыми настройками, а также страницы wallarm_blocked_renamed.html
, block_page_firefox.html
и block_page_chrome.html
. Запуск контейнера с примонтированным конфигурационным файлом →
Ingress‑контроллер¶
-
Передать в развернутый Helm‑чарт параметр
controller.config.http-snippet
, используя командуhelm upgrade
:helm upgrade --reuse-values --set controller.config.http-snippet='wallarm_block_page_add_dynamic_path /usr/custom-block-pages/block_page_firefox.html /usr/share/nginx/html/wallarm_blocked_renamed.html; map $http_user_agent $block_page { "~Firefox" &/usr/custom-block-pages/block_page_firefox.html; "~Chrome" &/usr/custom-block-pages/block_page_chrome.html; default &/usr/share/nginx/html/wallarm_blocked_renamed.html;}' <INGRESS_CONTROLLER_NAME> wallarm/wallarm-ingress -n <KUBERNETES_NAMESPACE>
-
Создать ConfigMap из файлов
wallarm_blocked_renamed.html
,block_page_firefox.html
иblock_page_chrome.html
. -
Примонтировать созданный ConfigMap в pod с Ingress‑контроллером Вебмониторэкс. Для этого необходимо изменить объект Deployment Ingress‑контроллера Вебмониторэкс по инструкции.
Директория для монтирования ConfigMap
Рекомендуется использовать отдельную директорию для файлов, примонтированных с помощью ConfigMap. При монтировании файлов в существующую директорию, предыдущие файлы в этой директории могут быть удалены.
-
Добавить аннотацию к Ingress:
kubectl annotate ingress <INGRESS_NAME> nginx.ingress.kubernetes.io/wallarm-block-page='$block_page response_code=445 type=acl_ip'