浏览器指纹识别是一种通过收集浏览器特征信息来识别和区分不同用户的技术。在Nginx反向代理中,我们可以利用这些信息进行访问控制(ACL)。以下是实现方案:
浏览器指纹通常包括以下可获取的信息: - User-Agent - Accept-Language - Screen resolution - Timezone - Plugins - WebGL - Canvas - WebRTC - Fonts - Cookie设置
http {
lua_package_path "/path/to/lua/scripts/?.lua;;";
init_by_lua_block {
fingerprint = require "fingerprint"
}
server {
listen 80;
location / {
access_by_lua_block {
local fp = fingerprint.get_fingerprint()
if not fingerprint.is_allowed(fp) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
}
proxy_pass http://backend;
}
}
}
// 使用FingerprintJS等库
FingerprintJS.load().then(fp => fp.get()).then(result => {
const visitorId = result.visitorId;
// 发送到服务器
fetch('/auth', {
method: 'POST',
headers: {
'X-Fingerprint': visitorId
}
});
});
map $http_x_fingerprint $is_allowed {
default 0;
"123abc456def" 1; # 允许的指纹
"789ghi012jkl" 1; # 另一个允许的指纹
}
server {
listen 80;
location / {
if ($is_allowed = 0) {
return 403;
}
proxy_pass http://backend;
}
}
http {
geo $allowed_fingerprints {
default 0;
123abc456def 1;
789ghi012jkl 1;
}
server {
listen 80;
location / {
if ($allowed_fingerprints = 0) {
return 403;
}
proxy_pass http://backend;
}
}
}
可以使用ModSecurity等WAF解决方案,配合指纹识别规则:
http {
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
server {
listen 80;
location / {
modsecurity_rules '
SecRule REQUEST_HEADERS:X-Fingerprint "!@rx ^[a-f0-9]{32}$" \
"id:1001,phase:1,deny,status:403,msg:'Invalid fingerprint format'"
SecRule REQUEST_HEADERS:X-Fingerprint "!@ipMatchFromFile fingerprints.txt" \
"id:1002,phase:1,deny,status:403,msg:'Fingerprint not allowed'"
';
proxy_pass http://backend;
}
}
}
对于需要动态更新的指纹列表,可以结合Redis:
http {
lua_package_path "/path/to/lua/scripts/?.lua;;";
init_by_lua_block {
redis = require "resty.redis"
}
server {
listen 80;
location / {
access_by_lua_block {
local red = redis:new()
red:connect("127.0.0.1", 6379)
local fp = ngx.var.http_x_fingerprint
if not fp then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local allowed = red:sismember("allowed_fingerprints", fp)
if allowed ~= 1 then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
}
proxy_pass http://backend;
}
}
}
以上方案可以根据实际需求组合使用,建议先在小范围测试后再全面部署。