Saltar a contenido

testcookie: Módulo de mitigación de robots testcookie de NGINX

Instalación

Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:

  • RedHat Enterprise Linux 7, 8, 9 y 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 y 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

Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:

load_module modules/ngx_http_testcookie_access_module.so;

Este documento describe nginx-module-testcookie v1.28 lanzado el 19 de julio de 2022.


testcookie-nginx-module es un módulo simple de mitigación de robots que utiliza un desafío/respuesta basado en cookies.

Las cookies de desafío se pueden establecer utilizando diferentes métodos:

  • "Set-Cookie" + redirección HTTP 302/307 Location
  • "Set-Cookie" + redirección HTML meta refresh
  • Plantilla personalizada, se puede usar JavaScript aquí.

Para prevenir el análisis automático, el valor de la cookie de desafío se puede cifrar con AES-128 en modo CBC utilizando una clave y un iv personalizados/aleatorios, y luego descifrado en el lado del cliente con JavaScript.

Directivas

testcookie

sintaxis: testcookie (on|off|var);

predeterminado: off

contexto: http, server, location, if

on - Habilitar módulo

off - Deshabilitar módulo

var - No interceptar solicitudes, solo establecer variables del módulo.

testcookie_name

sintaxis: testcookie_name <string>

predeterminado: TCK

contexto: http, server, location

Establece el nombre de la cookie.

testcookie_domain

sintaxis: testcookie_domain <string>

predeterminado: none, establecido por el navegador

contexto: http, server, location

Establece el dominio de la cookie.

testcookie_expires

sintaxis: testcookie_expires <string>

predeterminado: 31 Dec 2037 23:55:55 GMT

contexto: http, server, location

Establece el valor de expiración de la cookie.

testcookie_path

sintaxis: testcookie_path <string>

predeterminado: /

contexto: http, server, location

Establece la ruta de la cookie, útil si planeas usar diferentes claves para ubicaciones.

testcookie_samesite

sintaxis: testcookie_samesite <string>

predeterminado: None

contexto: http, server, location

Establece el atributo de la cookie, te permite declarar si tu cookie debe estar restringida a un contexto de primer partido o de mismo sitio. El valor predeterminado es None (Las cookies se enviarán en todos los contextos, es decir, se permite el envío entre orígenes). Acepta valores: Lax, Strict, None.

testcookie_secret

sintaxis: testcookie_secret <string>

predeterminado: directiva de configuración requerida

contexto: http, server, location

Cadena secreta, utilizada en el cálculo de la cookie de desafío, debe tener 32 bytes o más, es mejor que sea larga pero estática para prevenir el restablecimiento de cookies para usuarios legítimos en cada reinicio del servidor. Si se establece en "random" - se generará un nuevo secreto en cada reinicio del servidor, no recomendado (todas las cookies con la clave anterior serán inválidas).

testcookie_session

sintaxis: testcookie_session <variable>

predeterminado: directiva de configuración requerida

contexto: http, server, location

Establece la entrada de la función de generación de desafíos, * $remote_addr - la dirección IP del cliente se utilizará como un identificador único de usuario * $remote_addr$http_user_agent - IP del cliente + User-Agent

testcookie_arg

sintaxis: testcookie_arg <string>

predeterminado: none

contexto: http, server, location

Establece el nombre del parámetro GET, utilizado para el cálculo de intentos de establecimiento de cookies,

Si no se establece - el servidor intentará establecer la cookie infinitamente.

testcookie_max_attempts

sintaxis: testcookie_max_attempts <integer>

predeterminado: 5

contexto: http, server, location

Establece el número máximo de redirecciones antes de que el usuario sea enviado a la URL de respaldo, de acuerdo con RFC1945 no puede ser más de 5.

Si se establece en 0 - el servidor intentará establecer la cookie infinitamente (en realidad, el navegador mostrará la página de error).

testcookie_p3p

sintaxis: testcookie_p3p <string>

predeterminado: none

contexto: http, server, location

Establece la política P3P.

testcookie_fallback

sintaxis: testcookie_fallback <script>

predeterminado: none

contexto: http, server, location

Establece la URL de respaldo, a la que el usuario será redirigido después de que se exceda el número máximo de intentos, especificado por la directiva testcookie_max_attempts. Se pueden usar variables de scripting de Nginx aquí. Si no se establece - el cliente recibirá un 403 después de alcanzar el máximo de intentos.

testcookie_whitelist

sintaxis: testcookie_whitelist <network list>

predeterminado: none

contexto: http, server

Establece las redes para las cuales no se utilizará la prueba, agrega aquí redes de motores de búsqueda. Actualmente solo IPv4 CIDR.

testcookie_pass

sintaxis: testcookie_pass $variable;

predeterminado: none

contexto: http, server

Establece el nombre de la variable para probar si se debe omitir la verificación de la cookie. Si el valor de la variable se establece en 1 durante la solicitud - no se realizará la verificación de la cookie. Se puede usar para listas blancas más complejas.

testcookie_redirect_via_refresh

sintaxis: testcookie_redirect_via_refresh (on|off);

predeterminado: off

contexto: http, server, location

Establece la cookie y redirige utilizando una meta refresh HTTP, requerido si se utiliza testcookie_refresh_template.

testcookie_refresh_template

sintaxis: testcookie_refresh_template <string>

predeterminado: none

contexto: http, server, location

Utiliza HTML personalizado en lugar de una simple meta refresh HTTP, necesitas establecer la cookie manualmente desde la plantilla. Disponibles todas las variables de nginx y

$testcookie_nexturl - URL a la que el cliente debe ser redirigido, si se excede *testcookie_max_attempts* aquí estará el valor de *testcookie_fallback*
$testcookie_got - valor de la cookie recibido del cliente, vacío si no hay cookie o no coincide con el formato
$testcookie_set - valor correcto de la cookie que esperamos del cliente
$testcookie_ok - el usuario pasó la prueba (1 - pasado, 0 - no pasado) Nota: cambiado de "yes"/"no" en v1.10

Además, si testcookie_refresh_encrypt_cookie está habilitado, hay tres variables más:

$testcookie_enc_key - clave de cifrado (32 dígitos hexadecimales)
$testcookie_enc_iv - iv de cifrado (32 dígitos hexadecimales)
$testcookie_enc_sec - valor de cookie cifrado (32 dígitos hexadecimales)

testcookie_refresh_status

sintaxis: testcookie_refresh_status <code>

predeterminado: 200

contexto: http, server, location

Utiliza un código de estado HTTP personalizado al servir HTML.

testcookie_deny_keepalive

sintaxis: testcookie_deny_keepalive (on|off);

predeterminado: off

contexto: http, server, location

Cierra la conexión justo después de establecer la cookie, no hay razón para mantener conexiones con bots.

testcookie_get_only

sintaxis: testcookie_get_only (on|off);

predeterminado: off

contexto: http, server, location

Procesa solo solicitudes GET, las solicitudes POST serán omitidas.

testcookie_https_location

sintaxis: testcookie_https_location (on|off);

predeterminado: off

contexto: http, server, location

Redirige al cliente al protocolo https después de establecer la cookie, también afecta a $testcookie_nexturl, útil con la descarga SSL de terceros.

sintaxis: testcookie_refresh_encrypt_cookie (on|off);

predeterminado: off

contexto: http, server, location

Cifra la variable de la cookie, utilizada con testcookie_refresh_template para forzar el descifrado del lado del cliente con AES-128 CBC.

sintaxis: testcookie_refresh_encrypt_cookie_key <32 hex digits|random>

predeterminado: directiva requerida si se habilita el cifrado

contexto: http, server, location

Establece la clave de cifrado.

Valores posibles:

random - nueva clave generada en cada reinicio de nginx
32 hex digits - clave estática, útil si planeas ofuscarla profundamente en JavaScript del lado del cliente.

testcookie_refresh_encrypt_iv

sintaxis: testcookie_refresh_encrypt_iv <32 hex digits|random|random2>

predeterminado: random

contexto: http, server, location

Establece el iv de cifrado.

Valores posibles: random - nuevo iv generado para cada solicitud del cliente random2 - nuevo iv generado para cada reinicio de nginx 32 hex digits - iv estático, útil si planeas ofuscarlo profundamente en JavaScript del lado del cliente.

testcookie_internal

sintaxis: testcookie_internal (on|off);

predeterminado: off

contexto: http, server, location

Habilita la verificación de testcookie para redirecciones internas (deshabilitado por defecto por razones de optimización), útil para este tipo de configuraciones:

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

testcookie_httponly_flag

sintaxis: testcookie_httponly_flag (on|off);

predeterminado: off

contexto: http, server, location

Habilita la bandera HttpOnly para la cookie.

testcookie_secure_flag

sintaxis: testcookie_secure_flag (on|off|$variable);

predeterminado: on

contexto: http, server, location

Habilita la bandera Secure para la cookie. Cualquier valor de variable excepto "on" se interpreta como False.

testcookie_port_in_redirect

sintaxis: testcookie_port_in_redirect (on|off);

predeterminado: off

contexto: http, server, location

Expone el puerto en la redirección.

Ejemplo de configuración

http {
    #configuración predeterminada, módulo deshabilitado
    testcookie off;

    #estableciendo el nombre de la cookie
    testcookie_name BPC;

    #estableciendo el secreto
    testcookie_secret keepmesecret;

    #estableciendo la clave de sesión
    testcookie_session $remote_addr;

    #estableciendo el nombre del argumento
    testcookie_arg ckattempt;

    #estableciendo el número máximo de intentos de establecimiento de cookies
    testcookie_max_attempts 3;

    #estableciendo la política p3p
    testcookie_p3p 'CP="CUR ADM OUR NOR STA NID", policyref="/w3c/p3p.xml"';

    #estableciendo la URL de respaldo
    testcookie_fallback http://google.com/cookies.html?backurl=http://$host$request_uri;

    #configurando la lista blanca
    testcookie_whitelist {
        8.8.8.8/32;
    }

    #estableciendo redirección a través de código html
    testcookie_redirect_via_refresh on;

    #habilitando cifrado
    testcookie_refresh_encrypt_cookie on;

    #estableciendo la clave de cifrado
    testcookie_refresh_encrypt_cookie_key deadbeefdeadbeefdeadbeefdeadbeef;

    #estableciendo el iv de cifrado
    testcookie_refresh_encrypt_cookie_iv deadbeefdeadbeefdeadbeefdeadbeef;

    #estableciendo la plantilla de respuesta
    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 / {
            #habilitar módulo para ubicación específica
            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;
        }
    }
}

Consulta más casos en el directorio "docs" del proyecto.

Suite de pruebas

Este módulo viene con una suite de pruebas impulsada por Perl. Gracias al módulo Test::Nginx en el mundo de Perl.

Fuentes

Disponibles en github en kyprizel/testcookie-nginx-module.

GitHub

Puedes encontrar consejos adicionales de configuración y documentación para este módulo en el repositorio de GitHub para nginx-module-testcookie.