Un truc que j’ai fait un jour, c’est un système de reverse proxy pour apache. Si vous avez pas ce que c’est un reverse proxy, c’est sans doute que vous n’en avez pas besoin, mais je vais y aller d’une explication rapide;
Ça ce traduit en “mandataire” et c’est en général un serveur entre une machine sur un réseau interne (un poste de travail dans une entreprise, par exemple) et l’internet. On peut faire proxy pour des tas de choses, mais généralement c’est pour le protocole HTTP et ses amis HTTPS, FTP qui lui ressemble très vaguement, bref les trucs de l’internet. Mandataire, c’est bien l’idée, il reçoit les requêtes, les envoie à votre place au serveur, et vous envoie la réponse quand il l’a.
Jusque là, il n’y a pas d’intérêt si ce n’est que ça résoud le problème du routage réseau. Bon, sans rentrer dans les détails, sur un réseau privé, l’adresse de l’ordinateur n’est pas connue sur le réseau public, l’internet. Donc, impossible de s’y rendre sans un mandataire qui va nous prêter son adresse IP. Il y a d’autres solutions techniquement, mais le proxy peut faire des choses en plus, et notamment ces trois choses :
Inutile de dire que ça, c’est la théorie. Dans la pratique, c’est plus ou moins bien fait et à la sortie, c’est parfois un cauchemar. Mais bref.
Le reverse proxy, c’est la même chose, mais la différence, c’est que les serveurs sont dans un réseau interne, et que l’on “cache”, si l’on veut, le fait qu’il y a douze serveurs derrière une seule adresse publique. C’est toujours le principe du mandat, mais cette fois-ci, les requêtes viennent de l’extérieur et vont vers l’intérieur.
Les trois choses sont toujours présentes, mais à l’envers !
J’ai expliqué, la différence entre la pratique et la théorie, tout-à-l’heure, non ? Ben là, pareil.
http://intranet.cheunous.com/appli1/ on arrive sur le serveur interne-1 et pareil pour appli2 ?Apache+mod_perl est votre ami !
AVERTISSEMENT : Je ne m’engage à rien, d’ailleurs, en informatique, je m’engage jamais sans être payé et encore. Your mileage may vary, comme dirait l’autre. Il faudrait adapter à apache 2.0 etc... En plus, j’ai pas de LDAP sous la main pour tester.
Il vous faudra des lignes dans ce genre :
LoadModule perl_module /usr/lib/apache/1.3/mod_perl.so
...
<IfModule mod_perl.c>
Alias /perl/ /var/www/perl/
<Location /perl>
SetHandler perl-script
PerlHandler Apache::Registry
Options +ExecCGI
</Location>
</IfModule>
Pour un endroit à protéger, il faudra donc quelque chose du genre
<Directory /var/www/secret>
AuthType basic
AuthName "Endroit secret"
PerlAuthenHandler Apache::AuthSystem
require valid-user
Order allow,deny
Allow from all
</Directory>
Ce n’est qu’un vague exemple, mais c’est l’idée (à fourrer dans un fichier AuthSystem.pm et à mettre là où apache le cherchera).
package Apache::AuthSystem; use Apache::Constants ':common'; use Net::LDAP; sub handler { my $r = shift; my($res, $sent_pwd) = $r->get_basic_auth_pw; return $res if $res != OK; my $user = $r->connection->user; my $reason = ""; my $tmp; my $base_dn; my $serveur; my $filter; my $port; my $cn; my $domaine; my @tmp; my $binddn; my $bindpwd; # decoupage du user en DOMAINE\USER (vous savez, windos...) if (index($user, "\\") > 0) { $user = substr($user, rindex($user, "\\")+1); } $serveur = "serveur-ldap"; $filter="attributDuLdap=".$user; # ce qui dépend de chez vous $port=389; $binddn="CN=connecteur anonyme,CN=users,DC=cheunous,DC=com"; $bindpwd="anonyme"; $base_dn="DC=cheunous,DC=com"; # on se debarrase des mots de passe vide if ($sent_pwd eq "") { $r->note_basic_auth_failure; $r->log_reason("user $filter : no password supplied",$r->uri); return AUTH_REQUIRED; } # procedure ldap pour verifier le mot de passe my $ldap = new Net::LDAP($serveur, port => $port); # d'abord une connexion semi-anonyme my $mesg = $ldap->bind($binddn, password=>$bindpwd); # on verifie que la connexion est ok if (my $error = $mesg->code()) { $r->note_basic_auth_failure; $r->log_reason("user $filter : LDAP Connection Failed: $error ($filter)",$r->uri); return AUTH_REQUIRED; } # ensuite on cherche le gars my $attrs = mail; $mesg = $ldap->search( base => "", filter => "($filter*)", attrs => $attrs ); if (my $error = $mesg->code()) { # oops il existe pas $r->note_basic_auth_failure; $r->log_reason("user $filter : LDAP Search Failed: $error ($filter)",$r->uri); return AUTH_REQUIRED; } my $entry = $mesg->shift_entry; my $user_dn = $entry->dn(); $r->log_reason("user $user_dn : LDAP Search OK ($user_dn)",$r->uri); # on prend son dn my $login = $user_dn; # et on essaye de se logguer avec le password qu'il nous a envoyé $mesg = $ldap->bind($login,password=>$sent_pwd); if (my $error = $mesg->code()) { $r->note_basic_auth_failure; $r->log_reason("user $login : failed bind: $mesg->error ",$r->uri); # essaye encore return AUTH_REQUIRED; } my $error = $mesg->code(); $r->log_reason("AUTHDEBUG user $user_dn bind: $error",$r->uri); # user authentifié return OK; } 1;
Il vous faudra les modules de proxy qui vont bien...
LoadModule proxy_module /usr/lib/apache/1.3/libproxy.so ... ProxyRequests On ... <Directory proxy:http://serveur-interne-1/*> AuthType basic AuthName "intranet" require valid-user PerlAuthenHandler Apache::AuthSystem Order deny,allow Allow from all </Directory> ProxyPass /appli1/ http://serveur-interne-1/appli1/ ProxyPassReverse /appli1/ http://serveur-interne-1/appli1/ ... # idem pour le serveur-interne-2 et appli2
Le mod_revrite. A woodoo thing, comme ils disent.
LoadModule rewrite_module /usr/lib/apache/1.3/mod_rewrite.so .... RewriteEngine On RewriteLogLevel 0 RewriteLog "/var/log/apache/rewrite_log" RewriteRule ^/appli1(.*) http://serveur-interne-1/appli1$1 [P] RewriteRule ^/serveur-interne-1/appli1/(.*)$ http://intranet.cheunous.com/$1 [R]
Mais là, c’est sans garantie de tomber en marche.
Vos remarques et tests complémentaires sont les bienvenus. Je collerai les solutions aux problèmes que je trouve quand j’aurais le temps. Faire marcher l’ensemble du biniou est laissé comme un exercice pour le lecteur.