Archive pour la catégorie ‘Libre’

Présentation de Vala

Vendredi 11 juin 2010

J’ai découvert une présentation du langage dans GLMF n°127 qui l’utilisait pour se brancher sur le pare-feu. Cela ayant aiguisé ma curiosité, j’ai cherché à en savoir davantage sur le langage.

Le langage C m’a toujours paru difficile à aborder. Non pas au niveau de sa syntaxe, mais au sujet de l’accès à sa documentation et aux librairies disponibles. Pour moi qui suis habitué à Java ou à Python, j’ai regardé Vala comme un moyen de mettre un pied dans le C. Je vais essayé de présenter ma manière de le voir, après avoir fait une petite plongée dedans…

Présentation

Le langage Vala à été créé par les développeurs de Gnome pour qu’ils puissent disposer d’un langage de haut niveau. Gnome ayant eu pendant quelques temps un pied ( dansant ) dans mono, Vala en est très inspiré. ( Je ne connais pas mono et ne peux donc pas lancer de comparatif, je vous renvoie donc à celui présenté par Gnome par rapport à C#, et pour Java ). Le langage est ensuite compilé en C, et GCC est utilisé pour la compilation d’un exécutable.

On est donc dans un langage intermédiaire, qui reste très proche du C comme nous allons le voir par la suite.

Analyse

Langage objet haut niveau

Vala est tout d’abord un langage haut niveau : on y retrouve des interface ( pour pouvoir moduler le code facilement ), des delegate ( qui permettent de de définir un type de fonction pour un callback ), une gestion événementielle ( gérer le déclenchement de plusieurs méthodes dans le code par un appel unique ) … On dispose donc d’un langage objet assez riche pour éviter d’avoir passer du temps sur des détails et se concentrer sur le programme et son déroulement. Il est pensé objet et l’on retrouve vite ses marques, tout comme l’on sent qu’il est assez facile d’« abstraire » le code pour faire une application qui n’en reste pas un simple script…

Je n’ai pas envie de détailler la syntaxe du langage et tout ce qu’il intègre car vous pourrez trouver tout cela en ligne. Je vous renvoie au tutoriel qui explique la structure du langage en détail, qui présentent des exemples détaillés.

La GLib

Le langage est basé sur la GLib, la librairie standard utilisé dans les applications GTK. La plupart des types primitifs ( int… ) sont donc en réalités des types issus de cette librairie ( gint…). On accède ainsi à l’ensemble des méthodes de la GLib, diffusées sous formes de classes objets et bien documentées ( la valadoc ). Cela rejoint l’histoire de Vala puisque La GLib est tout utilisée par les développeurs Gnome ( on constate d’ailleurs que la plupart des composants Gnome ont une entrée dans cette Valadoc ).

Il ne faut cependant pas croire que l’on dispose avec cette bibliothèque standard d’un ensemble de routines aussi riche que dans le package standard d’un Java ou d’un Python : la GLib est avant tout destinée à des développeurs C, et beaucoup des méthodes standard du C n’y sont pas disponibles. Pour parer cela, Vala propose une classe POSIX[LIEN] proposant les méthodes standard du C, mais celle-ci n’est pas exhaustive et il nous arrive souvent de tomber sur une fonction qui ne nous est pas accessible via le langage haut niveau qu’est Vala.

Les Bindings

Pour répondre à cela, propose la possibilité de mettre en place un binding vers une libraire C de manière native. ( Normal me direz vous, le code en sortie de Vala est du C ! ) On peut donc très facilement utiliser n’importe quelle libraire existante. Vala étant un langage objet, il devient donc possible d’utiliser les librairies standard au sein d’un code objet de haut niveau. Cela ne demande que quelques lignes, demandant au minimum le fichier dans lequel se trouve la définition de la méthode, et sa signature.

Exemple du binding définissant la méthode execl ( issue du fichier /usr/share/vala/vapi/posix.vapi ) :

[CCode (cheader_filename = "unistd.h")]
public int execl (string path, params string[] arg);

et voici la signature de la méthode C correspondante :

extern int execl (__const char *__path, __const char *__arg, ...) __THROW __nonnull ((1));

Les types primitifs de la GLib étant basés sur les types primitifs C correspondant, il n’y a pas de problème de cast dans la plupart de cas. Toutefois, Vala utilise des char* pour définir ses string : il est parfois nécessaire de mettre en place faire un cast quand une méthode nous un char[] : même dans le code haut niveau, le C n’est jamais loin…

C’est souvent frustrant de devoir mettre en place un binding pour une fonction disponible en standard dans la libc. Je pense qu’il manque la possibilité d’inclure directement du code C dans le code vala, tout comme il est possible directement de l’assembleur dans du C. Cela permettrait un confort dans l’utilisation qui n’est pas disponible actuellement.

À noter qu’un outil permet de mettre en place ces bindings pour les composants basés sur GObjet ( Gnome toujours… ). De plus de nombreux bindings sont disponibles pour les composants Gnome. Attention, cela n’empêchera pas d’avoir à installer les headers C correspondants !

Les profils

Il est possible d’utiliser des profils de compilation. Cette option encore expérimentale a été mise en place pour répondre à des réclamations de la part des utilisateurs qui voulaient programmer en Vala sans avoir de dépendances envers la GLib. Ainsi, il est possible d’appeler le compilateur avec la syntaxe suivante :

valac --profile posix

ce qui a pour conséquence de réduire le jeu de bibliothèque par défaut à celles disponibles dans la classe POSIX. Cela permet de limiter les dépendances du programmes, mais beaucoup de types standard de Vala deviennent de ce fait indisponible; on sent bien que le langage n’a pas été pensé pour ça.

Conclusion

Pour résumer, je dirais que Vala correspond à ce qu’il annonce : un langage haut niveau pour faciliter la création d’applications Gnome. Dès que l’on cherche à sortir de ce cadre, on se retrouve confronté à des limitations ( qui ne sont bien sûr pas insurmontable ) :

  • Pour ceux qui ne cherche pas à travailler sur du code Gnome, embarquement de bibliothèques qui ne nous intéressent pas forcement. ( Bien que sur ce point, la GLib est plutôt standard sur les PCs ayant X d’installés )
  • Pour ceux qui cherchent un langage de haut niveau, le C est encore trop présent entre les lignes pour pouvoir l’oublier complètement. D’un autre côté, l’intégration du code C n’est pas toujours évidente puisqu’elle oblige à déclarer des bindings pour des fonctions standards.
  • Mais surtout, le fait que l’ensemble des fonctions de la libc ne soient pas encore disponibles oblige à mettre le doigt dans les bindings régulièrement.

Le langage est bien sûr encore amené à évoluer, et les points que je cite ici ne sont pas pour autant rédhibitoires. D’un point de vue totalement subjectif Je trouve le langage simple mais sans trop de saveur. Ça reste un langage objet qui n’est bien sûr pas révolutionnaire; on sent qu’il ne fait que reprendre les concepts des langages qui l’ont inspiré, mais le produit est cohérent, et d’après les benchs génère un code plutôt optimisé ( en rapport avec le temps que l’on pourrait passer à produire le même code en C ). Après, je ne prend pas le même plaisir à programmer en Vala qu’en python ( j’avais bien dit que j’étais subjectif ^^ ).

Cela dit, pour moi, qui ne suis pas un développeur Gnome, je suis plus intéressé par la possibilité d’avoir un langage haut niveau qui reste très proche du C, avec les performances qui vont avec; si le prix pour cela est une dépendance vers la GLib, ça reste un coût sommes toutes assez faible.

Mettre en place un environnement sftp chrooté

Jeudi 8 avril 2010

La demande

Ma copine m’a demandé de trouver une solution simple pour échanger des fichier avec sa sœur, msn posant des problèmes… J’ai pensé à mon serveur ssh et mettre en place une connexion sftp pour ça. Sur le principe cela a été adopté avec une petite présentation de filezilla (je ne sais pas s’il existe des clients sftp intégrés sous windows ?), j’ai donc commencé à mettre en place le système.

De mon côté, la condition principale est de n’autoriser les connexions que par clef publique ( pas de mot de passe ),  ma copine a tenu à ce que sa sœur ne puisse pas accéder aux documents présents dans son home, et du mien à ce que l’on ne puisse pas pour autant se promener dans l’arborescence du serveur : il va donc falloir chrooter l’environnement.

Il existe pas mal de documentation la dessus sur internet, mais je me suis souvent retrouvé face à des exemples incorrects ou incompatible avec le fait de passer par une clef publique, je vais donc détailler les problèmes rencontrés.

Le compte + clef publique

La première étape est de créer le compte, cela se fait assez simplement :

# adduser ${user}

Création de la clef ssh avec puttygen
et en répondant aux questions par défaut… Vient ensuite la clef publique : filezilla gère les clefs privés au format ppk ( putty ) et je n’ai pas trouvé d’outil pour les générer sous windows. Je suis donc passé par wine + puttygen pour créer la clef. Une fois celle-ci crée, on enregistre la partie publique et la partie privée de la clef.

La clef publique va être enregistrée dans le fichier ${user}/.ssh/know_host sur le serveur pour autoriser le client à s’y connecter. La clef privée sera enregistrée de son côté au format ppk pour être utilisée par filezilla (il est possible à partir de ce fichier de générer une clef privée de type openssh ).

Intégrer la clef privée dans FileZilla

Il faut ensuite intégrer la clef privée dans filezilla en passant par les paramètres : elle sera automatiquement lue à la connexion ( il faut choisir «interactive» dans le type d’authentification ). ( Attention : sous windows j’ai rencontré des problèmes avec un répertoire contenant des accents, la clef semblait être lue, mais la connexion ne se faisait pas pour autant. )

Chrooter l’environnement

Aujourd’hui il est possible de chrooter nativement un environnement sftp avec openssh. Il faut pour cela mettre en place une condition sur l’utilisateur ( ou le groupe ) pour faire le chroot :

Match user ${user}
   ChrootDirectory /var/chroot/
   X11Forwarding no
   AllowTcpForwarding no
   ForceCommand internal-sftp

Dans cet exemple le chemin /var/chroot sera utilisé comme racine lors des connexions sftp. Ce répertoire doit être détenu par root:root et avoir les droits 755. Cela veut dire que si notre utilisateur à pour répertoire home /home/${user}, il se retrouvera dans /var/chroot/home/${user} lors des connexions sftp. Il est nécessaire de conserver le répertoire home de l’utilisateur pour que ssh accepte une connexion par clef. En effet, lorsque l’utilisateur va se connecter, ssh va lire dans son répertoire personnel pour lire le fichier .ssh/know_host et autoriser ou non la clef qui se présente. Ce qui signifie que si l’on modifie le répertoire personnel, il faut aussi déplacer cette arborescence ( hors de question dans ce cas de mettre / comme racine de l’utilisateur ).

À noter : j’ai préféré faire le match sur le nom de l’utilisateur plutôt que sur son groupe ( le groupe sera utilisé par ailleurs ). Dans le cas où nous avons plusieurs utilisateurs, il est possible de les mettre à la suite ( séparés par des virgules ).

J’ai vu de nombreux tutoriaux qui indiquent comme répertoire de chroot « /home/%u » ( le répertoire de l’utilisateur standard ), et qui demandent de changer le répertoire de login de l’utilisateur par « / ». Je pense que c’est une très mauvaise idée : d’une part parce que cela oblige à déposer les clefs à la racine du serveur, mais aussi à cause de la contrainte d’openssh demandant à ce que le répertoire root soit détenu par root : cela veut dire que l’utilisateur n’a pas le droit de déposer de fichiers ou de créer de répertoires dans son propre home !

Le plus simple est donc de prendre un autre répertoire pour l’échange, et laisser le home de l’utilisateur pour la configuration. ( Cela permet aussi d’être sûr que le répertoire .ssh ne sera pas effacé par erreur par l’utilisateur… ) J’ai donc mis un lien symbolique pour lier le /home de l’utilisateur avec son répertoire d’échange :

# mkdir /home/${user}/echanges
# ln -s /var/chroot/home/${user} /home/${user}/echanges

On retrouvera ainsi la possibilité de voir les fichiers déposés en passant par le /home de l’utilisateur ( même si ce dernier ne pourra pas y aller… )

Isoler l’environnement

Maintenant que nous avons empêché l’utilisateur de se balader sur l’ordinateur, nous allons l’empêcher de se balader dans les autres répertoires des utilisateurs : cela se fait en une ligne de commande (pour chacun des répertoires que nous allons ouvrir en sftp : )

# for fichier in /var/chroot/home/*; do chmod o-r ${fichier}; done

Et voilà ! Les utilisateurs peuvent voir qu’il existe d’autres comptes que le leur, mais ne peuvent pas y accéder.

Autoriser le partage

Maintenant que nous avons fermé les droits de manière générale il nous reste à autoriser le partage des fichiers ( après tout c’était le but de la demande !) de manière plus fine. Cela implique pour moi deux choses :

  1. permettre à un autre utilisateur d’accéder aux données présentes
  2. permettre à un autre utilisateur de déposer ( ou de supprimer des donnée )

Pour le premier point, c’est facile il suffit d’ajouter l’utilisateur A au groupe de l’utilisateur B :

# usermod -a -G ${user} ${un_autre_utilisateur}

Et l’utilsateur un_autre_utilisateur pourra donc accéder à l’ensemble des fichier pour les lire ( et éventuellement les rapatrier chez lui).

Pour le second point ( possibilité d’écrire et modifier ) c’est un peu plus compliqué; en gros nous voulons que les fichiers déposés par sftp dans le répertoire de l’utilisateur ait comme groupe d’appartenance celui du propriétaire du répertoire ( quel que soit l’utilisateur qui dépose ) et qu’ils soient modifiable par le groupe ( g+w ) du propriétaire.

Par exemple : l’utilisateur A dépose un fichier dans le répertoire d’échange de l’utilisateur B. Il faut que les droits de ce fichier se présentent ainsi une fois le transfert terminé :

$ ls -l fichier
-rw-rw----  1 utilisateurA utilisateurB

( ainsi l’un et l’autre pourront supprimer le fichier ).

Pour cela nous allons utiliser une « bidouille » de l’os : le sgid bit. Derrière ce nom barbare se trouve un marqueur qui permet de fixer le droit de tous les fichiers qui seront créés dans le répertoire ( plus d’info ici ). Pour le déterminer on passe par chmod :

# chmod g+s /var/chroot/${user}

Cela détermine bien quel est le groupe qui sera propriétaire du fichier, mais cela ne donne pas à ce groupe le droit de le modifier pour autant ! Sous linux, c’est la commande umask qui permet de déterminer les droits des fichiers. Le problème est qu’il s’agit d’une commande lié à l’environnement de l’utilisateur, et non pas aux répertoires sur lesquels nous travaillons ( à moins de passer par les ACLs mais cela est déjà assez compliqué comme ça… ). Ici, nous sommes dans un environnement sftp, sans shell de login, donc sans possibilité d’exécuter la commande directement, il faut que ce soit le serveur sftp qui le configure. J’ai trouvé énormément de documentations ( la plupart des bidouillages ) pour contourner le problème, mais la solution la plus simple vient de la dernière version d’OpenSSH (5.4 ) sortie le 8 mars dernier.

Exemple de configuration

Une nouvelle option sur le serveur sftp permet d’indiquer quel est l’umask qui sera appliqué ( dans notre cas 002) : dans le fichier/etc/ssh/sshd_config nous allons configurer les paramètres par défaut du serveur sftp :

Remplacer :

Subsystem sftp /usr/lib/openssh/sftp-server.sh

par :

Subsystem sftp /usr/lib/openssh/sftp-server -u 002

Pour définir les droits umask qui seront appliqués par défaut pour toutes les connexions sftp par défaut. Ce paramétrage est à redéfinir pour les paramétrages personnalisés ( bloc Match ) :

ForceCommand internal-sftp -u 002

Conclusion

Nous avons un environnement bien hermétique, pouvant gérer l’augmentation du nombre de compte ( il suffit de refaire les chmod dans notre environnement chrooté  à la création du compte ), et hermétique. Le paramétrage côté serveur est effectivement assez lourd au début, mais je pense que la mise à jour ne demande pas trop de travail, et on gère les droits de manière assez fine ( en passant par les groupes ce qui me semble être dans la mentalité unix ).

Pour le client, il n’y a pas grand chose à paramétrer ( récupérer la clef et l’intégrer ), et il n’y a aucun risque que celui-ci vienne casser son paramétrage. On peut même sauvegarder sa clef privée dans son home (le vrai ), au cas où il perdrait le fichier.

Les utilisateurs invisibles de Linux

Mercredi 17 février 2010

Bonjour à tous, pour mon premier article sur le planet-libre, je voudrais faire part d’une réflexion qui m’interpelle depuis un moment concernant l’univers Linux : le fait que les utilisateurs non administrateurs soient exclus de toute la documentation/prise en main que l’on peut trouver sur le système. Je ne donne ici que quelques aspects de cette réflexion mais je pense qu’elle touche l’ensemble des participants au monde du libre.

La plupart des articles que l’on peut voir sur le net qui concernent l’utilisation du PC sous Linux restent limités à un point : souvent ils oublient le fait que plusieurs utilisateurs puissent être enregistrés sur le PC, et que tous ne soient pas forcément des administrateurs ( ceux qui peuvent avoir des droits root sur la machine ).
Pourquoi donc ? Est-ce que cela signifie que la plupart des linuxiens sont les seuls à utiliser le PC ? C’est possible, mais là n’est pas mon sujet. Je pense que le problème est que les utilisateurs sont pour l’instant invisible de la littérature sur Linux que l’on peut trouver sur le net. À la fois invisible du côté des distributions, et invisible du côté des communautés.

Le problème se retrouve présent dans deux aspects : d’une part dans la documentation s’adressant aux administrateurs, et d’autre part dans la documentaiton s’adressant aux utilisateurs.

Si l’on suit les manipulations que l’on peut trouver un peu partout sur le net, on trouve souvent des modifications qui ont pour conséquences de modifier la configuration générale du système, et l’on trouve plus souvent des modifications dans /etc/ que dans ~/.config/

Suivre les besoins des utilisateurs

Tous les utilisateurs n’utilisent pas forcément l’ordinateur de la même manière et il faut prévoir quels sont leurs besoin avant de se lancer dans une opération générale.
Par exemple, il n’y a pas longtemps était paru sur le planet-libre un article sur privoxy qui se terminait par une manière élégante d’utiliser privoxy sans configuration supplémentaire[1]. Or privoxy est lent pour traiter les sites puisant des ressources un peu partout — par exemple google news ou planet-libre (!) et se transformer en inconfort pour l’utilisateur.

Les mises à jour

Faire une mise à jour est toujours quelque chose de périlleux, et l’on ne sait pas forcément comment le système va réagir; entre le logiciel qui ne fonctionne plus car sa configuration a changé ou celui qui ne fonctionne plus car un bug a été introduit dans la nouvelle version, les risques sont possibles ( je n’ai par exemple pu plus lire de dvd lors de la mise à jour du noyau 2.6.30[2]… )
Je ne veux pas relancer le débat sur le packaging des distributions ( rolling release contre version fixes) mais le problème doit être posé : comment être sûr en faisant une mise à jour que l’on ne va pas casser tel composant ?

En plus des modifications générales sur la configuration que peuvent introduire les modifications, on peut se retrouver dans la situation inverse : l’utilisateur n’a pas le droit de visualiser les fichiers de logs, d’installer un paquet ou de modifier un fichier de configuration et ne pourra donc pas suivre la documentation qu’il peut trouver ici et là sur le net.

Pouvoir utiliser ses propres applications ?

Les distributions n’ont pour l’instant pas de solutions pour gérer l’installation de paquets par un utilisateur normal ( qui irait s’installer dans /opt// par exemple ), pouvant être installés sans droit root, et ne pouvant être exécutés que par l’utilisateur ayant fait son installation.

Utiliser des commandes non root

En fait, ce système que l’on nous décrit ouvert ne l’est réellement que si l’on est admin dessus. Pour les autres, la manipulation se limite à bash, python…
Dans la documentation, on trouve même des exemples demandant à l’utilisateur d’être root alors qu’une commande équivalente peut être lancée par un utilisateur normal ( par exemple $netstat -ie au lieu de #ifconfig )

Ce problème de l’utilisateur non root est pour l’instant contourné ( par exemple en configurant sudo dès l’installation ), mais il reste posé, et n’est jamais attaqué de front.

Le fait que cette situation ne soit jamais évoquée est pour moi significative de l’utilisation faite de linux aujourd’hui : bien loin du grand public. Nous sommes tous ici des utilisateurs bidouilleurs, et ne voyons pas forcément une utilisation quotidienne d’un utilisateur standard. Je ne veux pas en faire une généralisation sur l’avenir de Linux et une remise en cause nécessaire. Je pose juste ici un constat sur une situation qui est pour moi, encore trop souvent invisible.

[2] Artisan Numérique » Se prémunir des « SpyWebs » avec Privoxy
[1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=557340

Un système de backup automatique

Dimanche 18 octobre 2009

On le sait tous, il faut faire des sauvegardes de manière régulière. On le sais également, pour que celles-ci se fasse sur le long terme, il faut que celles-ci se fassent de manière automatique, et sur un autre support que le PC que l’on souhaite sauvegarder. Le problème qui se pose est le suivant : comment concilier ces deux conditions sur un PC de bureau ( ne disposant donc pas d’une série de serveur allumés en permanences et prêt à recevoir nos sauvegardes en continue… ) ?

Pour répondre à tout cela, nous allons mettre en place un système de backup sur disque dur externe, qui se lancera à chaque fois que notre disque sera monté. À chaque fois que le disque dur sera allumé, la sauvegarde s’enclenchera. Cela ne garantie pas, bien sûr que les sauvegardes se feront à un intervalle régulier, mais cela garantie au moins que nous n’aurons pas à nous en soucier. Pour cela nous allons utiliser les outils qui sont disponibles sous un environnement Linux : rsync et hal. Cet article nous présente une base pour faire notre sauvegarde Une sauvegarde améliorée avec rsync. Nous allons juste devoir le modifier un petit peu pour répondre à un problème qui arrive souvent avec les périphériques USB : selon que d’autres périphériques sont déjà montés ou non, nous ne savons pas dans quel répertoire nous allons nous trouve. Il va donc falloir mettre en place une ligne pour récupérer le répertoire dans lequel nous sommes. Il ne nous reste plus qu’à trouver le moyen de l’éxécuter automatiquement pour cela nous allons utiliser halevt. Le script est disponible ici

Comme son nom l’indique, halevt est un gestionnaire d’évènements pour hal. Hal est un gestionnaire d’évènement matériel sous Linux; il envoie des informations à chaque fois que des informations sont envoyées depuis les composants. Cela permet de détecter le branchement d’un périphérique USB et de le monter sur le bureau ( et qui nous simplifie grandement la vie aujourd’hui !!!). Halevt est un démon à l’écoute des informations qui nous sont envoyées par hal, et d’activer des actions en conséquence : par exemple pour lancer l’antivirus sur la clef usb, reconfigurer le mappage du clavier en fonction de la marque que l’on branche etc. Pour notre part, nous allons nous contenter de lancer un script (celui du backup mentionné plus haut ).

Pour commencer nous allons devoir identifier le lecteur à mettre sous surveillance : inutile de se baser sur les noms de montage habituels ( /dev/sda par exemple ) en effet en fonction des périphériques déjà branchés nous n’allons pas obtenir la même configuration. Nous allons utiliser les point de montage défini dans /dev/disk/by-uuid qui permet d’obtenir l’identifiant de notre disque (et qui sera repris par la suite dans la configuration de hal ). Une fois que nous avons relevé quel est le disque concerné, il faut mettre en place une entrée pour notre évènement dans la configuration de halevt :

<halevt:Device match="hal.block.device &amp; hal.block.is_volume = true &amp; hal.volume.uuid = fd20536f-7b80-4a80-8c3d-b5bebe8fb484">
<halevt:Property name="hal.volume.is_mounted">
<halevt:Action value="true" exec="bash $hal.volume.mount_point$/chemin/script/backup-ssh.sh"/>
</halevt:Property>
</halevt:Device>

Cela si halevt est exécuté avec les droits de l’utilisateur lançant le backup. Si on le fait tourner en démon, il faut trouver une autre solution ( sur mon poste j’ai utilisé sudo, mais on peut très bien se baser sur le sticky bit pour donner les droits au script ). De même, dans la configuration mise en place, le script se trouve sur le disque de stockage ( de manière à pouvoir le lancer à la main si le démon n’est pas disponible ), cela peut être adapté en fonction de chacun…

Dans le cas d’une configuration multi-utilisateur, je pense qu’il est nécessaire de passer par un script qui lance les différentes sauvegardes sous le bon groupe de l’utilisateur à chaque fois. ( Ce qui en plus permet d’éviter le problème du sudo ) mais je n’ai pas eu besoin d’aller jusque là pour l’instant ! À vous d’adapter ce que je vous propose en fonction de votre configuration !

Un pilote wiimote sous Linux en python

Jeudi 19 février 2009

La wiimote est la manette de contrôle de la console wii de Nintendo, un outil merveilleux dont voici un petit résumé de ses fonctionnalités :

  • Accéléromètres
  • Caméra infrarouge
  • Émetteur/Récepteur Bluetooth
  • 11 boutons

( voir le détail sur la page de wikipédia )

En disposant d’un récepteur bluetooth, il est possible de se connecter à la télécommande et de récupérer ses informations, mieux, avec le projet cwiid, on peut transformer la wiimote en souris !

Ainsi selon le mode dans lequel se trouve la télécommande, on contrôle notre curseur en inclinant la télécommande, ou en la pointant vers une source infrarouge

La source infrarouge pouvant être la sensor bar fournie avec la console, ou une source externe, bougie lampe ou tout ce dont pouvez disposer diffusant de la chaleur à partir d’un point unique

Le pilote fourni avec cwiid fonctionne mais n’est pas optimisé. Il arrive que la souris parte dans une direction incontrôlée, ou de ne pas pouvoir accéder à certaines parties de l’écran.

La faute est due au pilote intégré qui se contente juste de placer le pointeur sur la source infrarouge, avec quelques petites optimisations.
En effet, le capteur de la wiimote nous indique quelle est la position de toutes les sources infrarouges perçues ( et nous fourni également des informations sur leur intensité ), mais la conversion en pointeur est laissée au pilote :
Quelle source choisir comme référence ?
Comment gérer les cas où une source est sortie du champ de vision ?
Comment réagir quand cette source revient dans le champ de vision ?

Tout ceci doit être pris en compte pour pouvoir offrir une ergonomie au curseur et faciliter le contrôle.

Heureusement pour nous le pilote nous donne la possibilité de réécrire nos propres moteurs, et donc de gérer nous même la manière dont on veut que la souris réagisse. Nous avons même le choix dans le langage ! En effet, nous pouvons choisir entre offrir un plugin compilé ( le pilote est écrit en C ), ou l’écrire en python. C’est cette deuxième option que je vais présenter dans les articles qui suivront.

Suite : mise en pace du plugin (EN)

Mettre en place une solution de chiffrage avec authentification forte

Vendredi 7 novembre 2008

Voici une méthode que j’ai mis en place pour protéger l’accès à mon répertoire /home via Cryptsetup. Il existes de nombreux tutoriels expliquant comment créer une partition chiffrée, je ne vais pas détailler cela ici. L’intérêt du script que je propose ici est qi’il se lance au moment du login, et qu’il va chercher le mot de passe sur une clef USB.

Charger le mot de passe contenu dans la clef USB

Il suffit juste de l’insérer avant de se logguer, et de la retirer une fois l’authentification réussie.

Voici le script en question

#!/bin/sh

#Si la clef n'est pas insérée, refuse le login
[ -b /dev/disk/by-uuid/chemin-de-la-clef ] || exit 1

if [ -b /dev/mapper/home ]
	then
		#Si la partition est deja montée, connecte
		exit 0
	else

		# Monte la clef
		mkdir /tmp/clef/
		mount /dev/disk/by-uuid/chemin-de-la-clef /tmp/clef/ 2>/tmp/out

		# Déchiffre la partition
		/sbin/cryptsetup luksOpen -d /tmp/clef/clef /dev/disk/by-uuid/chemin-de-la-clef home 2>>/tmp/out

		# Démonte la clef, elle peut maintenant être retirée sans pb
		umount /tmp/clef
		rmdir /tmp/clef/

		mount -o defaults -t ext2 /dev/mapper/home /home
		exit 0

fi

Bien sûr, il faut que la clef soit contenue dans le fichier clef sur le périphérique USB.

Mettre le script au login de l’utilisateur

Maintenant, 2ème étape, il s’agit de lancer ce script au moment où l’utilisateur vient de se logguer.
Comme je passe par un login manager sur mon portable ( GDM ), j’ai choisi d’utiliser ses ressources pour lancer le script. En effet, GDM possède des scripts qui sont lancés aux différents moments de la connexion. Ce qui nous intéresse ici se trouve dans le fichier : /etc/gdm/PostLogin/Default
Il suffit d’y coller notre script ( ou d’y faire appel ) , et notre partition sera activée automatiquement lors de la connexion ( et seulement si le mot de passe est valide ).
On peut obtenir des paramètres de la part de GDM dans ce script, nom de l’utilisateur qui se loggue, répertoire de login etc, cela permet de personnaliser notre script si on le souhaite..
Un code de retour en erreur refusera le login, que le mot de passe entré soit bon ou non…

Une gestion avancée de fail2ban

Lundi 15 septembre 2008

Beaucoup d’articles sont déjà parus sur l’utilisation de fail2ban pour protéger son ordinateur. Je vais parler ici d’une utilisation avancée de fail2ban, couplé avec le pare-feu iptables dans le but de faire plein de joli de choses avec ceux qui tentent d’accéder à nos Pcs !

Pour rappel, fail2ban permet de bloquer certaines IPs en fonction de ce que les logs renvoient comme messages. Il est possible de déterminer les ports sur lesquels les IPs seront bloquées et la durée du blocage. En ce qui concerne les filtres qui déclencheront ou non le blocage, cela se base sur des regex, et on peut déterminer le nombre de tentatives avant qu’un blocage ne soit appliqué.
Dans l’esprit du projet, fail2ban empêche les attaques par force brute, mais nous allons voir qu’il est tout à fait possible de l’utiliser dans d’autres fins.

Créer de nouvelles règles de filtrage

Dans un premier temps, nous allons mettre en place une nouvelle règle de blocage pour, par exemple, bloquer les IPs en fonction des codes d’erreurs d’apache.

Mettre en place une nouvelle règle se fait de manière très simple, il suffit de créer un fichier contenant la regex à appliquer, et de mettre une référence vers ce fichier dans la configuration de fail2ban.

Dans notre cas, pour bloquer les IPs ayant générés une erreur 403 ou une erreur 401 dans apache, notre regex se présentera ainsi :

failregex = :80  .* ".*" 403 = :80  .* ".*" 401

(Celle-ci est bien sûr à adapter en fonction de la manière dont vous affichez vos logs de connexions. )

Dans le fichier de configuration de fail2ban ( /etc/fail2ban/jail.conf ), nous allons demander la lecture de ce fichier en indiquant quelques paramètres supplémentaires :

[apache-block]
enabled = true #Oui on active
port = http #On ne bloque que le port 80
filter  = apache-block # le nom du fichier que l'on a créé juste avant
action  = %(action_)s
logpath = /tmp/log/apache*/*access.log
maxretry = 1 #Nombre de tentatives
banaction = iptables-redirect # L'action à appliquer sur l'IP
bantime = 3600 # Le temps pendant lequel l'ip sera bannie.

Créer de nouvelles actions

Une fois que fail2ban aura lancé une procédure de blocage sur une connexion, il va lancer un script contenant les actions à réaliser sur cette IP. D’habitude ce script contient une règle iptables qui bloque l’adresse, et une autre règle qui supprime ce blocage.
Nous allons maintenant jouer avec iptables pour réaliser quelques effets intéressant avec nos IPs à bannir :

  • Relancer la durée du blocage :
  • Par défaut, fail2ban retire le blocage sur l’IP une fois que la durée spécifiée est écoulée. Je trouve ceci limité car cela n’empêche pas l’attaquant de continuer ses attaques et se retrouver prêt à refaire une attaque dès que cette durée est écoulée. De plus, cela peut donner une information sur la durée pendant laquelle nous filtrons son adresse.
    iptables propose un module, modrecent, permettant de bloquer une IP pendant une durée déterminée, et de réinitialiser cette durée si jamais une nouvelle connexions venait à être réalisée durant cette période.
    Pour ceci nous allons devoir une règle iptables, en dehors de fail2ban, qui consistera à bloquer une IP pendant telle période :

    Dans fail2ban, nous allons créer un nouveau fichier action, qui se présentera comme suit :

     #On crée une nouvelle table
    actionstart = iptables -N fail2ban-<name>
    #On bloque les connexions 2 fois sur 3
    iptables -A fail2ban- -m statistic --mode random  --probability .33 -j REJECT --reject-with icmp-host unreachable
    iptables -A fail2ban-<name> -j DROP
    #On insère une nouvelle règle qui met à jour le compteur à chaques nouvelles tentatives tant que le délai n'est pas écoulé
    iptables -I INPUT -p  <protocol> -m multiport --dports  <port> -m recent --update --seconds 360000 --name fail2ban-- -j fail2ban-<name>
    #Pour bannir une IP, il suffit de l'écrire dans le fichier de configuration de mod-recent
    actionban = echo  <ip> > /proc/net/ipt_recent/fail2ban-<name>
    
  • Mettre un message d’alerte :
  • On peut décider d’annoncer à notre utilisateur bloqué que nous avons banni son IP. Cela peut être utile si nous avons mis en place des règles de filtrage très strictes et qu’un utilisateur peut se retrouver bloqué sans avoir tenté la moindre intrusion ( mieux vaut être trop prudent que pas assez )
    Pour cela, nous allons avoir besoin d’un service qui consistera à afficher le texte sur demande. Hors de question de demander ça à apache ou autre serveur web, nous allons mettre en place notre propre serveur web, qui présentera une page statique, toujours identique.
    socat et tout désigné pour cela. Dans notre exemple nous allons le faire tourner en tant que serveur, sur un port ouvert, et avec des droits limités. Notre règle iptables consistera juste à rediriger les connexions entrantes sur le port 80 vers le port où l’on fait tourner socat.

    sudo -u nobody socat tcp4-listen:6666,reuseaddr,fork exec:"cat /etc/apache2/banned.html" &
    

    et la règle iptables à mettre en place :

    #On crée la règle sur la table de préroutage :
    actionstart = iptables -t nat -N fail2ban-<name>
    iptables -t nat -A fail2ban-<name> -j RETURN
    iptables -t nat -I PREROUTING -p  <protocol> -m multiport --dports <port>-j fail2ban-<name>
    iptables -N fail2ban-<name>
    iptables -A fail2ban-<name> -j RETURN
    iptables -I INPUT -p   <protocol> -m multiport --dports   <port> -j fail2ban-<name>
    

    et pour lancer l’action, là encore, on simule une perte de paquet pour ralentir le temps d’affichage de la page

    actionban =  iptables -t nat -I fail2ban-<name> 1 -s  -p tcp -m multiport --dports  <port> -m statistic --mode nth --every 3 -j REDIRECT --to-port 6666
    iptables -I fail2ban-<name> 1 -s  -j DROP
    

    Les règles d’unban et de stop se font en symetrique de ban et start, en supprimant des règles crées.

    Voilà, cela permet de mettre en place une sécurité personnalisée et adaptée, qui sort déjà des outils et configuration standards ( ce qui est toujours une bonne chose en matière de sécurité ). Les exemples que j’ai donné ne sont que des suggestions, et il possible de faire beaucoup d’autres choses avec un peu d’imaginations. Je vous renvoie au manuel d’iptables qui présente la liste de tous les modules existants, et de regarder un peu les paramètres disponibles parmi les fichiers de configuration de fail2ban. Mon seul regret est qu’à ce jour, ce programme ne gère pas encore les Ip en v6, mais ça n’est – pour l’instant – pas encore critique..