BLOG | NGINX

Sécurisation des URL avec le module Secure Link dans NGINX et NGINX Plus

NGINX-Partie-de-F5-horiz-black-type-RGB
Miniature de Kunal Pariani
Kunal Pariani
Publié le 29 juillet 2016

Le logiciel open source NGINX et NGINX Plus sont tous deux très sécurisés et fiables en tant que serveurs Web, proxys inverses et caches pour votre contenu. Pour une protection supplémentaire contre l'accès par des clients non autorisés, vous pouvez utiliser des directives du module Secure Link pour exiger que les clients incluent une chaîne hachée spécifique dans l'URL de la ressource qu'ils demandent.

Dans cet article de blog, nous expliquerons comment configurer les deux méthodes implémentées dans le module Secure Link. Les extraits de configuration d'exemple protègent les fichiers HTML et les listes de lecture multimédia, mais peuvent être appliqués à tout type d'URL HTTP. Les méthodes s’appliquent à la fois à NGINX et à NGINX Plus, mais par souci de concision, nous ferons uniquement référence à NGINX Plus pour le reste du blog.

Aperçu des méthodes du module Secure Link

Le module Secure Link vérifie la validité d'une ressource demandée en comparant une chaîne codée dans l'URL de la requête HTTP avec la chaîne qu'il calcule pour cette requête. Si un lien a une durée de vie limitée et que le délai a expiré, le lien est considéré comme obsolète. L'état de ces contrôles est capturé dans la variable $secure_link et utilisé pour contrôler le flux de traitement.

Comme mentionné, le module fournit deux méthodes. Un seul d'entre eux peut être configuré dans un contexte http , serveur ou emplacement donné.

  • Le premier mode, plus simple, est activé par la directive secure_link_secret . La chaîne codée est un hachage MD5 calculé sur la concaténation de deux chaînes de texte : la partie finale de l'URL et un mot secret défini dans la configuration NGINX Plus. (Pour plus de détails sur la première chaîne de texte, voir Utilisation des URL sécurisées de base .)

    Pour accéder à la ressource protégée, le client doit inclure le hachage juste après le préfixe de l'URL, qui est une chaîne arbitraire sans aucune barre oblique. Dans cet exemple d'URL, le préfixe est videos et la ressource protégée est le fichier bunny.m3u8 :

    /videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8

    Un cas d’utilisation de cette méthode est lorsqu’un utilisateur télécharge une image ou un document sur un serveur pour le partager, mais souhaite empêcher toute personne connaissant le nom du fichier d’y accéder jusqu’à ce que le lien officiel soit publié.

  • La deuxième méthode, plus flexible, est activée par les directives secure_link et secure_link_md5 . Ici, la chaîne codée est un hachage MD5 de variables définies dans le fichier de configuration NGINX Plus. Le plus souvent, la variable $remote_addr est incluse pour restreindre l'accès à une adresse IP client particulière, mais vous pouvez utiliser d'autres valeurs, par exemple $http_user_agent , qui capture l'en-tête User-Agent et restreint ainsi l'accès à certains navigateurs.

    En option, vous pouvez spécifier une date d'expiration après laquelle l'URL ne fonctionne plus même si le hachage est correct.

    Le client doit ajouter l’argument md5 à l’URL de la demande pour spécifier le hachage. Si une date d'expiration est incluse dans la chaîne hachée, le client doit également ajouter l'argument expires pour spécifier la date, comme dans cet exemple d'URL pour demander le fichier protégé pricelist.html :

    /files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740

Le module Secure Link est inclus dans les binaires NGINX open source prédéfinis de nginx.org , les packages NGINX fournis par les fournisseurs de systèmes d'exploitation et dans NGINX Plus . Il n'est pas inclus par défaut lorsque vous créez NGINX à partir de la source ; activez-le en incluant l'argument --with-http_secure_link_module à la commande configure .

Utilisation d'URL sécurisées de base

La manière la plus simple de sécuriser les URL est d'utiliser la directive secure_link_secret . Dans l'extrait d'exemple suivant, nous sécurisons un fichier de liste de lecture multimédia HTTP Live Streaming (HLS) nommé /bunny.m3u8 . Il est stocké dans le répertoire /opt/secure/hls , mais est exposé aux clients utilisant une URL qui commence par le préfixe des vidéos .

serveur {
écoute 80 ;
nom_serveur secure-link-demo ;

emplacement /vidéos {
secure_link_secret enigma ;
si ($secure_link = "") { retour 403 ; }

réécriture ^ /secure/$secure_link ;
}

emplacement /secure {
interne ;
racine /opt ;
}
}

Avec cette configuration, pour accéder au fichier /opt/secure/hls/bunny.m3u8 les clients doivent présenter l'URL suivante :

/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8

La chaîne hachée vient juste après le préfixe, qui est une chaîne arbitraire sans aucune barre oblique (ici, vidéos ).

Le hachage est calculé sur une chaîne de texte qui concatène deux éléments :

  • La partie de l'URL qui suit le hachage, ici hls/bunny.m3u8 .
  • Le paramètre de la directive secure_link_secret , ici enigma .

Si l'URL de demande du client n'a pas le hachage correct, NGINX Plus définit la variable $secure_link sur la chaîne vide. Le si le test échoue et NGINX Plus renvoie le 403 Interdit code d'état dans la réponse HTTP.

Sinon (ce qui signifie que le hachage est correct), la directive de réécriture réécrit l’URL – dans notre exemple vers /secure/hls/bunny.m3u8 (la variable $secure_link capture la partie de l’URL qui suit le hachage). Les URL commençant par /secure sont gérées par le deuxième bloc d'emplacement . La directive racine de ce bloc définit /opt comme répertoire racine pour les fichiers demandés et la directive interne spécifie que le bloc est utilisé uniquement pour les demandes générées en interne.

Générer le hachage sur le client pour une URL sécurisée de base

Pour obtenir le hachage MD5 au format hexadécimal que le client doit inclure dans l'URL, nous exécutons la commande openssl md5 avec l'option -hex :

# echo -n 'hls/bunny.m3u8enigma' | openssl md5 -hex (stdin)= 80e2dfecb5f54513ad4e2e6217d36fd4

Pour une discussion sur la génération de hachages par programmation, voir Génération du hachage par programmation .

Réponse du serveur aux URL sécurisées de base

Les exemples de commandes curl suivants montrent comment le serveur répond à différentes URL sécurisées.

Si l'URL inclut le hachage MD5 correct, la réponse est200 D'ACCORD :

# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8 | head -n 1 HTTP/1.1 200 OK

Si le hachage MD5 est incorrect, la réponse est403 Interdit :

# curl -I http://secure-link-demo/videos/2c5e80de986b6fc80dd33e16cf824123/hls/bunny.m3u8 | head -n 1 HTTP/1.1 403 Interdit

Si le hachage de bunny.m3u8 est utilisé pour un fichier différent, la réponse est également403 Interdit :

# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hs/oven.m3u8 | head -n 1 HTTP/1.1 403 Interdit

Utilisation d'URL sécurisées qui expirent

La méthode la plus flexible pour sécuriser les URL utilise les directives secure_link et secure_link_md5 . Dans cet exemple, nous les utilisons pour autoriser l'accès au fichier /var/www/files/pricelist.html uniquement à partir des clients sur l'adresse IP 192.168.33.14 et uniquement jusqu'au 31 décembre 2016.

Notre serveur virtuel écoute sur le port 80 et gère toutes les requêtes HTTP sécurisées sous le bloc d'emplacement /files , où la directive root définit /var/www comme répertoire racine pour les fichiers demandés.

La directive secure_link définit deux variables qui capturent les arguments dans l'URL de la requête : $arg_md5 est défini sur la valeur de l'argument md5 et $arg_expires sur la valeur de l'argument expires .

La directive secure_link_md5 définit l'expression qui est hachée pour générer la valeur MD5 de la requête ; pendant le traitement de l'URL, le hachage est comparé à la valeur de $arg_md5 . L'exemple d'expression ici inclut le délai d'expiration passé dans la requête (capturé dans la variable $secure_link_expires ), l'URL ( $uri ), l'adresse IP du client ( $remote_addr ) et le mot enigma .

serveur {
écoute 80 ;
nom_serveur secure-link-demo ;

emplacement /fichiers {
racine /var/www ;
secure_link $arg_md5,$arg_expires ;
secure_link_md5 "$secure_link_expires$uri$remote_addr enigma" ;

si ($secure_link = "") { retour 403 ; }
si ($secure_link = "0") { retour 410 ; }
}
}

Avec cette configuration, pour accéder à /var/www/files/pricelist.html , un client avec l'adresse IP 192.168.33.14 doit envoyer cette URL de requête avant le Sat Dec 31 23:59:00 UTC 2016 :

/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740

Si le hachage dans l'URL envoyée par le client (capturé dans la variable $arg_md5 ) ne correspond pas au hachage calculé à partir de la directive secure_link_md5 , NGINX Plus définit la variable $secure_link sur la chaîne vide. Le test if échoue et NGINX Plus renvoie le403 Code d'état interdit dans la réponse HTTP.

Si les hachages correspondent mais que le lien a expiré, NGINX Plus définit le $lien_secure variable à 0; encore une fois le si le test échoue mais cette fois NGINX Plus renvoie le 410 Disparu code d'état dans la réponse HTTP.

Générer le hachage et le délai d'expiration sur un client

Voyons maintenant comment un client calcule les arguments md5 et expire à inclure dans l'URL.

La première étape consiste à déterminer l’équivalent temporel Unix de la date d’expiration, car cette valeur est incluse dans l’expression hachée sous la forme de la variable $secure_link_expires . Pour obtenir l'heure Unix – le nombre de secondes depuis Epoch (1970-01-01 00:00:00 UTC) – nous utilisons la commande date avec l'option -d et le spécificateur de format +%s .

Dans notre exemple, nous définissons l'heure d'expiration sur Sat Dec 31 23:59:00 UTC 2016 , donc la commande est :

# date -d "2016-12-31 23:59" +%s1483228740

Le client inclut cette valeur comme argument expires=1483228740 dans l’URL de la demande.

Nous exécutons maintenant la chaîne définie par la directive secure_link_md5$secure_link_expires$uri$remote_addr enigma – via trois commandes :

  • La commande openssl md5 avec l'option -binary génère le hachage MD5 au format binaire.
  • La commande openssl base64 applique l'encodage Base64 à la valeur hachée.
  • Les commandes tr remplacent le signe plus ( + ) par le trait d'union ( - ) et la barre oblique ( / ) par le trait de soulignement ( _ ), et suppriment le signe égal ( = ) de la valeur codée.

Pour notre exemple, la commande complète est :

# echo -n '1483228740/files/pricelist.html192.168.33.14 enigma' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = AUEnXC7T-Tfv9WLsWbf-mw

Le client inclut cette valeur comme argument md5=AUEnXC7T-Tfv9WLsWbf-mw dans l'URL de la demande.

Générer le hachage par programmation

Si votre serveur Web NGINX Plus diffuse du contenu dynamique à partir d'un serveur d'applications, NGINX Plus et le serveur d'applications doivent utiliser la même URL sécurisée. Vous pouvez générer le hachage pour l'argument md5 dans l'URL par programmation. La fonction Node.js suivante génère un hachage correspondant à celui défini dans l'extrait de configuration NGINX Plus ci-dessus. Il prend un délai d'expiration, une URL, une adresse IP client et un mot secret comme arguments et renvoie le hachage MD5 au format binaire codé en Base64.

var crypto = require("crypto");

function generateSecurePathHash(expires, url, client_ip, secret) {
if (!expires || !url || !client_ip || !secret) {
return undefined;
}

var input = expires + url + client_ip + " " + secret;
var binaryHash = crypto.createHash("md5").update(input).digest();
var base64Value = new Buffer(binaryHash).toString('base64');
return base64Value.replace(/=/g, '').replace(/+/g, '-').replace(///g, '_');
}

Pour calculer le hachage de notre exemple actuel, nous passons ces arguments :

generateSecurePathHash(nouvelle date('31/12/2016 23:59:00').getTime()), '/files/pricelist.html', "192.168.33.14", "enigma");

Réponse du serveur aux URL sécurisées avec des délais d'expiration

Les exemples de commandes curl suivants montrent comment le serveur répond aux URL sécurisées.

Si un client avec l'adresse IP 192.168.33.14 inclut le hachage MD5 et le délai d'expiration corrects, la réponse est200 D'ACCORD :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 200 OK

Si un client avec une adresse IP différente envoie la même URL, la réponse est403 Interdit :

# curl -I --interface "192.168.33.33" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 403 Interdit

Si la valeur de hachage de l'argument md5 est incorrecte, la réponse est403 Interdit :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=qeUNjiY2FTIVMaXUsxG-7w&expires=1483228740' | head -n 1 HTTP/1.1 403 Interdit

Si l'URL a expiré (la date représentée par l'argument expires est dans le passé), la réponse est410 Disparu :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=Z2rNva2InyVcRTlhqAkT4Q&expires=1467417540' | head -n 1 HTTP/1.1 410 Disparu

Exemple – Sécurisation des fichiers de segments avec une date d’expiration

Voici un autre exemple d’URL sécurisée avec date d’expiration, utilisée pour protéger à la fois la liste de lecture d’un élément multimédia et les fichiers de segment.

Une différence par rapport à l'exemple précédent est que nous ajoutons ici un bloc de configuration de carte pour supprimer l'extension de la liste de lecture (fichier .m3u8 ) et des segments HLS (fichiers .ts ) lorsque nous capturons le nom de fichier dans la variable $file_name , qui est transmise à la directive secure_link_md5 . Cela permet de sécuriser les requêtes pour les segments .ts individuels ainsi que pour la playlist.

Une autre différence par rapport au premier exemple est que nous incluons la variable $http_user_agent (qui capture l'en-tête User-Agent ) dans la directive secure_link_md5 , pour restreindre l'accès aux clients sur des navigateurs Web spécifiques (par exemple, pour que l'URL fonctionne sur Safari mais pas sur Chrome ou Firefox).

map $uri $file_name {
default none;
"~*/s/(?<name>.*).m3u8" $name;
"~*/s/(?<name>.*).ts" $name;
}

serveur {
listen 80;
server_name secure-link-demo;

location /s {
root /opt;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$file_name$http_user_agent enigma";

if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
}

Résumé

Le module Secure Link de NGINX vous permet de protéger les fichiers contre tout accès non autorisé en ajoutant des données codées telles que le hachage d'une partie spécifique de l'URL. L'ajout d'un délai d'expiration limite également la durée de validité des liens, pour encore plus de sécurité.

Pour essayer NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation.


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."