Skip to content

Linux Attitude

Le libre est un état d'esprit

Réparer une debian 

Sep 1 Par peck

Niveau :      
Résumé : debsums ; dpkg -S ; apt-get install --reinstall

Si vous avez bidouillé une debian en installant un logiciel sans passer par dpkg par exemple, ou si quelqu'un vous a fait une mauvaise blague et qu'il y a des problèmes dans les logiciels installés, alors il y a un moyen pour vérifier si le problème vient d'un fichier modifié :

$ apt-get install debsums
$ debsums -c

Debsums est un outil debian qui fait un hash de tous les fichiers installés par des paquets debian et le compare au hash provenant du paquet original. L'option -c permet de lister tous les fichiers qui posent problème. Cela ne vous prémunit pas des attaquants qui pourraient aussi modifier la base des paquets, mais c'est utile pour toute manipulation plus ou moins volontaire du système.

Une fois la liste des fichiers modifiés récupérée, il nous reste à trouver dans quel paquet se trouvait le fichier en question :

$ dpkg -S /bin/ls # nous indique que ls est dans le paquet coreutils

Et maintenant passons à l'étape réparation :

# retélécharge et réinstalle tous les binaires d'un paquet déjà installé
$ apt-get install --reinstall lepaquet

Et pour ceux qui voudraient faire une réinstallation complète de leur distribution :

$ dpkg --get-selections | grep install | awk '{print $1}' | xargs  apt-get install --reinstall --yes

Mais comme dit le commentaire ci-dessous cela ne marche que si vous ne faite pas de pinning et si votre distribution est à jour. La commande suivante permet de ne pas changer les versions des paquets :

$ dpkg -l | grep ^ii | awk ‘{print $2″="$3}’ | xargs apt-get install -reinstall -s -t release-cible

Les dates de fichier 

Aug 22 Par peck

Niveau :      
Résumé : atime, ctime, mtime, crtime

Je constate que je n'ai jamais fait d'article sur les dates de fichier, c'est bien dommage car on me pose souvent la question. Voila qui va régler ce malentendu.

ctime et mtime

Unix depuis très longtemps ne stocke pas la date de création d'un fichier (contrairement à windows). A la place il stocke 3 dates au format timestamp unix. Les plus difficiles à comprendre sont mtime et ctime. Mais en réalité c'est simple, il suffit d'apprendre leur nom :

  • mtime : modification time, date de dwœernière modification du contenu du fichier
  • ctime : change time, date de dernier changement des métadonnées du fichier (par exemple le propriétaire)

Rien que pour vous, j'ai un moyen antimnémotechnique : M comme Contenu et C comme Métadonnée. Je ne sais pas vous, mais moi ça marche.

Attention, la modification du contenu d'un fichier modifie sa date de modification, qui est une métadonnée ... Elle modifie donc aussi sa date de changement. En conséquence de quoi on a toujours ctime >= mtime.

atime

Historiquement unix a eu l'idée originale de stocker la date de dernier accès à un fichier, le atime (access time). Ça a l'air cool, mais en réalité c'est une fausse bonne idée car elle interfère avec la notion fondamentale de lecture. En effet, pour mettre à jour le atime, chaque lecture impliquera une écriture.

Plus le temps passe plus le atime est problématique. Ça a commencé avec les sites web qui avaient des problèmes de performance à cause de la mise à jour du atime lors de la lecture des fichiers. On a alors inventé la possibilité de désactiver le atime au montage (option noatime).

Puis ça continue avec le SSD, écrire le atime implique une écriture toute petite à chaque lecture de fichier, ce qui implique la modification d'un inode et donc d'un block disque. Et avec le fonctionnement du SSD cela implique la lecture et la réécriture d'un gros bloc de données, donc des problèmes de performances. Puisque le atime reste utilisé par quelques applications (aussi rares soient-elles), on a inventé l'option relatime, qui ne met a jour le atime que s'il était égal ou antérieur au ctime. Ça permet de détecter une lecture depuis la dernière modification tout en faisant sauter un grand nombre de mises à jour du atime (mais pas toutes). C'est similaire à l'option noatime, mais ça permet aux applications, comme mutt, de savoir si un fichier a été lu depuis sa dernière modification.

Le problème suivant intervient avec les snapshots, lorsqu'on utilise des snapshots de disques (à travers LVM ou à travers un serveur de VM), on se retrouve à mettre à jour le disque de snapshot et donc occuper de l'espace disque rien qu'en le lisant. Le summum étant atteint avec btrfs. Si vous faites un snapshot avec btrfs il ne vous prendra quasiment aucune place sur le disque. Si vous faites un find sur ce snapshot, la mise à jour du atime va quasiment remplir l'espace disque du snapshot d'une copie complète des données originales.

Conclusion, oubliez le atime ...

crtime

Comme je vous l'ai dit, windows stocke la date de création, c'est donc tout naturellement que les linuxiens ont voulu la même fonctionnalité. C'est enfin chose faite avec ext4. En effet, ext4 a profité de l'agrandissement de la taille des inode (de 128 à 256) pour stocker plus d'informations, celles-ci incluent la date à la nanoseconde près et la date de création.

Cool, mais comment fait-on ?

Malheureusement, les outils habituels n'ont pas encore été mis à jour pour récupérer cette information. Il nous faut donc le faire à la main :

# d'abord on récupère le numéro d'inode du fichier
$ stat --format "%i" /chemin/vers/le/fichier
# puis on récupère la date de création
$ debugfs -R 'stat <123456>' /dev/partition | grep crtime

Notez que ça ne marche que sur des partitions ayant des inodes de 256 octets, ce qui exclue les systèmes de fichiers mis à jour depuis ext2 et ceux venant d'un ext3 avec des inodes de 128 octets.

A quoi ça sert ? 

Jul 2 Par peck

Niveau :      
Résumé :

Petit problème pour le plaisir.

Problème

Nous voulons créer un algorithme, voire une formule arithmétique simple, nous permettant de générer des nombres entiers ayant la propriété suivante : pour tout x, l'ensemble des chiffres de l'ensemble des nombres générés inférieurs à x doit être distribués équitablement.

Équitablement signifie que chaque chiffre doit apparaître autant de fois que chaque autre plus ou moins le nombre de chiffres de x.

Prenons un exemple pour bien me faire comprendre :

  • Soit x = 100
  • Prenons l'ensemble des nombres entiers inférieurs à x : 0-99
  • Écrivons les sur 2 chiffres (1=01) et prenons tous les chiffres

Nous avons alors 20 fois le chiffre 0 (10 fois coté dizaines, 10 fois coté unités), 20 fois le 1 ...

Donc c'est équilibré, nous sommes contents.

Prenons x = 99, nous avons tous les nombres sauf 99, donc 20 chiffres de chaque sorte et seulement 18 fois le 9. Deux de moins que les autres or 2 est le nombre de chiffres de x.

Donc c'est équilibré, nous sommes contents.

Prenons x=90, nous n'avons que 9 fois le 9 et 19 fois le 0, ce n'est pas équilibré.

Par conséquent la formule que nous cherchons c'est pas f(x)=x mais quelque chose qui prend une suite logique de nombres mais pas dans l'ordre naturel, comme le fait le code de gray.

Mais pourquoi ?

Pendant que vous réfléchissez, je vais vous expliquer la raison du problème. Lorsque vous câblez une salle machine, vous utilisez de nombreux câbles. Pour une bonne gestion de ces câbles, qui vont rapidement être emmêlés avec d'autres une fois branchés, il faut les identifier pour repérer facilement les 2 bouts d'un même câble.

Une première solution est d'utiliser patchsee, sympa quand on a les moyens et qu'on n'a encore installé aucun câble, mais elle ne marche pas pour notre stock de câble existant.

Une autre solution est d'étiqueter les câbles, mais les étiquettes papier même plastifiées ont tendance à s’abîmer, s'effacer et sont difficilement repérables de loin. On les remplace donc parfois par des clips de repérage.

Malheureusement, nous sommes soumis à la terrible loi de Benford. Appliquée au clips, elle nous condamne a acheter beaucoup de 1, un peu moins de 2, encore moins de 3 etc ... Or ils sont vendu par lots ayant la même quantité de chaque chiffre, drame lorsque vous voulez étiqueter 200 ou 2000 câbles.

La solution : répartir les chiffres de façon à n'acheter que ce que vous consommez. C'est ce que que j'ai décrit d'une façon un peu plus formelle précédemment.

La réponse

Alors vous avez réfléchi ?

Évitez de vous précipiter sur la solution, elle est simple et vous pouvez la trouver.

J'ai dû faire plusieurs essais et quelques calculs pour trouver.

Il y a plusieurs solutions.

Mais très peu de solutions sont simples et faciles à expliquer à celui qui devra utiliser ce système après vous.

La solution que je propose ne nécessite pas de formule compliquée.

Vous avez trouvé ?

Voici ma solution :

  • 00, 11, 22, 33, 44, 55, 66, 77, 88, 99
  • 10, 21, 32, 43, 54, 65, 76, 87, 98, 09
  • 20, 31, 42, ...

Vous voyez le pattern ?

A un nombre à 2 chiffres N=(x)(y) j'associe le nombre M=(x+y)(y) en ne gardant qu'un seul chiffre à chaque opération bien sûr. A un nombre à 3 chiffres N=(x)(y)(z) j'associe le nombre M=(x+y+z)(y+z)(z) etc.

  • Pour faire le 35e nombre je prends le 5 (.5) j'ajoute 3 et je mets le résultat à gauche : 85
  • Pour faire le 125e nombre je prends le 5 (..5) j'ajoute 2 et je mets le résultat à gauche (.75) j'ajoute 1 et je mets le résultat à gauche : 875
  • Pour faire le 589e nombre je prends le 9 (..9) j'ajoute 8 et je mets le résultat à gauche (.79) j'ajoute 5 et je mets le résultat à gauche : 279

Les nombres sont équilibrés car pour chaque série de 10 on a 10 chiffres différents aux unités, 10 chiffres différents aux dizaines ...

De plus ça marche pour le nombre de chiffres que vous voulez, vous pouvez étiqueter 25000 câbles avec cette méthode. Et Vous pouvez même changer de nombre de chiffres en cours de route, coder les 100 premiers nombres sur 2 chiffres et les 900 suivants sur 3 chiffres comme avec les entiers naturels.

Conclusion

Il n'y a pas de petites économies !

D'ailleurs, à ceux qui utilise le codage des nombres naturels, je récupère gracieusement tous les 7, 8 et 9 dont vous n'avez plus usage ! Il me suffira d'adapter le codage en base 3 pour les réutiliser.

Les maths c'est utile parfois ...

Foireuwall DNS (bis) 

Jun 25 Par peck

Niveau :      
Résumé : ipset; IN A

Ceci n'est pas une amélioration de l'article précédent, mais un complément.

Un firewall basé sur le DNS

On veut être indépendant des ip utilisées par les gens que l'on filtre. On se propose cette fois de faire des règles de filtrage basées sur le forward DNS et non plus le reverse DNS.

Cette fois, on ne peut plus utiliser l'IP du paquet pour récupérer le nom de domaine, mais on peut mettre au jour automatiquement les règles de firewall en fonction d'un domaine défini et non plus avec des IP statiques.

Encore une fois, les précautions précédentes s'appliquent :

  • on base une règle sur quelque chose qu'on ne maitrise pas, voire qu'un attaquant pourrait maitriser : la base dns de la source
  • on devient dépendant du résolveur dns et donc de ses failles

Mais à la différence de la dernière fois, le dns est potentiellement sous contrôle d'un ami (si on parle de whitelist et non de blacklist). De plus on peut imaginer utiliser DNSSEC pour gagner en sécurité.

Changeons de technologie. Puisque nous ne faisons plus de reverse DNS, nous devons connaître à l'avance l'intégralité des domaines. Donc on ne peut plus avoir de regex ou de wildcard. Et puisque nous devons les connaître à l'avance, nous pouvons juste faire des requêtes, stocker les IP résultantes et les utiliser directement dans le firewall.

La technologie du jour s'appelle donc ipset. Elle permet d'utiliser un pool d'ip que l'on peut faire varier dynamiquement dans une règle iptables.

Iptables

Son usage est simple :

# on ne matche que sur l'ip source
iptables -A ... -m --match-set chezmoi.com src -j ...
# on matche sur un couple source/destination
iptables -A ... -m --match-set friendzone src -j ...

Ensuite il suffit de créer les set

ipset --create chezmoi.com iphash
# ip ipset create chezmoi.com hash:ip  (pour ceux qui ont une ancienne version d'ipset)
ipset --create friendzone iphash
# ip ipset create friendzone.com hash:ip  (pour ceux qui ont une ancienne version d'ipset)

Règles en live

Il ne nous reste plus qu'à mettre à jour les set dynamiquement, par exemple en interrogeant régulièrement les serveurs dns.

# on utilise un ipset temporaire pour que le firewall continue de fonctionner pendant nos opérations
ipset --create temp iphash

for rule in rules
do
    ipset --flush temp
    for i in domains[$rule]
    do
        host $rule | 
        xargs ipset --add $rule $ip
    done
    ipset --swap temp $rule
done

ipset --destroy temp

Il n'y a plus qu'a lancer ce script régulièrement grâce à notre ami cron.

Et voila !

Notez qu'il y a moyen avec ipset de matcher plusieurs adresses à la fois (ip, mac, source, destination), de matcher des réseaux et même de matcher des ports.

Foireuwall DNS 

Jun 22 Par peck

Niveau :      
Résumé : perl, libipq, IN PTR

Le problème

Les firewall ne proposent jamais de faire une règle qui couperait la connexion en fonction du domaine de l'appelant. C'est gênant car on aimerait bien pouvoir devenir indépendant de l'ip de notre partenaire.

Si on ouvre un accès à un ami, pourquoi devrait-il nous avertir lorsqu'il change d'ip alors qu'il a fait correctement son travail en mettant à jour son DNS.

En réalité il y a de bonnes raisons à cela, en effet le domaine ne se trouve pas dans le paquet il faut donc aller le chercher quelque part. Et cela implique :

  • qu'on base une règle sur quelque chose qu'on ne maîtrise pas, voire pire, qu'un attaquant pourrait maîtriser : la base dns de la source
  • qu'on devient dépendant du résolveur dns et donc de ses failles
  • qu'il est possible que le firewall empêche le firewall d'aller chercher l'info sur le serveur dns
  • qu'il faut attendre que le dns réponde et donc les performances d'un tel firewall risquent d'être catastrophiques

Les deux derniers problèmes sont purement techniques et ont donc une solution technique acceptable moyennant quelques compromis. Par contre les deux premiers problèmes concernent la sécurité et il faut donc garder en tête que si on met en place une telle règle, elle est là pour nettoyer les flux qui traversent notre firewall, mais qu'elle n'apporte que peu de sécurité par rapport à l'absence de règle.

La solution

Maintenant que nous savons qu'il ne faut pas le faire, voyons comment faire :-)

Tout d'abord il y a deux possibilités, se baser sur le forward DNS (IN A et IN AAAA) ou sur le reverse dns (IN PTR). Aujourd'hui je vous propose le pire des cas, le reverse DNS, puisque votre configuration est directement tributaire de la volonté de l'attaquant.

Commençons par un prototype, donc en perl, parce que je le veux bien.

Le point important ici est de faire la résolution dns en espace utilisateur. Pour cela il faut d'utiliser libipq, la bibliothèque permettant de communiquer entre l'espace utilisateur et netfilter la partie noyau du firewall linux.

Il nous faut donc :

  • libipq : IPTables::IPv4::IPQueue
  • parser les paquets ip : NetPacket::IP
  • faire des requêtes dns : Net::DNS

Et voici le script tout simple, le reste de l'article est en commentaire dans le script.


continue reading...

Une seule ip 

Jun 2 Par peck

Niveau :      
Résumé : ip link add link eth0 vlan1 type vlan id 1

Je suis de retour !

Désolé pour le lag ... mais je réponds aux commentaires.

Problème

Aujourd'hui, un problème qu'on m'a posé récemment. Comment faire lorsqu'on a un parc de box (routeur wifi, machine embarquée, ...) et qu'on veut pouvoir à tout moment se connecter physiquement sur son port ethernet et la configurer en utilisant ip (par ssh, snmp ...).

La première solution est d'avoir une configuration réseau immuable sur ces machines ET de répertorier d'une façon ou d'une autre un identifiant unique pour chacune de ces machines qu'on peut alors faire correspondre à une ip. C'est assez contraignant et ça impacte fortement la configuration réseau des machines. Ça risque de nous empêcher de réutiliser ce port pour communiquer dans un réseau existant le reste du temps.

La deuxième solution serait d'utiliser un protocole type zeroconf pour configurer automatiquement le réseau lorsqu'on se branche, l'inconvénient est de réussir à le désactiver lorsque la machine se retrouve dans son réseau de destination qui n'utilise pas nécessairement zeroconf tout en le gardant actif pour le configurateur.

Je vous propose donc une solution différente : l'ip unique. Toutes les machines à configurer ont la même IP. C'est bien beau me direz-vous, mais comment fait-on pour éviter les conflits sur le réseau de destination ? Et comment fait-on pour que ces machines communiquent ensemble ?

C'est tout simple, on met cette IP sur un vlan prédéfini. Ainsi vous n'avez plus aucune contrainte sur la configuration réseau de l'appareil. Ce peut être une box en bridge ou en routeur, une machine physique avec un routage complexe, ou une machine configurée en dhcp.

Solution pour linux

Pour ajouter une interface réseau virtuelle associée à un vlan :

# le vlan 1 sur l'interface eth0 sera dans l'interface virtuelle vlan1 
$ ip link add link eth0 vlan1 type vlan id 1 

# ou, pour ceux qui n'aiment pas le couteau suisse, ip, il y a l'outil d'origine
$ vconfig add eth0 1 # pas le choix, l'interface s'appellera nécessairement eth0.1

Et il suffit de lui configurer une ip choisie en dur et c'est fini, vous pouvez mettre n'importe quelle configuration pour eth0 ...

$ ip addr add 192.168.254.254/28 dev eth0.1

Pour faire ceci en statique, sur une debian like il faut modifier /etc/network/interfaces en nommant l'interface à configurer eth0.1 Pour les redhat like il faut créer le fichier /etc/sysconfig/network-script/ifcfg-eth0.1

Linux embarqué 

Feb 17 Par peck

Aujourd'hui une pub éhontée pour un livre. Je ne connais même pas l'auteur personnellement, mais la maison d'édition me l'a envoyé gratuitement, ça prouve qu'il est bien non ?

Il s'agit de Linux embarqué. Pour une fois, ne vous attendez pas à trouver des lignes de commande, des howto ou ce genre de détails. Il s'agit bien d'un livre technique, mais dons le but est de vous faire choisir (ou pas) linux comme plateforme pour l'embarqué.

Il vous pose les bonnes questions et vous aide à y répondre. Quel modèle de développement ? Temps réel ou non ? Investissez-vous sur le long terme ? Et ce n'est qu'après avoir étudié le sujet que vous saurez s'il est judicieux de choisir linux.

Mais une fois que vous avez choisi linux, pensez-vous vraiment que cela suffise à votre succès ? Gilles Blanc vous explique comment vous préparer, ce que vous devez savoir, comment organiser le projet. Tout ce qu'il faut à l'intention du chef de projet.

Ce livre permet aux gens de faire un choix avisé, de savoir quelles sont les raisons de ce choix et comment. C'est grâce ça que vous pourrez soutenir ce choix tout au long du projet. Il permettra de transformer un projet sur l'embarqué en succès. Et il est probable que parmi ces projets un certain nombre utiliseront linux. Et comme tout le monde devrait le savoir, un projet réussi est un bien meilleur ambassadeur du libre qu'un geek dans son coin.

En conclusion, même si je ne recommanderais pas ce livre à ma grand-mère, je pense qu'il a une énorme valeur pour la progression du logiciel libre. Je le recommande à tout chef de projet ou ambassadeur du logiciel libre qui voudrait lancer un produit avec du linux embarqué.

57 pages