使用 NGINX 的 `ngx_http_secure_link_module` 模块保护资源链接

一、模块简介

  • 版本:自 NGINX 0.7.18 起引入

  • 功能

    1. 签名校验:对请求 URI 中的签名进行校验,保证链接未经篡改。
    2. 时效控制:根据请求中携带的过期时间,判断链接是否仍在有效期。
  • 启用方式 :编译 NGINX 时加入 --with-http_secure_link_module 参数。

二、两种工作模式

1. 简单的"秘密词"模式

  • 指令secure_link_secret word;
  • 原理 :在 URL 中以 /前缀/<md5_hex>/<真实路径> 形式传递签名,NGINX 对比签名是否匹配。
  • 优点:配置简单,无需传递过期参数;
  • 缺点:无法控制时效,仅做防篡改。
配置示例
nginx 复制代码
server {
    listen 80;
    server_name example.com;

    # 开启"秘密词"模式,secret 为约定好的密钥
    location /p/ {
        secure_link_secret secret;

        # 签名校验失败返回 403
        if ($secure_link = "") {
            return 403;
        }

        # 内部重写到受保护的真实路径
        rewrite ^ /secure/$secure_link break;
    }

    # 真实资源目录,仅允许内部访问
    location /secure/ {
        internal;
        root /data/protected;
    }
}
  • 签名生成(Linux 下)

    bash 复制代码
    # 真实资源为 /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";
  • 原理

    1. 从请求参数(如 ?md5=...&expires=...)中提取签名和过期时间;
    2. 使用指定表达式(通常包含 $secure_link_expires, $uri 和密钥)计算 MD5,并与请求中的签名比对;
    3. 如果签名匹配且当前时间 ≤ 过期时间,则 $secure_link=1,否则为 0 或空串;
  • 优点:既能防篡改,又可设置时效;

  • 缺点 :需要在 URL 中额外传递 expires 参数,URL 更长一些。

配置示例
nginx 复制代码
server {
    listen 80;
    server_name example.com;

    location /s/ {
        # 提取 md5 签名 和 expires 时间
        secure_link   $arg_md5,$arg_expires;
        # 用 expires + URI + 客户端 IP + secret 组合生成 md5
        secure_link_md5 "$secure_link_expires$uri$remote_addr secret";

        # 签名不匹配(变量为空)拒绝访问
        if ($secure_link = "") {
            return 403;
        }
        # 已过期(变量为"0")返回 410 Gone
        if ($secure_link = "0") {
            return 410;
        }

        # 校验通过,正常转发或返回静态资源
        root /data/protected;
    }
}
  • 签名生成(Linux 下):

    bash 复制代码
    # 假设当前时间戳为 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

三、常见注意事项

  1. 时间同步:确保 NGINX 服务器时间与客户端签名生成时的时间保持一致,可采用 NTP 校时。
  2. 密钥安全secret 或其他密钥不应硬编码在公网上,建议放在受限权限的配置文件中,并定期轮换。
  3. IP 限制 :示例中加入了 $remote_addr,可绑定签名与客户端 IP,进一步提高安全性;
  4. 缓存 :如果使用了缓存(如 proxy_cachefastcgi_cache),注意签名 URL 往往带不同参数,可能导致缓存失效;
  5. 加密算法:本模块只支持 MD5,若需更强安全可在外部使用更强算法生成签名,并在 NGINX 前端(如 Lua、JS)验证。

四、应用场景

  • 下载加速与防盗链:为用户生成带时效的临时下载链接,避免盗链和过期下载。
  • 视频点播:保护视频流地址,防止链接被无效抓取或分享。
  • 动态接口防滥用:对关键接口生成一次性或限时访问链接,防止机器刷接口。

五、总结

ngx_http_secure_link_module 模块为 NGINX 提供了简单高效的链接保护与时效控制能力。两种模式各有侧重:

  • secure_link_secret:轻量、防篡改
  • secure_link + secure_link_md5:防篡改 + 时效控制

您可以根据业务需求选择合适方案,并结合 IP、UA、Referer 等信息,进一步增强安全性。希望本文对您快速上手并应用该模块有所帮助!如果有任何问题或优化建议,欢迎在评论区讨论。

相关推荐
杨浦老苏7 分钟前
全新的开源监控工具CheckCle
运维·docker·群晖
智联视频超融合平台1 小时前
智慧赋能光伏运维——无人机巡检+地面监控双链路覆盖,打造光伏电站管理新标杆
运维·人工智能·网络协议·信息可视化·音视频·无人机
小飞敲代码2 小时前
【Hadoop 实战】Yarn 模式上传 HDFS 卡顿时 “No Route to Host“ 错误深度解析与解决方案
大数据·linux·运维·服务器·hadoop·分布式·hdfs
水银嘻嘻2 小时前
03 接口自动化-精通Postman之接口鉴权,接口Mock,接口加解密以及接口签名Sign
运维·自动化·postman
不念霉运2 小时前
Gitee DevOps:中国企业数字化转型的加速引擎
运维·gitee·代码规范·devops·代码复审
遇见火星2 小时前
在CentOS系统上部署GitLabRunner并配置CICD自动项目集成!
linux·运维·ci/cd·centos·gitlabrunner
大脸男孩3 小时前
gitlab迁移
运维·gitlab
派葛穆5 小时前
网络-MOXA设备基本操作
运维·网络
群联云防护小杜5 小时前
物联网僵尸网络防御:从设备认证到流量染色
运维·服务器·前端·网络·物联网·安全·ddos