真正灵活的防盗链需用nginx+lua(openresty)实现实时动态鉴权,因valid_referers仅支持静态域名匹配,无法应对无referer、伪造referer或需按用户/设备/时间放行等场景;lua可校验token、时间戳、签名及设备绑定,并联动redis、风控等实现毫秒级有状态防护。

直接用 valid_referers 做 referer 防盗链简单但僵硬——它只能静态匹配域名,无法应对播放器不带 referer、移动端 WebView 丢失来源、或需要按用户/设备/时间动态放行的场景。真正灵活的防盗链,得靠 Nginx + Lua(通常通过 OpenResty)在请求入口做实时判断。
为什么必须用 Lua?referer 机制不够用
很多资源(如 m3u8、ts 分片、API 返回的图片 URL)是被播放器、小程序、APP 直接拉取的,这些客户端往往不发或伪造 referer。单纯依赖 $invalid_referer 会误杀大量合法请求,也拦不住伪造 referer 的盗链者。Lua 能访问请求的任意字段(IP、User-Agent、URL 参数、Header、Cookie),还能调用外部服务(Redis、Memcached、数据库)做状态校验,实现“有状态的鉴权”。
核心思路:Token + 状态校验(以 m3u8 场景为例)
不暴露原始资源路径,而是分发带签名参数的临时链接,比如:
合法播放页生成的地址:https://cdn.example.com/live/123.m3u8?token=abc123&ts=1728425820&sign=fd8a9b...
后端(或 Lua)在收到该请求时,立即验证:
- 检查
ts是否在有效窗口内(如 ±5 分钟),过期即拒 - 用约定密钥和算法(如 HMAC-SHA256)重算
sign,比对是否一致 - 查 Redis 缓存:该
token是否已被同一 IP+UA 组合使用过;若被其他 UA 或 IP 先用过,视为盗链 - 验证通过则透传请求到真实文件,否则返回 403
关键配置片段(OpenResty 环境)
在 location ~ \.m3u8$ 块中嵌入 Lua:
1. 提前加载模块与缓存连接
在 http 块里初始化 Redis 客户端:
lua_shared_dict auth_cache 10m;<br>
init_by_lua_block {<br>
local redis = require "resty.redis"<br>
redis_client = redis:new()<br>
}
2. 请求阶段校验逻辑
在 location 中:
access_by_lua_block {<br>
local args = ngx.req.get_uri_args()<br>
if not args.token or not args.ts or not args.sign then<br>
return ngx.exit(403)<br>
end<br>
-- 时间校验<br>
if math.abs(ngx.time() - tonumber(args.ts)) > 300 then<br>
return ngx.exit(403)<br>
end<br>
-- 签名校验(示例用 hmac_sha256,密钥需保密)<br>
local expected = ngx.hmac_sha256("your_secret_key", args.token .. args.ts)<br>
if expected ~= args.sign then<br>
return ngx.exit(403)<br>
end<br>
-- 设备绑定校验(简化版:用 ip + ua hash 作 uid)<br>
local uid = ngx.md5(ngx.var.remote_addr .. ngx.var.http_user_agent)<br>
local cached_uid = ngx.shared.auth_cache:get(args.token)<br>
if cached_uid and cached_uid ~= uid then<br>
return ngx.exit(403)<br>
end<br>
ngx.shared.auth_cache:set(args.token, uid, 3600) -- 缓存 1 小时<br>
}
延伸能力:不止防盗链,还能联动风控
Lua 脚本可自然扩展更多防护维度:
- 对高频请求的 IP 自动限流(如每分钟最多 10 次 .m3u8 请求)
- 识别已知恶意 User-Agent(如某些爬虫 SDK、模拟器标识)直接拦截
- 结合业务系统接口,校验 token 是否对应有效付费用户
- 记录盗链行为到日志或上报监控平台,用于后续封禁或溯源
整个过程发生在 Nginx worker 进程内,毫秒级响应,不穿透到后端应用,资源开销极低。











