跳转至

hmac-secure-link: 具有 OpenSSL 哈希支持的替代 NGINX HMAC 安全链接模块

安装

您可以在任何基于 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-hmac-secure-link
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-hmac-secure-link

通过在 /etc/nginx/nginx.conf 顶部添加以下内容来启用模块:

load_module modules/ngx_http_hmac_secure_link_module.so;

本文档描述了 nginx-module-hmac-secure-link v0.3,于 2019 年 3 月 06 日发布。


描述:

Nginx HMAC 安全链接模块增强了标准安全链接模块的安全性和功能性。
安全令牌是使用安全的 HMAC 构造和 OpenSSL 支持的任意哈希算法创建的,例如: blake2b512blake2s256gostmd4md5rmd160sha1sha224sha256sha3-224sha3-256sha3-384sha3-512sha384sha512sha512-224sha512-256shake128shake256sm3

此外,安全令牌的创建遵循 RFC2104,即, H(secret_key XOR opad,H(secret_key XOR ipad, message)),而不是简单的 MD5(secret_key,message, expire)

用法:

要哈希的消息由 secure_link_hmac_message 定义,secret_keysecure_link_hmac_secret 给出,哈希算法 H 由 secure_link_hmac_algorithm 定义。

为了提高安全性,时间戳应以 ISO 8601 格式 2017-12-08T07:54:59+00:00(根据 ISO 8601 的一种可能性)或作为 Unix 时间戳 附加到要哈希的消息中。

可以创建具有有限生命周期的链接。这由一个可选参数定义。如果过期时间为零或未指定,则链接具有无限生命周期。

服务器端的配置示例。

location ^~ /files/ {
    # 传递的变量是安全令牌、时间戳、过期时间(可选)
    secure_link_hmac  $arg_st,$arg_ts,$arg_e;

    # 秘钥
    secure_link_hmac_secret my_secret_key;

    # 要验证的消息
    secure_link_hmac_message $uri$arg_ts$arg_e;

    # 要使用的加密哈希函数
    secure_link_hmac_algorithm sha256;

    # 如果哈希不正确,则 $secure_link_hmac 为空字符串。
    # 如果哈希正确但链接已过期,则 $secure_link_hmac 为零。
    # 如果哈希正确且链接未过期,则 $secure_link_hmac 为一。

    # 在生产环境中,我们不应向潜在攻击者透露
    # hmac 认证失败的原因
    if ($secure_link_hmac != "1") {
        return 404;
    }

    rewrite ^/files/(.*)$ /files/$1 break;
}

应用程序端应使用标准的 hash_hmac 函数生成哈希,然后需要进行 base64url 编码。以下是 Perl 的示例。

变量 $data 包含安全令牌、ISO 8601 格式的时间戳和以秒为单位的过期时间

perl_set $secure_token '
    sub {
        use Digest::SHA qw(hmac_sha256_base64);
        use POSIX qw(strftime);

        my $now = time();
        my $key = "my_very_secret_key";
        my $expire = 60;
        my $tz = strftime("%z", localtime($now));
        $tz =~ s/(\d{2})(\d{2})/$1:$2/;
        my $timestamp = strftime("%Y-%m-%dT%H:%M:%S", localtime($now)) . $tz;
        my $r = shift;
        my $data = $r->uri;
        my $digest = hmac_sha256_base64($data . $timestamp . $expire,  $key);
        $digest =~ tr(+/)(-_);
        $data = "st=" . $digest . "&ts=" . $timestamp . "&e=" . $expire;
        return $data;
    }
';

PHP 中的类似函数

$secret = 'my_very_secret_key';
$expire = 60;
$algo = 'sha256';
$timestamp = date('c');
$stringtosign = "/files/top_secret.pdf{$timestamp}{$expire}";
$hashmac = base64_encode(hash_hmac($algo, $stringtosign, $secret, true));
$hashmac = strtr($hashmac, '+/', '-_'));
$hashmac = str_replace('=', '', $hashmac);
$host = $_SERVER['HTTP_HOST'];
$loc = "https://{$host}/files/top_secret.pdf?st={$hashmac}&ts={$timestamp}&e={$expire}";

在 Node.js 中使用 Unix 时间戳

const crypto = require("crypto");
const secret = 'my_very_secret_key';
const expire = 60;
const unixTimestamp = Math.round(Date.now() / 1000.);
const stringToSign = `/files/top_secret.pdf${unixTimestamp}${expire}`;
const hashmac = crypto.createHmac('sha256', secret).update(stringToSign).digest('base64')
      .replace(/=/g, '')
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
const loc = `https://host/files/top_secret.pdf?st=${hashmac}&ts=${unixTimestamp}&e=${expire}`;

还可以将此模块与充当代理服务器的 Nginx 一起使用。

要签名的字符串在 secure_link_hmac_message 中定义,secure_link_hmac_token 变量包含要传递给后端服务器的安全令牌。

location ^~ /backend_location/ {
    set $expire 60;

    secure_link_hmac_message "$uri$time_iso8601$expire";
    secure_link_hmac_secret "my_very_secret_key";
    secure_link_hmac_algorithm sha256;

    proxy_pass "http://backend_server$uri?st=$secure_link_hmac_token&ts=$time_iso8601&e=$expire";
}

嵌入变量

  • $secure_link_hmac -
  • $secure_link_hmac_token -
  • $secure_link_hmac_expires - 请求中传递的链接的生命周期。

GitHub

您可以在 nginx-module-hmac-secure-link 的 GitHub 仓库 中找到此模块的其他配置提示和文档。