FreeBSD de plus en plus Xen
Utiliser FreeBSD en domU dans un hyperviseur Xen sera bientôt possible. Cela faisait déjà un moment qu’une page wiki avait été dédiée à ce projet et qu’une petite équipe travaillait dessus. D’après les derniers tests que j’ai pu faire, le domU FreeBSD est beaucoup plus stable, il reste encore quelques bugs et certains reglages kernel inhabituels sont encore nécessaires mais la solution est presque utilisable pour les bidouilleurs ayant un peu de temps à y consacrer. Pour ceux que ça intéresse, Adrian Chadd met à disposition différentes images kernel ici. Une mailling-list a aussi été dédiée à ce projet.
Pour continuer dans la virtualisation, la version 11 du client XenApp vient d’être ajoutée à l’arbre des ports par Thomas Abthorpe (net/citix_xenapp). Ce client permet donc d’éxecuter des applications Windows virtualisées par un serveur citrix XenApp sous FreeBSD. Attention cependant, ce port nécessite l’utilisation de la compatibilité Linux, les points tricky nécessaires à la mise en place de ce port sont disponibles sur cette page wiki.
FreeBSD 8.0 en approche
Le freeze du code source de la version 8 est annoncé pour bientôt. Au menu de cette nouvelle version quelques fonctionalités sympathiques dont entre autres :
- nouvelle implémentation TTY avec enfin le support de l’UTF-8
- jails hiérarchiques : des jails inclus dans d’autres jails pour plus de sécurité
- nouvelle pile USB
- suppression des verrous de la pile réseau
- corrections de bugs sur la pile 802.11
- nouveaux serveurs et clients NFS
- version 13 de ZFS (cf ce lien) qui est déjà disponible en 7.0-STABLE
Avec tout ça, il y a même un planning provisoire :
- 25 juin : code freeze
- 29 juin : 1ère Bêta
- 6 juillet : 2ème Bêta
- 13 juillet : 3ème Bêta
- 27 juillet : 1ère Release Candidate
- 17 août : 2ème Release Candidate
- 31 août : Release
Sans doute la manière la plus rapide d’ajouter un authentification SSH par clef publique :
- Génération de la clef (à ne faire qu’une seule fois)
ssh-keygen
- Ajout de la clef aux clefs autorisées sur le serveur distant
cat ~/.ssh/id_rsa.pub | ssh user_distant@fqdn_serveur_distant \ "cat - >> ~/.ssh/authorized_keys"
Simple, rapide et efficace.
Trust no one !
La plupart des protocoles réseaux utilisés de nos jours n’étant pas cryptés, il est souvent nécessaire de mettre en place un VPN afin de sécuriser certains flux. Pour cet article, nous utiliserons le daemon VPN ‘mpd‘.
Installation du serveur
Il faut tout d’abord installer le port mpd
# cd /usr/ports/net/mpd/ && make install clean
Puis éditer le fichier ‘/etc/rc.conf‘ pour que le daemon soit lancé au démarrage en background (option -b) sans que la console d’administration soit accessible de l’extérieur (option -a)
mpd_flags="-b -a 127.0.0.1" mpd_enable="YES"
Configuration du serveur
La configuration se situe dans trois fichiers, voici un exemple de configuration pour chacun des fichiers :
# Fichier /usr/local/etc/mpd/mpd.conf default: load vpn1 vpn1: new -i ng0 vpn vpn # the session value does matter, but I'm not sure why set iface session 28800 # "username" here should match "username" in mpd.secret set bundle authname "majinbox" set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e56 set ccp yes mpp-e128 # set this to your correct routing information set iface route 10.253.6.0/24 set link yes acfcomp protocomp set ipcp yes vjcomp set iface disable on-demand set iface idle 0 set link keep-alive 61 753 set link mtu 1460 set ccp yes mpp-stateless set link no pap set link accept chap set link enable no-orig-auth open
Cette configuration permet d’avoir un lien appellé ‘vpn1‘ pour l’utilisateur ‘majinbox‘. Dans le cas ou le VPN serait utilisé par des clients sous Windows, il est important de commenter la ligne qui active la compression. Il est possible de créer plusieurs connexions, en ajoutant ‘load vpn2‘ dans la section ‘default‘ et en créant une section contenant les directives propres à la sections.
# fichier /usr/local/etc/mpd/mpd.conf majinbox MonMotDePasseEnClair
Ce fichier contient les identifiant et mot de passes des différents utilisateurs. Les mots de passes étant stockés en clair, il faut limiter au maximum les droits en lecture sur ce fichier.
#fichier /usr/local/etc/mpd/mpd.links vpn: set link type pptp set pptp peer 217.174.206.169 set pptp enable incoming set pptp disable originate
Ce fichier permet de définir le sens des connexions VPN, dans notre cas, la connexion est entrante car nous sommes sur le serveur.
Installation et configuration du client
L’installation est la configuration du client est identique à l’exception du fichier ‘mpd.links‘. Il faut être vigilant et lancer le serveur avant le client.
Jusqu’il y a peu de temps, il fallait bidouiller le /etc/make.conf pour utiliser l’option -j de make permettant de paralléliser la compilation d’un port. En plus d’être un hack relativement laids, ce type de bidouille était incompatible avec certains ports. Ce temps là est révolu, il y maintenant une whitelist de ports qui sont d’office compilé avec autant de job en parallèle qu’il y a de cores présents sur la machine. Les ports qui ne sont pas marqué comme compatibles restent compilés sans parallélisation.
Cette fonctionnalité est activée par défaut, pour la désactiver (ce qui n’a d’intérêt que dans des cas très particuliers), il suffit d’ajouter à /etc/make.conf la directive suivante :
DISABLE_MAKE_JOBS=yes
Afin de forcer le nombre de jobs à exécuter en parallèle (option -j de make), il faut utiliser la directive suivante (toujours dans /etc/make.conf) :
MAKE_JOBS_NUMBER=6
Il existe un option pour les kamikazes téméraires qui permet de forcer l’utilisation de cette nouvelle fonctionnalité pour l’ensemble des ports (même pour ceux qui ne sont pas marqués comme compatibles) :
FORCE_MAKE_JOBS=yes
Je vous déconseille néanmoins cette solution. Si le but est de compiler quelques ports qui ne sont pour l’instant pas marqués comme validés, il suffit d’ajouter le fichier Makefile du ou des ports en question et d’y ajouter la directive suivante en dessous des déclarations de dépendances :
MAKE_JOBS_SAFE=yes
Les mainteneurs de ports peuvent aussi marquer leur port comme incompatible avec la directive :
MAKE_JOBS_UNSAFE=yes
Une petite astuce bien pratique :
openssl rsa -in server.key -out server.key.unencrypted
J’en profite pour faire un peu de pub pour StartSSL qui propose des certificats SSL gratuits mais dont l’interface impose de mettre une passphrase sur le certificat (ces certificats ne sont pas malheuresement pas reconnus par IE)
Une des raisons du succès de Firefox est le grand nombre d’extensions disponibles. Ces extensions permettent d’étendre les fonctionnalités du navigateur et il y en a vraiment pour tout les goûts. Dans cet article, nous présenterons 5 des extensions les plus utiles dans le cadre du developpement web.
FireBug
Cette extension permet de naviguer et de modifier de manière intuitive l’ensemble des éléments d’une page web : code HTML, feuille de style CSS, et script JavaScripts. Les modifications se font directement dans le navigateur et sont appliquées immédiatement. Indispensable pour tester différentes mise en page ou pendant une phase de debug de JavaScript.
Lien de téléchargement
YSlow
Attention, cette extension ne fonctionne pas si FireBug n’est pas installé. Cette extension créée par Yahoo mesure les performances d’un site web (temps d’affichage d’une page, taille de la page) et propose des optimisations pertinentes basées sur les best-practices de Yahoo.
Lien de téléchargement
HttpFox
Très bon complément à FireBug, cette extension permet d’enregistrer l’ensemble du trafic HTTP. Cette approche systématique permet d’identifier de manière simple et exhaustive les requêtes les plus lentes.
Lien de téléchargement
Firefox DNS Flusher
Il n’est pas rare de devoir forcer des résolutions DNS lors des phases de développement ou de qualification d’une nouvelle version d’un site web. Forcer la résolutions d’un nom de domaine sur un serveur de test en modifiant le fichier host est aisée. Le problème est la cache DNS de Firefox. Cette extension permet de vider le cache de Firefox et surtout d’afficher l’adresse IP réellement utilisée pour l’affichage du site.
Lien de téléchargement
Selenium IDE
Les sites web étant de plus en plus aboutis au niveaux des fonctionnalités, les scenarii de test deviennent de plus en plus complexes. Selinum IDE permet d’aider le developpeur web dans la création et l’execution d’un scenario de test en permettant d’automatiser la navigation sur un site web.
Lien de téléchargement
Cette liste n’est bien sur pas exhaustive mais permet d’avoir un bon point de départ.
Jails faciles et légères avec ezjails
Update : Ajout de l’option « -p » à l’installation qui permet d’avoir les ports dans les jails
Principes de fonctionnement
Petit rappel : les jails permettent d’exécuter un système FreeBSD à l’intérieur d’un autre système FreeBSD. Cela permet entre autre d’installer des ports incompatibles sur une seule machine et de protéger le système des éventuelles failles de sécurité d’un démon lancé dans une jail.
‘ezjail‘ est un petit script sh qui permet en plus d’automatiser la création de jails de limiter l’espace disque utilisé par chaque jail en permettant de n’utiliser qu’un seul système de base monté en read-only sur chacun des jails.
Installation d’ezjail
cd /usr/ports/sysutils/ezjail make install clean
Il peut être utile d’ajouter la directive suivante au fichier ‘/etc/rc.conf‘ afin d’automatiser le démarrage des jails lors d’un reboot :
ezjail_enable="YES"
Création d’un premier jail
Il faut tout d’abord configurer ezjail. Suivant l’espace disque disponible, il peut être utile de modifier le répertoire dans lequel sont stockées les jails : ‘/usr/jails/‘ par défaut.
# cp /usr/local/etc/ezjail.conf.sample /usr/local/etc/ezjail.conf # vi /usr/local/etc/ezjail.conf
Afin de créer le jail de base, il suffit de lancer la commande :
# ezjail-admin install -p
Pour créer un jail, il suffira ensuite d’ajouter un alias IP dans le système hôte et de lancer la commande ‘ezjail-admin create‘. Uns fois, le jail créé, on pourra lancer ‘ezjail‘
# ifconfig fxp0 192.168.22.101 alias # ezjail-admin create <jailname> <jailIP> # /usr/local/etc/rc.d/ezjail start
Are you Token to me ?
Le but de cet article est d’aborder l’utilisation du mod_secdownload de Lighttpd. Ce module ne permet qu’un seul mode de protection basé sur l’expiration des URLs au bout d’une durée déterminée par l’administrateur. Une autre approche serait de créer des jetons qui expirent quand ils sont utilisés. Cette approche sera brièvement abordée à la fin de cet article.
Le principe de fonctionnement du module mod_secdownload est relativement simple, l’URL doit contenir : le chemin relatif du fichier à télécharger, la date de création de l’URL et une somme de contrôle servant à valider l’URL. Si la date de création est jugée trop loin dans le passé, un code d’erreur 410 est renvoyé. Si la somme de contrôle est invalide, un code d’erreur 403 est renvoyé. Si la date de création est suffisamment récente et que la somme de contrôle est correcte, le fichier est envoyé au client.
Gentlemen start our engines
Le module mod_secdownload est inclus dans la distribution de base de Lighttpd. Il faut néanmoins veiller à ce que le module soit chargé au lancement de Lighttpd. Ce qui donne dans lighttpd.conf :
server.modules = (
...
"mod_secdownload",
...
)
La configuration du module se fait grâce à 4 paramètres :
secdownload.secret = "MonSecret" secdownload.document-root = "/path/to/protected/files" secdownload.uri-prefix = "/telechargement/" secdownload.timeout = 30
- Le paramètre secret sert lors du calcul de la somme de contrôle. La sécurité de la protection est basée sur cette chaine de caractères, il est donc important de bien la choisir et de ne pas la divulguer.
- Le paramètre document-root sert à définir le chemin absolu du dossier contenant les données à proteger.
- Le paramètre uri-prefix est similaire aux directives Alias d’Apache. Chaque appel du type mondomaine.tld/uri-prefix sera traité par le module mod_secdownload
- Le paramètre timeout permet quand à lui de définir la durée en secondes pendant laquelle l’URL est valide
Et maintenant, je fais quoi ?
Une fois Lighttpd configuré, il faut que l’application Internet soit en mesure de générer des liens valides de téléchargements. Des implémentations simples sont disponibles sur le site de Lighttpd. Il est important de bien comprendre l’algorithme sous-jacent, une fois l’algorithme maîtrisé la création de liens de téléchargements est relativement aisée.
L’URL de téléchargement sera de la forme suivante :
<mondomaine.tld>/<uri-prefix>/<token>/<timestamp>/<chemin-relatif>
Le timestamp doit être au format Hexadecimal. Le token est la somme MD5 de la concaténation du secret définit dans la configuration Lighttpd, du chemin relatif du fichier (en y laissant le / du début du chemin) et du timestamp au format hexadecimal.
Le script générant les URLs de téléchargement a donc besoin de connaître le secret. Le token varie en fonction du temps et du fichier à télécharger. Il faut donc faire attention aux deux points suivant lors de l’implémentation du générateur d’URL de téléchargement :
- Le secret doit être stocké de manière sécurisée (fichier avec droits limités par exemple) afin de ne pas compromettre la protection
- Le générateur d’URLs doit avoir son horloge synchronisée avec le serveur de téléchargement
Et si je veux faire autrement ?
Une autre approche serait de créer un GUID (Global Unique ID) lors de la création de l’URL, stocker cet ID et de l’invalider une fois qu’il a été utilisé. Cette solution est plus complexe à mettre en place : il n’existe pas à ma connaissance de module Lighttpd permettant de mettre en place ce genre de scénario. Le téléchargement devra alors être géré par l’interpréteur PHP/Ruby/Python/… . De plus le stockage des IDs nécessite a priori l’utilisation d’une base de données.
Voici de manière synthétique les avantages et inconvénients des deux solutions :
- mod_secdownload : la vérification de la validité de l’URL est rapide et le téléchargement bénéficie des différentes optimisation de Lighttpd (IO asynchrones par exemple). Par contre, une URL est valide pour tout les client pendant le laps de temps défini dans la configuration. Cette solution est performante mais plus limitée. De plus la sécurité de l’ensemble de la solution est compromise dès lors que le secret est connu par un tiers.
- GUID par téléchargement : Cette solution est plus sécurisée, pour compromettre la solution, il faudrait obtenir un accès en écriture au système de stockage des IDs de téléchargements. Cependant, cette solution est plus lourde à mettre en place et moins performante car elle nécessite l’utilisation d’un interpréteur PHP/Ruby/Python/… lors du téléchargement du fichier.
Lighttpd est un très bon serveur web mais force est de constater qu’il est difficile de se passer d’apache (en particulier à cause des fichiers .htaccess qui ne sont pas supportés par Lighttpd). Nous allons donc voir comment mettre en place un serveur Lighttpd qui servira du contenu statique et dynamique tout en faisant office de proxy pour Apache quand l’utilisation de ce dernier est nécessaire.
Vue d’ensemble de la solution
- Lighttpd écoutera sur le port 80 et répondra donc à toutes les requêtes, il servira de reverse-proxy pour les requêtes destinées à Apache.
- Apache écoutera sur le port 8080, il répondra à toutes les requêtes sur ce port. En production, il ne devrait appelé que par Lighttpd mais il sera possible de l’appeller depuis n’importe quel navigateur pendant une phase de Debug.
- La configuration sera adaptable pour chaque VirtualHost, il sera envisageable de mettre en place 3 configurations différentes :
- uniquement Lighttpd, dans le cas d’un site statique ou dynamique pouvant fonctionner sous Lighttpd, cette configuration est à privilegier
- contenu statique servi par Lighttpd, contenu dynamique servi par Apache via le mod_proxy de Lighttpd. Cette solution est à utiliser pour améliorer les performances d’un site nécessitant Apache pour son contenu dynamique.
- site uniquement servi par Apache via le mod_proxy de Lighttpd. Cette solution n’est envisagée que pour des cas particuliers, elle est à éviter a priori.
Modification de la configuration d’Apache
Afin que le serveur Apache écoute sur le port 8080, il faut modifier la directive Listen 80 en Listen 8080 de son fichier de configuration. Il faura aussi modifier les configuration des différents VirtualHost pour qu’ils soient pris sur le port 8080. Enfin, vu qu’en fonctionnement nominal, le serveur ne sera interrogé que sur du contenu dynamique et page par page, on pourra désactiver le KeepAlive en plaçant la directive KeepAlive Off.
Configuration de base de Lighttpd
La configuration de Lighttpd est en général effectuée dans un seul fichier lighttpd.conf. Dans notre cas, nous avons besoin d’activer les modules suivants :
- mod_proxy : ce module permettra de faire fonctionner Lighttpd en tant que reverse-proxy.
- mod_status : ce module nous permettra de suivre l’état du serveur
- mod_auth : ce module permettra de limiter l’accès au server-status
Pour ajouter un module, il suffit de décommenter la ligne contenant le nom du module dans le fichier de configuration.
Pour activer le server-status, il suffit d’ajouter la directive suivante :
status.status-url = "/server-status"
Il est quand même plus sur de limiter l’accès au server-status, il faut créer un fichier .htpasswd avec les identifiants et mot de passes des utilisateurs autorisés à se connecter au server-status (l’executable htpasswd d’Apache convient parfaitement pour cette tâche). il faut ensuite ajouter les lignes suivantes à la configuration de Lighttpd (dans mon cas, le fichier .htpasswd est stocké dans le dossier /usr/local/www) :
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/usr/local/www/.htpasswd"
auth.require = ( "/server-status" =>
(
"method" => "basic",
"realm" => "status",
"require" => "valid-user"
)
)
On peut ajouter une petite optimisation : l’utilisation d’un cache pour les appels stat :
server.stat-cache-engine = "fam"
Ajout d’un VirtualHost servi uniquement par Lighttpd
C’est le cas le plus simple et a priori le plus performant, il faut néanmoins être sur que l’application web hébergée sur le VirtualHost est totalement compatible avec Lighttpd.
$HTTP"host" =~ "test.labs.fr" { server.document-root = "/home/majinboo/sites/test" accesslog.filename = "/var/log/lighttpd/test-access.log" }
Ajout d’un VirtualHost Mixte : contenu statique servi par Lighttpd et contenu dynamique sous Apache
Ce blog est propulsé par Dotclear, n’ayant que peu de retour sur la compatibilité de Dotclear avec Lighttpd, j’ai pour l’instant choisi de le faire fonctionner en configuration mixte. La stratégie est la suivante : pour qu’Apache soit appelé sur les URL non-statiques (qui sont la plupart du temps rewritées) on utilise un proxy uniquement pour les url qui ne terminent pas par une extension connue pour être celle d’un fichier statique.
Vu que le contenu sera servi pour moitié par Apache et pour l’autre moitié par Lighttpd, il faut configurer le virtualHost à la fois dans Apache et dans Lighttpd. Ce qui donne pour la configuration d’Apache quelque chose de relativement anodin :
<VirtualHost *:8080>
ServerAdmin majinboo@labs.fr
DocumentRoot "/home/majinboo/sites/blog.majinboo.org"
ServerName majinboo.org
ServerAlias www.majinboo.org
ServerAlias blog.majinboo.org
ErrorLog "/var/log/httpd/majinboo.org-error.log"
CustomLog "/var/log/httpd/majinboo.org-access_log" combined
</VirtualHost>
Pour Lighttpd, la configuration est un poil plus complexe en raison de l’utlisation du mod_proxy :
$HTTP"host" =~ "majinboo.org" { server.document-root = "/home/majinboo/sites/blog.majinboo.org" accesslog.filename = "/var/log/lighttpd/majinboo.org-access.log" $HTTP"url" !~ "\.(js|css|gif|jpg|png|ico|txt|swf|html|htm)$" { proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) ) } }
Ajout d’un VirtualHost entièrement managé par Apache
Cette configuration peut par exemple être utile dans le cas d’un WebService qui sert des images générées par un script (captcha ou autre). Dans ce cas il faudra mettre la configuration du VirtualHost dans la configuration d’Apache et se contenter de tout rediriger vers Apache dans la configuration de Lighttpd, ce qui donne :
$HTTP"host" =~ "test2.labs.fr" { server.document-root = "/home/majinboo/sites/captchaServer" accesslog.filename = "/var/log/lighttpd/captcha-access.log" proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) ) }
Petit test de performances
Le test consiste à lancer siege en mode benchmark avec une liste d’URLs correspondant à la page d’accueil de ce blog. Pour ce test, 150 utilisateurs concurrents déroulent la liste d’URLs de manière séquentielle pendant 10 minutes. Le serveur qui est testé est un Bi Xeon Dual Coeurs avec 4 GB de RAM.
Résultats avec Apache
- Nombre de requêtes par seconde : 148
- Load du serveur : 50
- Mémoire libre : 2GB
Résultats avec la configuration mixte Lighttpd / Apache
- Nombre de requêtes par seconde : 151
- Load du serveur : 20
- Mémoire libre : 2.3 GB
On remarque que les performances brutes ne sont pas significativement meilleures avec Lighttpd, cependant le serveur est bien moins chargé avec la configuration mixte. Il est possible que ce soit la machine de test qui limite (une dédibox première génération).
Possibilités d’amélioration qui feront l’objet d’un futur article
Pour l’instant, le mod_proxy de Lighttpd interroge Apache à chaque requête. Un patch permet d’ajouter un mod_cache à Lighttpd qui permettrait d’augmenter les performances de la solution en servant le résultats de certaines requêtes destinées à Apache depuis un cache.
De plus PHP et postGreSQL qui sont utilisés par le blog ne sont pour l’instant pas optimisés. Il serait opportun d’optimiser leur configuration et d’ajouter le module eAccelerator à PHP.