hmac-secure-link: Альтернативный модуль NGINX HMAC Secure Link с поддержкой хешей OpenSSL
Установка на Debian/Ubuntu
Эти документы относятся к APT пакету nginx-module-hmac-secure-link, предоставляемому репозиторием GetPageSpeed Extras.
- Настройте APT репозиторий, как описано в настройке APT репозитория.
- Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-hmac-secure-link
Показать дистрибутивы и архитектуры
| Дистрибутив | Версия | Компонент | Архитектуры |
|-------------|--------------------|-------------|----------------|
| debian | bookworm | main | amd64, arm64 |
| debian | bookworm-mainline | main | amd64, arm64 |
| debian | trixie | main | amd64, arm64 |
| debian | trixie-mainline | main | amd64, arm64 |
| ubuntu | focal | main | amd64, arm64 |
| ubuntu | focal-mainline | main | amd64, arm64 |
| ubuntu | jammy | main | amd64, arm64 |
| ubuntu | jammy-mainline | main | amd64, arm64 |
| ubuntu | noble | main | amd64, arm64 |
| ubuntu | noble-mainline | main | amd64, arm64 |
Описание:
Модуль HMAC secure link для Nginx улучшает безопасность и функциональность стандартного модуля 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 timestamps в 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 затем содержит безопасный токен, который нужно передать на серверный сервер.
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- Время жизни ссылки, переданной в запросе.