Перейти к содержанию

testcookie: Модуль NGINX для смягчения атак роботов

Установка

Вы можете установить этот модуль в любой дистрибутив на базе RHEL, включая, но не ограничиваясь:

  • RedHat Enterprise Linux 7, 8, 9 и 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 и Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-testcookie
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-testcookie

Включите модуль, добавив следующее в верхнюю часть файла /etc/nginx/nginx.conf:

load_module modules/ngx_http_testcookie_access_module.so;

Этот документ описывает nginx-module-testcookie v1.28, выпущенный 19 июля 2022 года.


testcookie-nginx-module — это простой модуль для смягчения атак роботов, использующий основанный на cookie метод вызова/ответа.

Cookies для вызова могут быть установлены с использованием различных методов:

  • "Set-Cookie" + 302/307 HTTP Location редирект
  • "Set-Cookie" + HTML meta refresh редирект
  • Пользовательский шаблон, здесь можно использовать JavaScript.

Чтобы предотвратить автоматический парсинг, значение cookie для вызова может быть зашифровано с помощью AES-128 в режиме CBC с использованием пользовательского/случайного ключа и iv, а затем расшифровано на стороне клиента с помощью JavaScript.

Директивы

testcookie

синтаксис: testcookie (on|off|var);

по умолчанию: off

контекст: http, server, location, if

on - Включить модуль

off - Отключить модуль

var - Не перехватывать запросы, только устанавливать переменные модуля.

testcookie_name

синтаксис: testcookie_name <строка>

по умолчанию: TCK

контекст: http, server, location

Устанавливает имя cookie.

testcookie_domain

синтаксис: testcookie_domain <строка>

по умолчанию: none, устанавливается браузером

контекст: http, server, location

Устанавливает домен cookie.

testcookie_expires

синтаксис: testcookie_expires <строка>

по умолчанию: 31 Dec 2037 23:55:55 GMT

контекст: http, server, location

Устанавливает значение истечения срока действия cookie.

testcookie_path

синтаксис: testcookie_path <строка>

по умолчанию: /

контекст: http, server, location

Устанавливает путь cookie, полезно, если вы планируете использовать разные ключи для различных локаций.

testcookie_samesite

синтаксис: testcookie_samesite <строка>

по умолчанию: None

контекст: http, server, location

Устанавливает атрибут cookie, позволяет вам указать, следует ли ограничить ваш cookie контекстом первого лица или того же сайта. По умолчанию None (Cookies будут отправляться во всех контекстах, т.е. отправка кросс-домена разрешена). Принимает значения: Lax, Strict, None.

testcookie_secret

синтаксис: testcookie_secret <строка>

по умолчанию: обязательная директива конфигурации

контекст: http, server, location

Секретная строка, используемая в вычислении cookie для вызова, должна быть 32 байта или более, лучше, чтобы она была длинной, но статической, чтобы предотвратить сброс cookie для законных пользователей при каждом перезапуске сервера. Если установлено "random" - новый секрет будет генерироваться при каждом перезапуске сервера, не рекомендуется (все cookie с предыдущим ключом будут недействительными).

testcookie_session

синтаксис: testcookie_session <переменная>

по умолчанию: обязательная директива конфигурации

контекст: http, server, location

Устанавливает входные данные для функции генерации вызова, * $remote_addr - IP-адрес клиента будет использоваться как уникальный идентификатор пользователя * $remote_addr$http_user_agent - IP клиента + User-Agent

testcookie_arg

синтаксис: testcookie_arg <строка>

по умолчанию: none

контекст: http, server, location

Устанавливает имя GET параметра, используемого для вычисления попыток установки cookie.

Если не установлено - сервер будет пытаться устанавливать cookie бесконечно.

testcookie_max_attempts

синтаксис: testcookie_max_attempts <целое число>

по умолчанию: 5

контекст: http, server, location

Устанавливает максимальное количество редиректов, прежде чем пользователь будет отправлен на резервный URL, согласно RFC1945 не может быть более 5.

Если установлено в 0 - сервер будет пытаться устанавливать cookie бесконечно (на самом деле браузер покажет страницу с ошибкой).

testcookie_p3p

синтаксис: testcookie_p3p <строка>

по умолчанию: none

контекст: http, server, location

Устанавливает политику P3P.

testcookie_fallback

синтаксис: testcookie_fallback <скрипт>

по умолчанию: none

контекст: http, server, location

Устанавливает резервный URL, на который пользователь будет перенаправлен после превышения максимального количества попыток, указанного директивой testcookie_max_attempts. Здесь можно использовать переменные скрипта Nginx. Если не установлено - клиент получит 403 после достижения максимального количества попыток.

testcookie_whitelist

синтаксис: testcookie_whitelist <список сетей>

по умолчанию: none

контекст: http, server

Устанавливает сети, для которых тестирование не будет использоваться, добавьте сюда сети поисковых систем. В настоящее время только IPv4 CIDR.

testcookie_pass

синтаксис: testcookie_pass $variable;

по умолчанию: none

контекст: http, server

Устанавливает имя переменной для проверки, следует ли обойти проверку cookie. Если значение переменной установлено в 1 во время запроса - проверка cookie не будет выполнена. Может использоваться для более сложного белого списка.

testcookie_redirect_via_refresh

синтаксис: testcookie_redirect_via_refresh (on|off);

по умолчанию: off

контекст: http, server, location

Установите cookie и перенаправьте с использованием HTTP meta refresh, требуется, если используется testcookie_refresh_template.

testcookie_refresh_template

синтаксис: testcookie_refresh_template <строка>

по умолчанию: none

контекст: http, server, location

Используйте пользовательский html вместо простого HTTP meta refresh, вам нужно вручную установить cookie из шаблона. Доступны все переменные nginx и

$testcookie_nexturl - URL, на который клиент должен быть перенаправлен, если превышено значение *testcookie_fallback*
$testcookie_got - значение cookie, полученное от клиента, пусто, если cookie нет или оно не соответствует формату
$testcookie_set - правильное значение cookie, которое мы ожидаем от клиента
$testcookie_ok - пользователь прошел тест (1 - прошел, 0 - не прошел) Примечание: изменено с "yes"/"no" в v1.10

Также, если testcookie_refresh_encrypt_cookie включен, есть три дополнительные переменные:

$testcookie_enc_key - ключ шифрования (32 шестнадцатеричных цифры)
$testcookie_enc_iv - вектор инициализации шифрования (32 шестнадцатеричных цифры)
$testcookie_enc_sec - зашифрованное значение cookie (32 шестнадцатеричных цифры)

testcookie_refresh_status

синтаксис: testcookie_refresh_status <код>

по умолчанию: 200

контекст: http, server, location

Используйте пользовательский HTTP статус-код при обслуживании html.

testcookie_deny_keepalive

синтаксис: testcookie_deny_keepalive (on|off);

по умолчанию: off

контекст: http, server, location

Закройте соединение сразу после установки cookie, нет смысла поддерживать соединения с ботами.

testcookie_get_only

синтаксис: testcookie_get_only (on|off);

по умолчанию: off

контекст: http, server, location

Обрабатывайте только GET запросы, POST запросы будут пропущены.

testcookie_https_location

синтаксис: testcookie_https_location (on|off);

по умолчанию: off

контекст: http, server, location

Перенаправьте клиента на https протокол после установки cookie, также влияет на $testcookie_nexturl, полезно с 3dparty SSL offload.

синтаксис: testcookie_refresh_encrypt_cookie (on|off);

по умолчанию: off

контекст: http, server, location

Шифрует переменную cookie, используется с testcookie_refresh_template для принудительного расшифрования на стороне клиента с помощью AES-128 CBC.

синтаксис: testcookie_refresh_encrypt_cookie_key <32 шестнадцатеричных цифр|random>

по умолчанию: обязательная директива, если шифрование включено

контекст: http, server, location

Устанавливает ключ шифрования.

Возможные значения:

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

testcookie_refresh_encrypt_iv

синтаксис: testcookie_refresh_encrypt_iv <32 шестнадцатеричных цифр|random|random2>

по умолчанию: random

контекст: http, server, location

Устанавливает вектор инициализации шифрования.

Возможные значения: random - новый iv генерируется для каждого клиентского запроса random2 - новый iv генерируется при каждом перезапуске nginx 32 шестнадцатеричных цифры - статический iv, полезный, если вы планируете скрыть его глубоко в клиентском JavaScript

testcookie_internal

синтаксис: testcookie_internal (on|off);

по умолчанию: off

контекст: http, server, location

Включите проверку testcookie для внутренних редиректов (по умолчанию отключена для оптимизации!), полезно для такого типа конфигураций:

rewrite ^/(.*)$ /index.php?$1 last;

testcookie_httponly_flag

синтаксис: testcookie_httponly_flag (on|off);

по умолчанию: off

контекст: http, server, location

Включите флаг HttpOnly для cookie.

testcookie_secure_flag

синтаксис: testcookie_secure_flag (on|off|$variable);

по умолчанию: on

контекст: http, server, location

Включите флаг Secure для cookie. Любое значение переменной, кроме "on", интерпретируется как False.

testcookie_port_in_redirect

синтаксис: testcookie_port_in_redirect (on|off);

по умолчанию: off

контекст: http, server, location

Укажите порт в редиректе.

Пример конфигурации

http {
    #стандартная конфигурация, модуль отключен
    testcookie off;

    #установка имени cookie
    testcookie_name BPC;

    #установка секрета
    testcookie_secret keepmesecret;

    #установка ключа сессии
    testcookie_session $remote_addr;

    #установка имени аргумента
    testcookie_arg ckattempt;

    #установка максимального количества попыток установки cookie
    testcookie_max_attempts 3;

    #установка политики p3p
    testcookie_p3p 'CP="CUR ADM OUR NOR STA NID", policyref="/w3c/p3p.xml"';

    #установка резервного URL
    testcookie_fallback http://google.com/cookies.html?backurl=http://$host$request_uri;

    #конфигурирование белого списка
    testcookie_whitelist {
        8.8.8.8/32;
    }

    #установка редиректа через html код
    testcookie_redirect_via_refresh on;

    #включение шифрования
    testcookie_refresh_encrypt_cookie on;

    #установка ключа шифрования
    testcookie_refresh_encrypt_cookie_key deadbeefdeadbeefdeadbeefdeadbeef;

    #установка вектора инициализации шифрования
    testcookie_refresh_encrypt_cookie_iv deadbeefdeadbeefdeadbeefdeadbeef;

    #установка шаблона ответа
    testcookie_refresh_template '<html><body>setting cookie...<script type=\"text/javascript\" src=\"/aes.min.js\" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("$testcookie_enc_key"),b=toNumbers("$testcookie_enc_iv"),c=toNumbers("$testcookie_enc_set");document.cookie="BPC="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";location.href="$testcookie_nexturl";</script></body></html>';

    server {
        listen 80;
        server_name test.com;

        location = /aes.min.js {
            gzip  on;
            gzip_min_length 1000;
            gzip_types      text/plain;
            root /var/www/public_html;
        }

        location = /w3c/p3p.xml {
            root /var/www/public_html;
        }

        location / {
            #включить модуль для конкретной локации
            testcookie on;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:80;
        }
    }
}

Смотрите больше случаев в директории "docs" проекта.

Тестовый набор

Этот модуль поставляется с тестовым набором на Perl. Благодаря модулю Test::Nginx в мире Perl.

Исходные коды

Доступно на github по адресу kyprizel/testcookie-nginx-module.

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-testcookie.