hmac-secure-link: Альтернативный модуль NGINX HMAC Secure Link с поддержкой хешей OpenSSL
Установка
Вы можете установить этот модуль в любом дистрибутиве на базе 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, выпущенный 6 марта 2019 года.
Описание:
Модуль Nginx HMAC secure link улучшает безопасность и функциональность стандартного модуля secure link.
Безопасный токен создается с использованием безопасной конструкции HMAC с произвольным алгоритмом хеширования, поддерживаемым OpenSSL, например:
blake2b512, blake2s256, gost, md4, md5, rmd160, sha1, sha224, sha256,
sha3-224, sha3-256, sha3-384, sha3-512, sha384, sha512, sha512-224, sha512-256, shake128, shake256, sm3.
Кроме того, безопасный токен создается, как описано в RFC2104, а именно,
H(secret_key XOR opad,H(secret_key XOR ipad, message)), вместо простого MD5(secret_key,message, expire).
Использование:
Сообщение, которое нужно захешировать, определяется с помощью secure_link_hmac_message, secret_key задается с помощью secure_link_hmac_secret, а алгоритм хеширования H определяется с помощью secure_link_hmac_algorithm.
Для повышения безопасности к сообщению, которое нужно захешировать, следует добавить временную метку в формате ISO 8601 2017-12-08T07:54:59+00:00 (один из вариантов в соответствии с ISO 8601) или в виде Unix Timestamp.
Возможно создание ссылок с ограниченным сроком действия. Это определяется необязательным параметром. Если период истечения равен нулю или не указан, ссылка имеет неограниченный срок действия.
Пример конфигурации для серверной стороны.
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}";
Использование Unix timestamp в Node.js
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 затем содержит безопасный токен, который будет передан на сервер backend.
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
Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-hmac-secure-link.