Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Serveur

Niveau :      
Résumé : alias / /%{username}

Aujourd'hui je voudrais faire un serveur web qui se comporterait comme un serveur FTP ou SFTP. Lorsqu'un utilisateur unix se connecte à un serveur FTP avec un login et un mot de passe, il lui est présenté un contenu qui lui est propre (son $HOME par exemple).

Comment faire l'équivalent avec apache ?

Dit autrement, je voudrais que les 2 commandes suivantes renvoient un contenu différent :

$ wget http://userA@www.monserveur.com/ # répertoire A
$ wget http://userB@www.monserveur.com/ # répertoire B

Pour cela il faut jouer avec les RewriteRules, mais c'est plus balaise que ça en a l'air.

Premièrement il faut une authentification. J'ai choisi ldap, mais prenez la méthode que vous préférez : http://httpd.apache.org/docs/2.2/mo... tout ce qui commence par mod_authn est valable. Voici comment on la met en place :

<Location />
        AuthType basic
        AuthName "My server"
        AuthBasicProvider ldap
        AuthLDAPURL ldap://serveur.ldap.com/dc=domaine,dc=com?uid?sub
        AuthLDAPBindDN cn=user,ou=technical,dc=domaine,dc=com
        AuthLDAPBindPassword password
        Require valid-user
</Location>

Ensuite on joue avec RewriteRule, les variables s'appellent sous la forme %{ENV:VARIABLE}

# utilisez %{ENV:USER_AUTH} pour ceux qui n'ont pas choisi l'authent LDAP
RewriteRule ^(.*) /%{ENV:AUTHENTICATE_uid}/$1

Mais ça ne marche pas. Tout d'abord on apprend qu'il faut mettre les règles dans le Location sinon les variables d'authentification ne sont pas disponibles. Ensuite on a oublié d'activer le rewrite engine. Et enfin dans un location (ou un directory) on ne matche plus la request uri mais le chemin créé à partir de cette uri. Cela qui une fois corrigé nous donne quelque chose comme ça :

<Location />
        RewriteEngine On
        # le résultat sera automatiquement préfixé par le DocumentRoot si on ne le fait pas nous même
        # notez l'absence du / initial dans le pattern ...
        RewriteRule ^var/www/html/(.*) /%{ENV:AUTHENTICATE_uid}/$1 
</Location>

Mais ça ne marche toujours pas. En effet, le rewrite engine d'apache est réentrant, quelle que soit la modification et quel que soit le flag utilisé, si une url est modifiée, apache fait une redirection interne et relance toute la machinerie (dont les redirections). Pour les petits malins, non [L] n'est pas fait pour ça, par contre la doc évoque un [END] qui aurait cette fonctionnalité mais je ne l'ai pas trouvé.

Il nous faut donc un moyen de détecter qu'une url a déjà été transformée par une RewriteRule. Malheureusement les variables (comme %{ENV:AUTHENTICATE_uid}) ne sont valables que dans la partie gauche de RewriteCond ou dans la partie droite de RewriteRule ce qui nous limite sévèrement. On ne peut pas matcher le chemin en pour détecter qu'il contient le répertoire de l'utilisateur. De plus on ne peut pas utiliser une autre racine, apache ajouterait automatiquement le DocumentRoot en cours.

J'ai essayé en utilisant des variables d'environnement temporaire (avec [E=VAR:VALUE]), mais le rewrite engine l'évalue trop tard et ne détecte pas la nouvelle valeur de la variable modifiée par lui-même.

Ma solution est donc de mettre en place un unique répertoire contenant les utilisateurs avec un nom improbable car il ne pourra pas être utilisé comme nom de répertoire dans les répertoires utilisateurs. Et d'utiliser ce nom de répertoire comme marqueur d'url déjà traitée. Ce qui nous donne :

        # mon répertoire s'appelle ____data____
        RewriteRule ^var/www/html/(?!____data____/)(.*) /____data____/%{ENV:AUTHENTICATE_uid}/$1

C'est bien joli, mais ça n'empercherait pas un utilisateur d'aller voir dans le répertorie de son voisin. En effet, ce ne sont que des rewrite rules, pas des droits d'accès. Puisqu'on ne peut pas utiliser les noms de répertoire utilisateur dans les require pour le matcher avec les nom d'utilisateur (on se mordrait la queue (et ça fait mal (au dos))). Il nous faut donc le garantir d'une autre façon, en forçant tout utilisateur a n'accéder qu'à son répertoire avec une autre règle.

        # ce qu'on veut c'est éviter l'utilisateur qui voudrait bypasser la première règle avec un http://www.monserveur.com/____data____/userX
        RewriteRule ^var/www/html/____data____/.*?/(.*) /var/www/html/____data____/%{ENV:AUTHENTICATE_uid}/$1
        # et on voudrait ausst éviter que l'utilisateur puisse scanner la racine
        RewriteRule ^var/www/html/____data____/?$ /var/www/html/____data____/%{ENV:AUTHENTICATE_uid}/

Notez l'ajout de /var/www/html dans les chaines de remplacement, c'est pour éviter qu'apache pense qu'on a modifié le chemin si on n'a rien changé.

Et c'est gagné, on a enfin trouvé !

Je vous laisse donc profiter du résultat :
Edit : la version finale minimise l'appel aux règles, prend en compte les chemins qui se terminent par / et les tentatives d'accès à des répertoires non autorisés.

<Location />
        AuthType basic
        AuthName "My server"
        AuthBasicProvider ldap
        AuthLDAPURL ldap://serveur.ldap.com/dc=domaine,dc=com?uid?sub
        AuthLDAPBindDN cn=user,ou=technical,dc=domaine,dc=com
        AuthLDAPBindPassword password
        Require valid-user

        # make http behave like ftp
        RewriteEngine On
        # create home dir var
        RewriteRule .* - [E=USER_ROOT:/var/www/html/____data____/%{ENV:AUTHENTICATE_homeDirectory}]
        RewriteCond %{ENV:USER_ROOT} !-d
        RewriteRule .* - [E=USER_ROOT:/var/www/html/forbidden]

        # redirection vers les repertpoires utilisateur
        RewriteCond %{REQUEST_FILENAME} !^/var/www/html/____data____
        RewriteRule ^var/www/html/(.*) %{ENV:USER_ROOT}/$1 [L,DPI]

        # impossibilite de lire la racine
        RewriteCond %{REQUEST_FILENAME} ^/var/www/html/____data____/?$
        RewriteRule .* %{ENV:USER_ROOT} [L,DPI]

        # impossibilite de lire le repertoire d'un autre
        RewriteCond %{ENV:AUTHENTICATE_homeDirectory}|%{REQUEST_FILENAME} !^(.*?)\|/var/www/html/____data____/\1
        RewriteRule ^var/www/html/____data____/?[^/]*/?(.*) %{ENV:USER_ROOT}/$1 [L,DPI]
</Location>

<Directory /var/www/html/forbidden>
        deny from all
</Directory>

Note : et pour ceux qui voudraient vraiment faire du FTP avec apache il y a mod_ftp.

Niveau :      
Résumé : ntp.conf ; fudge

Pour vérifier le bon fonctionnement de votre démon ntp, vous êtes amené à taper la commande suivante qui liste les source de temps utilisées :

$ ntpdc -p

Cette commande met une étoile face à la source de référence utilisée pour la synchronisation. Le choix se fait entre autre en fonction du stratum de la source. Je rappelle que les serveurs NTP disposant d'une source de temps matérielle fiable (horloge atomique) ont pour stratum 1. Ceux qui se synchronisent sur eux, 2, et ainsi de suite.

Étant donné qu'il y a un grand nombre de serveurs publics de strate 2 et 3, vous devriez avoir accès à des serveurs de strate 4, ou au pire 5. Mais si le serveur a une strate plus élevée, il se peut que l'horloge choisie ne soit plus le serveur, mais l'horloge locale qui a une strate définie par défaut à 5 sur certaine distributions.

Et là c'est le drame, vous n'êtes plus synchronisés !

Pour résoudre ce problème, il y a plusieurs méthodes, se résumant toutes en la configuration des serveurs de temps :

# ntp.conf

# mettre l'option prefer sur le serveur voulu
serveur xxx.com prefer
# réduire la strate du serveur
fudge xxx.com stratum 4

# augmenter la strate de l'horloge locale
# 127.127 pour les horloges non réseau
# 1.0 pour l'horloge système
fudge 127.127.1.0 stratum 10

Niveau :      
Résumé : molly-guard

Je suis sûr qu'un certain nombre d'entre vous ont plusieurs machines en production. Et je suis certain que vous les gérez toutes à distance (merci ssh).

Le risque est grand lorsqu'on a des machines distantes de confondre un terminal avec un autre. Vous pouvez bien sûr personnaliser un prompt différent pour chaque machine, mais je vous propose aujourd'hui une autre solution.

$ apt-get install molly-guard

Et voilà !

Maintenant les commandes shutdown, halt et reboot vous demanderont de taper le nom de la machine que vous voulez vraiment éteindre avant de le faire. Ouf, le serveur mail/dns/web de l'entreprise ne sera pas éteint par erreur à la place de votre serveur de base de données de test.

Cerise sur le gateau, ceci n'arrive pas si vous êtes sur un terminal local sur la machine, puisque vous êtes sensés savoir où vous êtes.

Exercice pratique, faites de même pour les quelques (elles doivent rester rares) commandes critiques sur vos machines.

Niveau :      
Résumé : apache, virtualhost, configuration

Que se passe-t-il lorsqu'apache reçoit une requête ?

La question peut paraître anodine jusqu'à ce qu'on ait à écrire un fichier de configuration un peu complexe. Il faut alors avoir une idée de l'ordre dans lequel les opérations sont effectuées.

Commençons par un aperçu rapide :
-> récupération du virtualhost concerné
-> récupération de la partie requête
-> rewrite rules et redirect
-> alias et réécriture de la requête nom de fichier
-> traitement par <directory>, <directorymatch>, .htaccess, <files>, <filesmatch>, <location> et <locationmatch>
-> droits d'accès
-> traitement du fichier en fonction de son type.

Ouf c'est long ! Comme cet article, alors prenez votre temps ...

Traitement de l'URL

Pour chaque requête, apache relit sa configuration (en fait il récupère la version parsée en mémoire). Ensuite il parcourt les éléments dans l'ordre, les compile en une seule conf puis la utilise cette conf spécifiquement pour cette requête.

Virtualhost

Bon ca c'est facile, on se base sur les ServerName définis dans les <virtualhost>. Si on n'en trouve pas, on cherche dans les ServerAlias, si on n'en trouve pas on cherche encore, mais cette fois avec les wildcard (*.mondomaine.com), si on ne trouve toujours pas, on prend le premier </virtualhost><virtualhost> qui a été dacléré. Et enfin s'il n'y a pas de virtualhost, on prend le DocumentRoot défini à la racine du serveur apache lui-même.

Voilà on a trouvé le virtualhost, maintenant on prend la requête, qui est la partie située à droite de l'URL après l'hôte et le port.


continue reading...

Niveau :      
Résumé : ssh qemu-system -hda /dev/sda

Supposons que vous administriez une machine distante. Vous n'avez pas d'accès physique à cette machine. C'est ennuyant puisque vous venez de changer la configuration de votre bootloader.

Comment faire pour rebooter tout en garantissant que ca va marcher ?

Hé bien j'ai la solution qui vous permettra de tester ce boot avant de rebooter : qemu.

Préparer les disques

Il nous faut des disques en lecture seule pour éviter que le boot de la machine virtuelle n'écrive sur un disque en cours d'utilisation. Donc pour chacun de vos disques physique :

$ cp -a /dev/sda /root/sda
$ chmod 440 /root/sda

Ainsi nous avons des disques garantis en lecture seule.


continue reading...

Uptime

Feb 20

Niveau :      
Résumé : uptimed

Linux est un système très stable. Tellement stable que certaines personnes font une gloire personnelle de la durée d'allumage de leurs machines.

Pour pouvoir vous vanter vous aussi auprès de vos collègues et briller dans les soirées, voici le moyen de savoir quelles ont été les différentes durées d'uptime de votre machine.

Uptimed est un simple démon disponible dans le paquet éponyme. Il suffit de l'installer. Ce démon ne fait qu'une chose et il le fait bien, il enregistre la durée depuis laquelle le système est lancé dans un fichier de logs et rend ces informations disponibles aux utilisateurs. Il est même capable de vous envoyer un mail pour vous avertir de l'atteinte d'un record.

Les utilisateurs ont accès aux meilleurs temps avec la commande uprecords :

$ uprecords

Tout ceci est bien joli et il est vrai que c'est très gratifiant d'avoir réussi à maintenir un système en fonctionnement pendant plusieurs années, voir une dizaine d'années pour certains. Mais il ne faut pas oublier une chose, la sécurité. Un noyau qui n'est jamais rebooté, ce n'est pas seulement un noyau stable, mais c'est aussi un noyau vulnérable car non mis à jour.

Alors bien sur certains argueront qu'il existe maintenant ksplice. Mais je pense que son usage reste marginal. C'est pourquoi, n'oubliez pas de mettre une sonde sur vos serveur pour surveiller les machines qui n'ont pas été rebootées depuis longtemps, c'est en fait un signe de faiblesse.

Niveau :      
Résumé : lvm raid

Aujourd'hui la suite tant attendue d'une série sur lvm.

Figurez-vous qu'il est possible de faire du raid avec LVM. Hé oui, vous avez déjà remarqué que vous pouviez mettre plusieurs disque dans un vg. Pour l'instant lvm se contente de les mettre bout à bout, comme le ferait un raid de type linear.

Striping

Le raid0 aussi appelé striping découpe un disque en petits morceaux et les alterne pour en faire un disque plus gros. Le but est d'avoir un disque plus gros, mais aussi d'augmenter les performances. En effet, dès qu'on va lire ou écrire un fichier un peu plus gros que ces morceaux, on va le faire sur 2 disques simultanément et donc augmenter la bande passante.

Lorsqu'on répartit les données linéairement sur le disque on ne gagne pas en performances, par contre en cas de crash d'un des deux disques, il y a moyen de récupérer presque la moitié des données, alors que dans le cas du striping, vous êtes sur de ne rien pouvoir récupérer.

Pour faire du striping avec lvm, rien de plus simple. Lors de la création de votre LV, il suffit de préciser le nombre de "stripes" qu'on désire :

# 2 etant le nombre de partition sur lesquels découper le volume
$ lvcreate -L 1G -i 2 lv0 vg0

Notez que si vous voulez forcer le striping sur certaines partitions, il est possible de donner en paramètre à lvcreate la liste des pv sur lesquels vous voulez qu'il soit.

Et pour vérifier que c'est bien ce que vous vouliez :

$ lvdisplay -m /dev/vg0/lv0

continue reading...