Laisser un commentaire

Anti-hotlinking pour vidéo avec NGINX

En dehors de toute notion de copyright, de vol intellectuel etc, lorsqu’on possède un site ou un serveur, dès lors qu’un autre site inclut un de nos médias sur ses pages en ne l’hébergeant pas lui-même, mais en faisant un lien direct vers le média hébergé sur notre serveur, il nous vole de la bande passante !

Alors bien évidemment, cela ne porte pas à conséquence si c’est un petit site perso avec très peu de trafic, mais dès que le site est un peu fréquenté, ça peut vite générer un fort trafic, et les coûts qui vont avec. Bien évidemment, plus le média est gros, plus c’est onéreux… C’est donc pour cela que nous allons aborder une technique pour se prémunir du hotlinking de vidéos.

À médias différents, traitements différents

Avec le HTML5, insérer une vidéo dans ses pages est tout aussi simple que d’insérer une image. Seulement, si un jpeg de quelques dizaines de Ko sauvagement hotlinké ne pèse pas bien lourd sur votre bande passante, il peut en être tout autrement d’une vidéo de plusieurs centaines de Mo.

La technique pour se prémunir du hotlinking au niveau des images est très connue. Au niveau de NGINX — puisque c’est sur ce serveur que nous allons travailler, bien que la technique s’adapte facilement à Apache — il suffit de quelques lignes à insérer dans le fichier de configuration de(s) site(s) /etc/nginx/sites-enabled/default (c’est la même arborescence qu’avec Apache et les sites s’activent et se désactivent avec des commandes similaires) :

location ~* \.(jpg)$ {
 valid_referers none blocked www.monsite.fr monsite.fr;
 if ($invalid_referer) { return 403; }

Puisque c’est si simple, pourquoi ne pas reproduire exactement la même technique pour les vidéos ? Il suffirait d’ajouter par exemple le mp4 aux extensions à prendre en compte : location ~* \.(jpg|mp4)$.

Je n’en connais pas trop la raison, mais concernant les vidéos, le navigateur n’envoie pas de referer dans l’en-tête HTTP. Donc dans le cas de la règle ci-dessus, deux choix s’offrent à nous :

  1. Conserver none en tant que referer valide et dans ce cas autoriser toutes les vidéos à être lues, peut importe la page source,
  2. Considérer que none n’est pas un referer valide et donc refuser de servir toutes les vidéos, même celles provenant de nos propres pages.

Vous en conviendrez, aucune de ces solutions n’est satisfaisante, puisque l’une d’elle est inutile et l’autre tout à fait contre-productive. Il s’agit donc de trouver une parade.

Nous n’avons pas de referer qui puisse nous indiquer si l’internaute requiert ce média à partir d’une de nos pages, ou à partir d’un site qui nous aurait “volé” notre contenu. Pour nous permettre de contrôler ceci, nous allons avoir recourt à un cookie !

Tout simplement, lors de la consultation de la page contenant la vidéo, il suffit de créer un cookie et de ne servir la vidéo qu’à la seule condition que ce cookie existe. Le but n’est pas ici d’expliquer comment créer un cookie dans votre langage de programmation de prédilection, si vous avez un trou, pour le php, c’est par ici. Je recommande cependant de mettre une durée de vie assez courte au cookie, de manière à ce qu’un internaute ayant navigué sur votre site ne puisse pas accéder au contenu spolié sur le site d’un concurrent 20mn plus tard par exemple…

Au niveau de NGINX, dans le fichier de conf de votre site, par exemple /etc/nginx/site-enabled/monsite, il va falloir intégrer cette directive. Toujours dans notre /etc/nginx/sites-enabled/default, ou autre fichier si vous en avez créé des personnalisés :

# si le cookie "monCookieDeVerif" n'existe pas, on retourne une erreur 403
if ($http_cookie !~ "monCookieDeVerif") { return 403; }

Et voilà, encore plus court que la directive concernant le hotlinking d’images ! On pourrait cependant améliorer un petit peu la sécurité en se basant aussi sur le contenu du cookie. Par exemple en mettant dans le contenu le chemin du fichier vidéo à accéder, puis en comparant le contenu du cookie à la variable $uri. Ce n’est qu’une suggestion, et je reste ouvert à toute remarque. Cette sécurité n’est pas imparable, mais elle permettra déjà d’éviter la plupart des désagréments !

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```