La plupart des sites Web que je vais héberger sur mon Dockstar sont privés. Par exemple je ne souhaite pas que mes photos de familles soient visible par tous le monde….

Pour restreindre l’accès à ces applications/sites web, j’aurais pu choisir des scripts php qui intégraient une gestion utilisateurs. Mais il est déjà difficile de trouver un script php qui fasse ce que l’on veut et qui soit léger donc si il faut en plus qu’il intègre une gestion complète et sécurisée des accès utilisateurs cela devient mission impossible….

Surtout qu’il existe une alternative : déléguer l’accès à un site au serveur web.


Authentification par mot de passe

Avec Apache cela se fait avec les fichiers .htacces, sous Nginx cela se fait dans le fichier de configuration du site avec le module HttpAuthBasicModule.

La configuration d’un site se fait via la création d’un fichier dans le répertoire /etc/nginx/sites-enabled/, pour restreindre l’accès à un répertoire d’un site il suffit d’ajouter les directives auth_basic et auth_basic_user_file dans le fichier du site.

  • La directive auth_basic indique que l’on utilise une authentification, les texte après sera affiché dans la boite de dialogue d’authentification :
  • La directive auth_basic_user_file indique le chemin vers le fichier contenant les couple login / mot de passe (crypté) autorisé à accéder au répertoire.

Voici ma configuration :

server {
	listen       80;
	server_name  localhost;
	root         /var/www;
 
	# Security
	location ~ /\.ht {
		deny  all;
	}
 
	location /Repertoire_protege/ {
		auth_basic            "Qui va là";
		auth_basic_user_file  /$document_root/Repertoire_protege/.htpasswd;
 
		index  index.html index.htm index.php;
 
		location ~ \.php$ {
			include /etc/nginx/fastcgi_params;
			fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
			fastcgi_pass    127.0.0.1:9000;
		}
	}
}

J’ai personnellement choisi de stocker le fichier contenant les login/mots de passe dans le répertoire à protéger lui même mais on peut le mettre où l’on souhaite (/etc/nginx, etc…), de même le nom est par convention/ habitude .htpasswd (héritage d’Apache) mais on peut choisir le nom que l’on veut.

Par sécurité (indispensable) dès lors que l’on stock ce fichier dans un répertoire accessible par Nginx, il convient d’interdire son accès (sinon il pourra être affiché/télécharger). Dans mon cas il s’agit de la directive « location ~ /\.ht » qui interdit l’accès à tous fichier commençant par .ht

 

Création du fichier des login / mot de passe

Pour créer le fichier .htpasswd contenant les login et le mot de passe crypté, il est communément conseillé d’utiliser le programme htpasswd du package apache2-utils.

Lorsque l’on utilise Nginx, il est toujours un peu dérangeant d’installer un package apache (même si ce dernier est petit : 1.3Mo), il existe donc des alternative sous forme de script perl par exemple.

Le premier que j’ai trouvé/testé est basique  :

#!/usr/bin/perl
 use strict;
 chomp(my $username=$ARGV[0]);
 chomp(my $password=$ARGV[1]);
 print $username.":".crypt($password,$username)."\n";

Il prend en paramètre le login et le mot de passe (en clair), crypte le mot de passe et écrit sur la sortie standard le couple login / mot de passe crypté avec la format attendu d’un ficheir .htpasswd.

 

Le second (que j’ai gardé) est plus ressemblant à htpasswd d’Apache htpasswd-b: a smart replacement for the Apache htpasswd utility

#!/usr/bin/perl
 
if (! scalar @ARGV ) {
	print "Usage: htpasswd-b passwordfile user password\n";
	print "(this program automatically creates the pw file if needed.)\n";
	exit 0;
}
 
@saltsource = ('a'..'z', 'A'..'Z', '0'..'9','.','/');
$randum_num = int(rand(scalar @saltsource));
$salt = $saltsource[$randum_num];
$randum_num = int(rand(scalar @saltsource));
$salt .= $saltsource[$randum_num];
 
$outf=$ARGV[0];
$user=$ARGV[1];
$passwd=$ARGV[2];
 
if ($user && $passwd) {
	$encrypted = crypt($passwd, "$salt");
 
	if (-f $outf) {
		open(OUT, ">>$outf") || die "htpasswd-b error: $!\n";
	} else {
		open(OUT, ">$outf") || die "htpasswd-b error: $!\n";
	}
	print OUT "$user:$encrypted\n";
	close(OUT);
 
	exit 0;
}

Créer un fichier (par exemple htpasswd-perl.pl), y copier le texte ci-dessus, le rendre exécutable (chmod). Il suffit ensuite d’appeler ce script avec le nom du fichier à créer / compléter, le login et le mot de passe en clair.

./htpasswd-perl.pl /var/www/Repertoire_protege/.htpasswd utilisateur mot_de_passe

Enfin j’ai trouvé mais non testé un troisième script qui semble très complet :

htpasswd-perl: mon replacement de htpasswd | Shtark.fr

 

Authentification par mot de passe et php

Si votre site doit servir des pages php vous aurez surement une directive du type « location ~ \.php$ » indiquant le paramétrage fastCGI. Il est très important de mettre cette directive dans le bloc location protégé (cf ma configuration ci-dessus) sinon l’accès au répertoire sera protégé :

http:/localhost/Repertoire_protege

Mais pas l’accès directe à une page php sur le même site :

http:/localhost/Repertoire_protege/index.php

Restriction d’accès par IP

Pour être encore plus sécurisé on peut carrément restreindre l’accès d’un site ou d’un répertoire à une liste fini d’adresse IP avec les directives allow et deny :

	location /Repertoire_protege/ {
		auth_basic            "Qui va là";
		auth_basic_user_file  /$document_root/Repertoire_protege/.htpasswd;
 
		allow 127.0.0.1;
		deny all;
 
		index  index.html index.htm index.php;
 
		location ~ \.php$ {
			include /etc/nginx/fastcgi_params;
			fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
			fastcgi_pass    127.0.0.1:9000;
		}
	}

Allow liste les IP autorisés et deny celle qui sont interdites, dans l’exemple ci-dessus toutes les IP sont interdites sauf l’IP locale (127.0.0.1)

Enfin on peut affiner le comportement de la restriction par IP avec la restriction par mot de passe avec la directive satisfy qui indique si les 2 restrictions (IP + mot de passe) doivent être remplies (satisfy all) ou 1 seule d’entre elle (satisfy any) :

Exemple si on a une restriction par mot de passe + la restriction suivante :

allow 192.168.1.100;
deny all;

Voici les résultats en fonction de la machine accédant au site/répertoire :

Accès depuis satisfy any satisfy all
192.168.1.100 accès direct au site prompt de connexion
autre prompt de connexion 403 forbiden

 

Sources :

Password protect folders with NGINX the right way : Indique la « ruse » de protection d’un répertoire avec php

Restriction of the access with the help of Nginx : voir restriction sur IP

How nginx processes a request

nginx auth password or ip – Server Fault

Les commentaires sont fermés.