使用 NGINX 的 `ngx_http_secure_link_module` 模块保护资源链接
一、模块简介
-
版本:自 NGINX 0.7.18 起引入
-
功能:
- 签名校验:对请求 URI 中的签名进行校验,保证链接未经篡改。
- 时效控制:根据请求中携带的过期时间,判断链接是否仍在有效期。
-
启用方式:编译 NGINX 时加入
--with-http_secure_link_module
参数。
二、两种工作模式
1. 简单的“秘密词”模式
- 指令:
secure_link_secret word;
- 原理:在 URL 中以
/前缀/<md5_hex>/<真实路径>
形式传递签名,NGINX 对比签名是否匹配。 - 优点:配置简单,无需传递过期参数;
- 缺点:无法控制时效,仅做防篡改。
配置示例
server {listen 80;server_name example.com;# 开启“秘密词”模式,secret 为约定好的密钥location /p/ {secure_link_secret secret;# 签名校验失败返回 403if ($secure_link = "") {return 403;}# 内部重写到受保护的真实路径rewrite ^ /secure/$secure_link break;}# 真实资源目录,仅允许内部访问location /secure/ {internal;root /data/protected;}
}
-
签名生成(Linux 下):
# 真实资源为 /p/link,secret 为 secret echo -n 'linksecret' | openssl md5 -hex # 输出:5e814704a28d9bc1914ff19fa0c4a00a # 最终访问: # http://example.com/p/5e814704a28d9bc1914ff19fa0c4a00a/link
2. 带过期时间的“MD5+Expires”模式
-
指令:
secure_link $arg_md5,$arg_expires;
secure_link_md5 "<expr> secret";
-
原理:
- 从请求参数(如
?md5=...&expires=...
)中提取签名和过期时间; - 使用指定表达式(通常包含
$secure_link_expires
,$uri
和密钥)计算 MD5,并与请求中的签名比对; - 如果签名匹配且当前时间 ≤ 过期时间,则
$secure_link
=1,否则为0
或空串;
- 从请求参数(如
-
优点:既能防篡改,又可设置时效;
-
缺点:需要在 URL 中额外传递
expires
参数,URL 更长一些。
配置示例
server {listen 80;server_name example.com;location /s/ {# 提取 md5 签名 和 expires 时间secure_link $arg_md5,$arg_expires;# 用 expires + URI + 客户端 IP + secret 组合生成 md5secure_link_md5 "$secure_link_expires$uri$remote_addr secret";# 签名不匹配(变量为空)拒绝访问if ($secure_link = "") {return 403;}# 已过期(变量为“0”)返回 410 Goneif ($secure_link = "0") {return 410;}# 校验通过,正常转发或返回静态资源root /data/protected;}
}
-
签名生成(Linux 下):
# 假设当前时间戳为 2147483647,资源 URI 为 /s/link,客户端 IP 为 127.0.0.1,secret 为 secret data="2147483647/s/link127.0.0.1 secret" # 计算二进制 MD5 并做 base64url 编码: openssl md5 -binary <<<"$data" \| openssl base64 \| tr '+/' '-_' | tr -d '=' # 例如得到 _e4Nc3iduzkWRm01TBBNYw # 最终访问链接: # http://example.com/s/link?md5=_e4Nc3iduzkWRm01TBBNYw&expires=2147483647
三、常见注意事项
- 时间同步:确保 NGINX 服务器时间与客户端签名生成时的时间保持一致,可采用 NTP 校时。
- 密钥安全:
secret
或其他密钥不应硬编码在公网上,建议放在受限权限的配置文件中,并定期轮换。 - IP 限制:示例中加入了
$remote_addr
,可绑定签名与客户端 IP,进一步提高安全性; - 缓存:如果使用了缓存(如
proxy_cache
、fastcgi_cache
),注意签名 URL 往往带不同参数,可能导致缓存失效; - 加密算法:本模块只支持 MD5,若需更强安全可在外部使用更强算法生成签名,并在 NGINX 前端(如 Lua、JS)验证。
四、应用场景
- 下载加速与防盗链:为用户生成带时效的临时下载链接,避免盗链和过期下载。
- 视频点播:保护视频流地址,防止链接被无效抓取或分享。
- 动态接口防滥用:对关键接口生成一次性或限时访问链接,防止机器刷接口。
五、总结
ngx_http_secure_link_module
模块为 NGINX 提供了简单高效的链接保护与时效控制能力。两种模式各有侧重:
secure_link_secret
:轻量、防篡改secure_link
+secure_link_md5
:防篡改 + 时效控制
您可以根据业务需求选择合适方案,并结合 IP、UA、Referer 等信息,进一步增强安全性。希望本文对您快速上手并应用该模块有所帮助!如果有任何问题或优化建议,欢迎在评论区讨论。