auth-hash: Аутентификация по хешу защищенной ссылки
Установка
Вы можете установить этот модуль в любой дистрибутив на базе 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-auth-hash
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-auth-hash
Включите модуль, добавив следующее в верхнюю часть файла /etc/nginx/nginx.conf:
load_module modules/ngx_http_auth_hash_module.so;
Этот документ описывает nginx-module-auth-hash v0.1.0, выпущенный 6 января 2026 года.
Описание:
Модуль защищенной ссылки HASH для Nginx улучшает безопасность и функциональность стандартного модуля защищенной ссылки. Защищенный токен создается с использованием безопасной конструкции HASH с произвольным алгоритмом хеширования, поддерживаемым OpenSSL, например: blake2b512, blake2s256, gost, md4, md5, mdc2, rmd160, sha1, sha224, sha256, sha3-224, sha3-256, sha3-384, sha3-512, sha384, sha512, sha512-224, sha512-256, shake128, shake256, sm3.
Использование:
Сообщение, которое нужно захешировать, определяется с помощью auth_hash_message, secret_key задается с помощью auth_hash_secret, а алгоритм хеширования H определяется с помощью auth_hash_algorithm.
Для повышения безопасности к сообщению, которое нужно захешировать, следует добавить время или временную метку (в зависимости от формата даты, указанного в параметре format).
Возможно создание ссылок с ограниченным сроком действия. Это определяется необязательными параметрами range_start или range_end. Если период истечения не указан, ссылка имеет неограниченный срок действия.
Пример конфигурации для серверной стороны.
location ^~ /files/ {
# Включает функцию, если она отключена, $auth_hash всегда будет пустым
auth_hash on;
# Устанавливает значение времени, используемое для проверки.
# Вы можете установить диапазон времени истечения, формат значения времени и часовой пояс значения времени
auth_hash_check_time $arg_ts range_end=$arg_e format=%s;
# Устанавливает значение токена, используемого для проверки
# Доступные форматы: hex (по умолчанию), base64, base64url и bin
auth_hash_check_token $arg_st format=hex;
# Секретный ключ
auth_hash_secret "my_secret_key";
# Сообщение для проверки
auth_hash_message "$uri|$arg_ts|$arg_e|$auth_hash_secret";
# Криптографическая хеш-функция, которая будет использоваться
auth_hash_algorithm sha256;
# В производственной среде мы не должны раскрывать потенциальному злоумышленнику
# причины, по которым аутентификация по хешу не удалась
# - Если хеш неверен, то $auth_hash является NULL строкой.
# - Если хеш верен и ссылка не истекла, то $auth_hash равно "1".
if ($auth_hash != "1") {
return 403;
}
rewrite ^/files/(.*)$ /files/$1 break;
}
Сторона приложения должна использовать стандартную хеш-функцию для генерации хеша, который затем необходимо закодировать в hex или base64url. Пример на Perl ниже.
Переменная $data содержит защищенный токен, временную метку в формате ISO 8601 и период истечения в секундах
perl_set $secure_token '
sub {
use Digest::SHA qw(sha256_base64);
use POSIX qw(strftime);
my $now = time();
my $secret = "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;
# hex
my $string_to_hash = $data . "|" . $timestamp . "|" . $expire . "|" . $secret;
my $digest_binary = sha256($string_to_hash);
my $digest = unpack("H*", $digest_binary);
# base64url
# my $digest = sha256_base64($data . "|" . $timestamp . "|" . $expire . "|" . $secret);
# $digest =~ tr/+/_/;
# $digest =~ s/=+$//;
$data = "st=" . $digest . "&ts=" . $timestamp . "&e=" . $expire;
return $data;
}
';
Аналогичная функция на PHP
$secret = 'my_very_secret_key';
$expire = 60;
$algo = 'sha256';
$timestamp = date('c');
$unixtimestamp = time();
$stringtosign = "/files/top_secret.pdf|{$unixtimestamp}|{$expire}|{$secret}";
// hex
$hash = bin2hex(hash($algo, $stringtosign, true));
// base64url
// $hash = base64_encode(hash($algo, $stringtosign, true));
// $hash = strtr($hash, '+/', '-_');
// $hash = str_replace('=', '', $hash);
$host = $_SERVER['HTTP_HOST'];
$loc = "https://{$host}/files/top_secret.pdf?st={$hash}&ts={$unixtimestamp}&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}|${secret}`;
// hex
const hash = crypto.createHash('sha256').update(stringToSign).digest('hex')
// base64url
// const hash = crypto.createHash('sha256').update(stringToSign).digest('base64')
// .replace(/=/g, '')
// .replace(/\+/g, '-')
// .replace(/\//g, '_');
const loc = `https://host/files/top_secret.pdf?st=${hash}&ts=${unixTimestamp}&e=${expire}`;
Версия на Bash
#!/bin/bash
SECRET="my_super_secret"
TIME_STAMP="$(date -d "today + 0 minutes" +%s)";
EXPIRES="3600"; # секунды
URL="/file/my_secret_file.txt"
ST="$URL|$TIME_STAMP|$EXPIRES|$SECRET"
## hex
TOKEN="$(echo -n $ST | openssl dgst -sha256 | awk '{print $1}')"
## Base64url
## TOKEN="$(echo -n $ST | openssl dgst -sha256 -binary | openssl base64 | tr +/ -_ | tr -d =)"
echo "http://127.0.0.1$URL?st=$TOKEN&ts=$TIME_STAMP&e=$EXPIRES"
Встроенные переменные
$auth_hash- Если хеш верен и ссылка не истекла, то $auth_hash равно "1". В противном случае оно равно null.$auth_hash_secret- Значение директивы auth_hash_secret
GitHub
Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-auth-hash.