testcookie: NGINX testcookie 机器人缓解模块
安装
您可以在任何基于 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,于 2022 年 7 月 19 日发布。
testcookie-nginx-module 是一个简单的机器人缓解模块,使用基于 Cookie 的挑战/响应。
可以使用不同的方法设置挑战 Cookie:
- "Set-Cookie" + 302/307 HTTP 位置重定向
- "Set-Cookie" + HTML meta 刷新重定向
- 自定义模板,这里可以使用 JavaScript。
为了防止自动解析,挑战 Cookie 值可以使用自定义/随机密钥和 IV 通过 AES-128 CBC 模式加密,然后在客户端使用 JavaScript 解密。
指令
testcookie
语法: testcookie (on|off|var);
默认值: off
上下文: http, server, location, if
on - 启用模块
off - 禁用模块
var - 不拦截请求,仅设置模块变量。
testcookie_name
语法: testcookie_name <string>
默认值: TCK
上下文: http, server, location
设置 Cookie 名称。
testcookie_domain
语法: testcookie_domain <string>
默认值: none, set by browser
上下文: http, server, location
设置 Cookie 域。
testcookie_expires
语法: testcookie_expires <string>
默认值: 31 Dec 2037 23:55:55 GMT
上下文: http, server, location
设置 Cookie 过期值。
testcookie_path
语法: testcookie_path <string>
默认值: /
上下文: http, server, location
设置 Cookie 路径,如果您计划为不同位置使用不同的密钥,这很有用。
testcookie_samesite
语法: testcookie_samesite <string>
默认值: None
上下文: http, server, location
设置 Cookie 属性,允许您声明 Cookie 是否应限制在第一方或同站上下文中。 默认值为 None(Cookie 将在所有上下文中发送,即允许跨源发送)。 接受的值:Lax, Strict, None。
testcookie_secret
语法: testcookie_secret <string>
默认值: required configuration directive
上下文: http, server, location
秘密字符串,用于挑战 Cookie 计算,应该是 32 字节或更多, 最好是长但静态,以防止每次服务器重启时合法用户的 Cookie 重置。 如果设置为 "random" - 每次服务器重启时将生成新密钥,不推荐(所有使用先前密钥的 Cookie 将无效)。
testcookie_session
语法: testcookie_session <variable>
默认值: required configuration directive
上下文: http, server, location
设置挑战生成函数输入, * $remote_addr - 客户端 IP 地址将用作用户唯一标识符 * $remote_addr$http_user_agent - 客户端 IP + User-Agent
testcookie_arg
语法: testcookie_arg <string>
默认值: none
上下文: http, server, location
设置 GET 参数名称,用于 Cookie 设置尝试的计算,
如果未设置 - 服务器将尝试无限次设置 Cookie。
testcookie_max_attempts
语法: testcookie_max_attempts <integer>
默认值: 5
上下文: http, server, location
设置在用户被发送到后备 URL 之前的最大重定向次数,根据 RFC1945 不能超过 5。
如果设置为 0 - 服务器将尝试无限次设置 Cookie(实际上,浏览器将显示错误页面)。
testcookie_p3p
语法: testcookie_p3p <string>
默认值: none
上下文: http, server, location
设置 P3P 策略。
testcookie_fallback
语法: testcookie_fallback <script>
默认值: none
上下文: http, server, location
设置后备 URL,用户将在超过指令 testcookie_max_attempts 指定的最大尝试次数后被重定向到此 URL。 可以在这里使用 Nginx 脚本变量。如果未设置 - 客户端将在达到最大尝试次数后收到 403。
testcookie_whitelist
语法: testcookie_whitelist <network list>
默认值: 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
使用 HTTP meta 刷新设置 Cookie 和重定向,如果使用了 testcookie_refresh_template,则需要。
testcookie_refresh_template
语法: testcookie_refresh_template <string>
默认值: none
上下文: http, server, location
使用自定义 HTML 而不是简单的 HTTP meta 刷新,您需要从模板手动设置 Cookie。 可用的所有 Nginx 变量和
$testcookie_nexturl - 客户端应重定向到的 URL,如果超过 *testcookie_max_attempts*,此处将显示 *testcookie_fallback* 的值
$testcookie_got - 从客户端接收到的 Cookie 值,如果没有 Cookie 或不匹配格式则为空
$testcookie_set - 我们期望从客户端收到的正确 Cookie 值
$testcookie_ok - 用户通过测试(1 - 通过,0 - 未通过)注意:在 v1.10 中从 "yes"/"no" 更改
此外,如果启用 testcookie_refresh_encrypt_cookie,则还有三个变量:
$testcookie_enc_key - 加密密钥(32 个十六进制数字)
$testcookie_enc_iv - 加密 IV(32 个十六进制数字)
$testcookie_enc_sec - 加密的 Cookie 值(32 个十六进制数字)
testcookie_refresh_status
语法: testcookie_refresh_status <code>
默认值: 200
上下文: http, server, location
在提供 HTML 时使用自定义 HTTP 状态码。
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
在设置 Cookie 后将客户端重定向到 HTTPS 协议,也会影响 $testcookie_nexturl,在与第三方 SSL 卸载时很有用。
testcookie_refresh_encrypt_cookie
语法: testcookie_refresh_encrypt_cookie (on|off);
默认值: off
上下文: http, server, location
加密 Cookie 变量,与 testcookie_refresh_template 一起使用,以强制客户端使用 AES-128 CBC 解密。
testcookie_refresh_encrypt_cookie_key
语法: testcookie_refresh_encrypt_cookie_key <32 hex digits|random>
默认值: required directive if encryption enabled
上下文: http, server, location
设置加密密钥。
可能的值:
random - 每次 Nginx 重启时生成新密钥
32 hex digits - 静态密钥,如果您计划在客户端 JavaScript 中深度混淆它,这很有用。
testcookie_refresh_encrypt_iv
语法: testcookie_refresh_encrypt_iv <32 hex digits|random|random2>
默认值: random
上下文: http, server, location
设置加密 IV。
可能的值: random - 为每个客户端请求生成新 IV random2 - 为每次 Nginx 重启生成新 IV 32 hex digits - 静态 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
为 Cookie 启用 HttpOnly 标志。
testcookie_secure_flag
语法: testcookie_secure_flag (on|off|$variable);
默认值: on
上下文: http, server, location
为 Cookie 启用 Secure 标志。 任何变量值,除了 "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;
#设置加密 IV
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 驱动的测试套件。感谢 Perl 世界中的 Test::Nginx 模块。
源代码
可在 GitHub 上找到 kyprizel/testcookie-nginx-module。
GitHub
您可以在 nginx-module-testcookie 的 GitHub 仓库 中找到此模块的其他配置提示和文档。