Tag - planet-libre

Entries feed

Sunday, June 7 2015

Beau-frère, entropie et établissement de connexion SSH lente

La connexion via SSH (échange de clés) à l'une de mes machines (Debian Jessie 64 bits) mettait un temps certain à s'établir : une petite dizaine de secondes. Mon beau-frère (celui fort en ordinateur, on en a tous un) m'a sauvé, il m'a annoncé doctement que la machine manquait sans doute d'entropie.

Et il avait raison !

Pour vérifier le stock d'entropie sur la machine :

cat /proc/sys/kernel/random/entropy_avail

me retournait des valeurs proches de 700 sur la machine à laquelle je me connectais.

Nous installâmes alors un démon pour récolter l'entropie :

apt install haveged

et dès lors

cat /proc/sys/kernel/random/entropy_avail

retournait des valeurs proches de 2000.

Et la connexion SSH s'établissait en un clin d'oeil.

Trop fort mon beau-frère.

Sunday, May 17 2015

Augmenter la qualité de service avec la QoS des routeurs sous Tomato

Le firmware Tomato (utilisable dans certains routeurs) continue à m'émerveiller de jour en jour. Je découvrais dernièrement les fonctionnalités de QoS (Quality of Service) qu'il contient. Elles permettent d'activer des règles classiques de QoS pour optimiser les flux sur une connexion au moyen de règles.

Les règles de QoS sont bien évidemment indispensables lorsque les connexions sont massivement partagées pour éviter que quelques utilisateurs actifs en P2P ou effectuant des téléchargements ou téléversements massifs ne viennent rendre la connexion commune utilisable. Elles peuvent aussi améliorer la qualité d'une connexion SIP en la protégeant quelque peu des soubresauts liés à des téléversements (surtout sur des connexions ADSL où le débit montant est limité) réalisés sur le même réseau. De bonnes règles de QoS peuvent également participer à maintenir des latences acceptables en s'assurant qu'un trop grand nombre de paquets n'est pas en train de s'accumuler à l'entrée du réseau du fournisseur d'accès (juste avant le goulot d'étranglement de la connexion ADSL).

Dans Tomato, la QoS s'active très simplement :

  • on se rend dans le menu dédié et on l'active

qos-settings-tomato.png

  • il est également possible de visualiser le trafic du réseau réparti suivant les différentes catégories de la QoS :

qos-plots-tomato.png

  • et bien sûr il est possible de rajouter des règles pour répartir le trafic dans les 11 catégories proposées par défaut !

Et ensuite ? Ensuite vient le temps du paramétrage : pour chaque catégorie de service on vient placer une limite en débit montant et en débit descendant. On peut donc laisser certains flux prendre la totalité de la bande passante et limiter d'autres de façon à sacraliser une part de la bande passante à d'autres usages. Si vous disposez d'une connexion ADSL avec un débit montant faible, vous vous dites sans doute que seules des limites 'outbound' doivent être établies car c'est la ressource rare : en fait il est important de limiter aussi le débit descendant afin de forcer le routeur à refuser certains paquets qui arrivent. L'expéditeur du paquet réalisera (automatiquement, c'est le fonctionnement normal du réseau) que des paquets se perdent et il réduira ainsi son rythme d'envoi... ce qui évitera l'accumulation de paquets à l'entrée de votre ligne ADSL et devrait permettre de réduire ainsi la pile des paquets en attente pour votre réseau et contribuant ainsi à réduire la latence de votre réseau.

Les règles affichées ci-dessous ne sont pas optimales : je réalise que régler la QoS est une affaire qui demande pas mal de tests et de doigté ; tout est très dépendant des usages sur votre réseau, des priorités et finalement cela laisse la part belle au essais/erreurs !

qos-limits.png

Ah j'allais oublier : voici une référence intéressante sur les mécanismes de QoS : http://tomatousb.org/tut:using-tomato-s-qos-system. J'ai transformé cette page web en ePub pour une lecture facilitée : QoS_TomatoUSB.epub. Bonne lecture !

Bon QoSing !

Saturday, May 16 2015

Unicorn vs Thin pour propulser une application Ruby on Rails, stress test pour choisir !

Unicorn et Thin sont deux serveurs pour Ruby assez fréquemment utilisés et cités dans la littérature informatique. A titre d'exemple, Unicorn est utilisé notamment chez Github: une bonne référence ! Thin est souvent cité pour sa robustesse et sa légèreté. Lequel choisir ?

Avant d'envisager le déploiement d'une application en production (prévision de charge : quelques centaines d'utilisateurs simultanément), j'ai souhaité les comparer.

Protocole de test

  • Linux Debian Jessie, Core M 5Y10, 4 Go de RAM, disque dur SSD ; les tests sont effectués en local sur la machine et le réseau n'intervient donc pas comme facteur dans le test.
  • Le stress test est réalisé avec Gatling (dont j'ai déjà décrit le fonctionnement ici) qui simule l'arrivée de 200 utilisateurs en 120 secondes sur l'application, chaque utilisateur exécute 8 requêtes sur l'application.
  • L'application Ruby on Rails (Rails 4.2.1, Ruby 2.2.2) est prête à l'emploi en environnement de production, les 2 gems Thin et Unicorn sont installés et fonctionnels.
  • Quand cela est nécessaire, Pound est utilisé comme "load balancer".
  • Thin est exécuté avec la commande :
thin -s 4 -e production -p 8080 start

ou, quand on le lance avec un seu

thin -e production -p 8080 start
  • Unicorn est exécuté par la commande :
unicorn -c config/unicorn.rb -E production -p 8080

avec pour contenu du fichier de config unicorn.rb une configuration très proche de celle proposée par Github sur cet article :

rails_root = "/path/to/app"
rails_env = ENV['RAILS_ENV'] || 'production'

# 4 workers, may be changed to 1 for the tests
worker_processes (rails_env == 'production' ? 4 : 1) 

# Load rails+app into the master before forking workers
# for super-fast worker spawn times
preload_app true

# Restart any workers that haven't responded in 30 seconds
timeout 30

before_fork do |server, worker|
  ##
  # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
  # immediately start loading up a new version of itself (loaded with a new
  # version of our app). When this new Unicorn is completely loaded
  # it will begin spawning workers. The first worker spawned will check to
  # see if an .oldbin pidfile exists. If so, this means we've just booted up
  # a new Unicorn and need to tell the old one that it can now die. To do so
  # we send it a QUIT.
  # Using this method we get 0 downtime deploys.

  old_pid = rails_root + '/tmp/pids/unicorn.pid.oldbin'
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  # Unicorn master loads the app then forks off workers - because of the way
  # Unix forking works, we need to make sure we aren't using any of the parent's
  # sockets, e.g. db connection
  ActiveRecord::Base.establish_connection
end

Les résultats

Match 1 : Unicorn vs Thin, avec un seul processus pour chacun

Quand un seul processus (un seul "worker" dans le vocable propre à Unicorn) est activé, l'arrivée ininterrompue de nouveaux utilisateurs charge considérablement l'application...

Voici les résultats du "stress test" : benchmark_1process.png

On observe que :

  • Thin parvient à servir tout le monde, mais au prix de temps de réponse assez longs
  • Les temps de réponse sont un petit plus courts avec Unicorn mais en revanche Unicorn échoue à servir un certain nombre d'utilisateurs - le résultat du second graphe montre que l'unique worker d'Unicorn arrête de répondre aux requêtes à plusieurs reprises et pendant des durées assez longues... je n'explique pas bien ce comportement... J'ai pensé à l'impact du paramètre 'timeout 30' mais je n'ai pas observé de différence lorsque j'ai porté la valeur du timeout à 300 (j'ai même observé une amplification du phénomène)...
  • Thin semble donc vainqueur sur ce match avec un seul processus... mais voyons vite avec plusieurs processus ce qui sera plus proche d'un déploiement réel !

Match 2 : Unicorn vs Thin, avec 4 processus pour chacun

Nous démarrons cette fois Unicorn avec 4 "workers" et 4 instances de Thin. Afin d'accéder de manière aléatoire aux différentes instances de Thin, nous utilisons cette fois Pound comme "load balancer". Pound a également été utilisé avec Unicorn pour rendre les conditions des tests équivalentes. Pound n'est toutefois "en théorie" pas nécessaire pour Unicorn qui répartit automatiquement les requêtes sur les différents "workers".

Place aux résultats : benchmark-4processus.png

On constate que :

  • Thin et Unicorn parviennent à servir tous les utilisateurs plus efficacement (normal, la multiplication des processus profite des plusieurs coeurs de la machine hôte)
  • Mais Unicorn est plus véloce que Thin : 97% des requêtes sont servies en moins de 800ms par Unicorn alors que seules 63% sont servies dans le même délai par Unicorn
  • On remarque également que les 4 processus d'Unicorn jugulent le flux des nouveaux utilisateurs avec au pic 24 utilisateurs en attente là où Thin faiblit peu à peu jusqu'à atteindre un pic à plus de 50 utilisateurs en attente dans l'application (pour rappel, dans le scénario testé, 200 utilisateurs se connectent régulièrement au cours des 120 secondes à l'application et exécutent 8 requêtes)
  • C'est donc une victoire d'Unicorn qui se tire mieux cette fois de la situation !

Conclusion

Je suis tenté de préférer Unicorn pour servir un site Ruby on Rails chargé. Cependant, il conviendra d'offrir suffisamment de workers à Unicorn pour qu'il puisse faire le travail correctement !

Quelques enseignements annexes :

L'impact de Pound sur les temps de réponse

Sans Pound, le temps de réponse moyen de Unicorn est de 117 ms. Avec Pound, toute autre chose étant égale par ailleurs, le temps de réponse moyen est de 161 ms. Il semble donc que le passage par Pound augmente le temps moyen de réponse d'environ 40 ms.

La multiplication des workers pour Unicorn : bonne ou mauvaise idée ?

La machine de test dispose de 4 coeurs. J'ai testé 4 workers et 16 workers avec Unicorn. Les résultats sont très similaires : respectivement 131 et 130 secondes pour effectuer le scénario de test complet. Les temps de réponse moyens sont là encore très proches : 113 ms vs 117 ms. Je ne pense pas que les différences constatées soient significatives. Les écart-types sur le temps de réponse diffèrent plus : 216 ms avec 4 workers et 265 ms pour 16 workers... Compte-tenu du nombre de coeurs sur la machine de test (4), l'utilisation de 16 workers ne semble pas permettre des gains substantiels. Un petit excès du nombre de workers par rapport au nombre de coeurs est peut-être à conseiller toutefois.

Sunday, April 5 2015

De belles rondeurs avec la Materia 101 d'Arduino

L'imprimante 3D Materia 101 d'Arduino est une très belle petite machine dont je ne peux que conseiller l'acquisition à tout amateur de nouvelles technologies. Assez peu chère, de qualité, et tout à fait libre, elle ravira ses utilisateurs. Fidèle à l'esprit Arduino, il s'agira plus d'une machine à usage éducatif (le montage étant déjà très instructif car permettant de comprendre en détail le fonctionnement des machines d'impression 3D) qu'un outil de production à grande échelle.

Après son montage, et au cours des premières impressions, nous avons toutefois constaté que les cercles n'étaient pas parfaitement ronds. Après avoir envisagé de nombreux paramètres (notamment réduire la vitesse d'impression pour éviter les vibrations trop importantes de la machine), nous avons réalisé qu'il fallait mettre en tension le plus possible les courroies de déplacement sur l'axe Y (les cercles étaient légèrement elliptiques sur cet axe).

Pour déplacer la tête d'écriture sur l'axe Y, 3 courroies sont impliquées. La première transfère le mouvement du moteur Y à l'axe général qui entraîne ensuite 2 autres courroies auxquelles est fixé le chariot de la tête de lecture.

Première étape : positionner le moteur Y pour mettre la courroie qui y est attachée très en tension : Ymotor.jpg

Deuxième étape : serrer les vis qui mettent en tension les courroies comme indiqué ci-dessous : screw_circleadjust.jpg

Dans notre cas, ce réglage effectué, les ronds étaient bien ronds - ce qui a permis à nos pièces de parfaitement s'emboîter les unes aux autres !

Bonne impression 3D !

Tuesday, March 10 2015

Se maintenir au top de la sécurité SSL/TLS en faisant le ménage sur sa suite de chiffrements (cipher suite)

Le monde de la sécurité informatique est en perpétuelle évolution et les chiffrements jugés solides à un instant T ne le sont plus forcément à T+1 ! En novembre dernier, je proposais un paramétrage qui permettait alors d'obtenir la note maximale sur Qualys SSLLabs https://www.ssllabs.com (ce qui n'est bien sûr pas une fin en soi mais qui est un indicateur facile du niveau de sécurité atteint... si l'on fait confiance aux gens de Qualys).

Cependant, les attaques sur l'algorithme de chiffrement RC4 se sont multipliées et celui-ci a été récemment déclaré comme faible et déconseillé donc pour l'établissement de connexions sécurisées. Diable, il faut donc mettre à jour la suite de chiffrements utilisés pour écarter ce chiffrement !

Heureusement, les gens de Mozilla (encore eux !) nous rendent la tâche aisée en publiant une série de 3 suites de chiffrement selon le niveau de sécurité et le niveau de rétro-compatibilité souhaités (avec de vieux navigateurs / de vieux OS) : https://wiki.mozilla.org/Security/Server_Side_TLS

En date du 10 mars, la suite de chiffrement conseillée pour le plus haut niveau de sécurité est la suivante :

Ciphersuite: ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK

Voilà qui devrait aider les administrateurs à optimiser la sécurité des connexions SSL/TLS proposées par leurs serveurs !

Tuesday, January 20 2015

Orange, le fournisseur d'accès à internet, grand complice des arnaques du web !

Oyez oyez, abonnés du fournisseur d'accès à internet Orange, ne vous laissez pas prendre dans le piège tendu par quelques vils commerciaux d'Orange...

Par défaut, les abonnés Livebox (fibre et ADSL) ont les options Contact+ et Internet+ activées. Concrètement, il s'agit d'options "minitelesques" : elles permettent à certains sites de vous facturer le temps de connexion à la minute, cette somme venant apparaître sur la facture internet ! Et bien sûr les sites en question n'affichent qu'en tout petit la mention "accès payant" (trop contents d'attirer le chalant !). Sans crier gare, vous voilà connectés à un site qui, minute après minute, vous soutire euro après euro... On se croirait revenu au temps du Minitel...

C'est à mes yeux un scandale qu'Orange se rende complice d'une telle pratique. Ce n'est pas un service "pratique" pour l'abonné mais bel et bien une manière d'attraper quelques euros auprès du public le plus crédule qui ne comprendra pas bien ce que cette somme fait sur sa facture Orange, et payera en secouant la tête la plupart du temps.

Heureusement, il est assez facile de désactiver les 2 options (Contact+ et Internet+) en ligne sur l'interface de gestion du compte Livebox d'Orange dans la section "Mes services" :

2015-01-20_09_38_58-Mes_services_Internet_-_Espace_Client_Orange_-__internet_.png

A faire d'urgence, et aider les gens autour de soi à faire ! On ne peut pas utiliser Internet et craindre, au détour de chaque page, une facture salée d'Orange !

Sunday, January 4 2015

Surveiller un changement de page web avec urlwatch

urlwatch est un super outil pour surveiller les changements d'une page web. Il est facile à utiliser pour détecter un changement mais également en afficher la teneur à l'aide d'un diff.

Utilisation de base

  • on spécifie une liste d'URLs à surveiller dans un fichier /home/bob/liste-des-urls avec une URL par ligne
  • on exécute urlwatch avec cette commande :
urlwatch --urls=/home/toto/liste-des-urls
  • urlwatch conserve alors automatiquement une version de la page (par défaut dans ~/.urlwatch)
  • quand on l'exécute une nouvelle fois, une comparaison est faite et toute modification est mise en avant

Des filtres plus complexes

Il est possible de coder en Python des filtres spécifiques (applicables par exemple à certaines URLs seulement) : par exemple suppression des zones de publicité, suppression de parties de page non pertinentes, ... Quelques exemples sont donnés ici.

Et hop, dans cron, pour un suivi régulier !

On peut bien sûr placer la commande dans cron pour une surveillance régulière automatique. La commande ci-dessous exécute urlwatch et envoie les résultats (s'ils sont non vides) à une adresse électronique :

urlwatch --urls=/home/toto/liste-des-urls | ifne mail -s "URL Watcher - un changement !" bob@courriel.fr

Fibre FTTH Orange et routeur avec micrologiciel Tomato : l'astuce du VLAN

Si la Fibre Optique FTTH d'Orange offre une bonne qualité de service (du moins dans mon expérience), la LiveBox pro fournie est selon moi une catastrophe : instable, ne re-démarrant pas toute seule en cas de coupure de courant, possibilités de paramétrage faibles...

J'ai très vite décidé de la renvoyer à Orange et de la remplacer par un routeur Asus RT-N16 équipé du micrologiciel Tomato (by Shibby). J'ai donc conservé le convertisseur fibre/RJ45 mais ai ré-envoyé la Livebox elle-même à l'opérateur (ce qui m'a valu d'ailleurs la disparition des frais de location de modem sur ma facture).

Je n'étais cependant pas au bout de mes peines car l'infrastructure de la Fibre Orange nécessite un paramétrage particulier de VLAN pour fonctionner.

Comme expliqué ici, le vénérable VPI/VCI 8/35 de l'ADSL a été remplacé en Fibre chez Orange par un VLAN 835. Concrètement, le routeur doit s'enregistrer et communiquer sur ce VLAN 835 pour discuter avec les équipements réseaux d'Orange et obtenir une adresse IP puis faire transiter le trafic vers internet.

Il faut donc apprendre au micrologiciel Tomato que le port WAN du routeur (celui connecté filairement au convertisseur fibre/RJ45) doit communiquer exclusivement sur ce VLAN.

On choisit le PPPoE pour le WAN...

Dans l'onglet principal, on choisit une connexion PPPoE et on saisit le nom d'utilisateur 'fti/xxxxx' et le mot de passe pour la connexion.

... et on bascule le WAN dans le VLAN 835

Il faut alors se rendre dans les options avancées, catégorie VLAN.

  • Dans VID offset, on saisit : 832 (c'est le multiple de 16 le plus proche de 835).
  • Puis on sélectionne la ligne correspondant au VLAN du WAN et on on choisit le numéro de VLAN 3. Automatiquement, le VID (VLAN ID) doit devenir 835 (832 d'offset + 3).
  • Il ne faut pas oublier également de cocher la case 'Tagged' pour demander au retour de bien prendre en compte le trafic 'marqué' comme appartenant au VLAN 835.

vlan835-orange-tomato.png

Et voilà le tour est joué. On sauvegarde, le routeur inscrit ces paramètres dans sa nvram et redémarre. On voit que le WAN PPPoE parvient à se connecter à internet et le routeur distribue internet à tous les postes du réseau qui le référencent comme passerelle.

A noter : Sur ASUS RT-N16, il a été nécessaire d'utiliser l'Offset. Il semblerait que sur des modèles de routeur plus récents, il ne soit pas nécessaire de changer l'offset mais seulement de modifier manuellement le VID.

Friday, January 2 2015

Entretenir et sécuriser Nextcloud/ownCloud avec logrotate et fail2ban

On ne présente plus ownCloud/Nextcloud, plateforme de stockage et partage de fichiers fort aboutie. Pour ceux qui hébergent leur propre instance d'ownCloud/Nextcloud, voici deux petites astuces pour bien entretenir et sécuriser l'installation.

La rotation des logs

La rotation des logs évite que le fichier owncloud.log n'occupe une place trop importante sur votre serveur. On pourra utiliser logrorate pour effectuer la rotation automatique et régulière.

Dans /etc/logrotate.d/owncloud, on placera le paramétrage (assez explicite) suivant :

/var/www/owncloud/data/owncloud.log {
        weekly
        missingok
        rotate 8
        compress
        notifempty
        create 640 www-data www-data
}

et le tour est joué. On prendra bien sûr le soin d'adapter le chemin vers le fichier et le nom de l'utilisateur créateur du fichier (ici www-data car c'est l'utilisateur propriétaire du serveur web sous Debian) ! Si l'on utilise Nextcloud plutôt qu'ownCloud, on remplacera owncloud.log par nextcloud.log sans surprise !

Surveillance avec fail2ban

Fail2ban est capable de détecter des connexions non autorisées et de bannir (via iptables) l'adresse IP offensante. Un éventuel attaquant n'aura ainsi pas tout le loisir de tester les combinaisons nom d'utilisateur / mot de passe à son aise. Concrètement, on paramètre fail2ban pour vérifier régulièrement un fichier de log et pour détecter dans ce fichier les tentatives d'accès frauduleuses (i.e. qui se répètent). Puis, quand une tentative frauduleuse est repérée, on bannit l'adresse IP correspondante.

Nous allons créer un nouveau filtre pour fail2ban dans /etc/fail2ban/filter.d/owncloud.conf :

[Definition] 
#Pour owncloud <8
failregex = {"app":"core","message":"Login failed:(.*)IP: '<HOST>'
#Pour owncloud 8
failregex = {"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>', X-Forwarded-For: '.*'\)","level":2,"time":".*"}

Si l'accès est contrôlé par un proxy, on pourra modifier la règle pour repérer l'adresse IP associée au champ X-Forwarded-for :

[Definition]
#Pour owncloud <8
failregex = {"app":"core","message":"Login failed:(.*)X-Forwarded-For: '<HOST>'
#Pour owncloud 8
failregex = {"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '.*', X-Forwarded-For: '<HOST>'\)","level":2,"time":".*"}

On peut alors créer une nouvelle règle dans /etc/fail2ban/jail.local :

[owncloud]
enabled  = true
port     = http,https
filter   = owncloud
logpath  = /var/www/owncloud/data/owncloud.log
maxretry = 6

et désormais, toute tentative d'accès répétée conduira à l'exclusion de l'IP douteuse !

'PS Merci à Arnaud Collarde pour la mise à jour de l'expression régulière pour ownCloud 8 et à Guillaume pour mise à jour de la regexp pour Nextcloud 15 qui m'indique que celle-ci pourrai ressembler à

failregex ={"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":"core","method":".*","url":".*","message":"Login failed: '.*' \(Remote IP: ''\)","userAgent":".*","version":".*"}

Sunday, November 23 2014

Température suivie avec un Raspberry Pi B+, une sonde DS18B20 et Munin

La sonde DS18B20 est une sonde de température 1-wire très facile d'utilisation avec le Raspberry Pi. Il y a de très nombreux sites et blogs qui en rapportent l'utilisation : par exemple http://www.framboise314.fr/mesure-de-temperature-1-wire-ds18b20-avec-le-raspberry-pi/ ou https://learn.adafruit.com/downloads/pdf/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing.pdf.

Je vais toutefois reprendre ici les principales étapes et me concentrer ensuite sur le suivi et l'affichage de la température via Munin.

Matériel

  • Un Raspberry Pi B ou B+ avec des GPIO libres
  • Une sonde DS18B20 (composant avec 3 pattes)
  • Une résistance 4.7 KOhms (des valeurs proches peuvent convenir également)
  • Quelques câbles

Montage électrique

Les sondes 1-wire peuvent être alimentées de 2 manières : en alimentant une des pattes à 3.3V ou bien en laissant le composant charger un condensateur avec les parasites ambiants et utilisant la charge de ce condensateur pour effectuer une messure. La 2e méthode a l'avantage de nécessiter un câble de moins dans l'installation mais il est possible qu'il faille être un peu plus patient pour effectuer des lectures de température (quelques secondes pour charger le condensateur selon le niveau des parasites).

Dans la suite, nous alimenterons directement le composant en 3.3V.

Nous allons donc simplement connecter :

  • la masse du capteur à un pin de masse
  • l'alimentation du capteur au pin 3.3V du Raspberry Pi
  • la patte centrale (lecture) au GPIO 4

et nous allons ajouter la résistance de 4.7KOhms en parallèle avec la sonde i.e. entre l'alimentation 3.3V et la ligne de lecture.

raspberry-pi-ds18b20-connections.jpg (image empruntée sur http://www.reuk.co.uk/DS18B20-Temperature-Sensor-with-Raspberry-Pi.htm)

Attention à ne pas inverser la masse et l'alimentation - cela pourrait endommager le composant. On peut se référer à cette documentation pour être certain de ne pas se tromper : http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf. La masse se trouve sur la patte de gauche quand on regarde la face plate du composant avec les pattes vers le bas.

Paramétrons le Pi

On peut alors brancher le Pi, se connecter en SSH et charger les modules nécessaires à la lecture des GPIO :

modprobe w1-gpio
modprobe w1-therm

Il faut aussi modifier le fichier /boot/config.txt et ajouter cette ligne :

dtoverlay=w1-gpio

Pour ne pas avoir à les charger à nouveau à chaque re-démarrage du Pi, on ajoutera les 2 lignes suivants au fichier /etc/modules :

w1-gpio
w1-therm

Remarque : si vous prévoyez plus de 10 sondes, il est possible qu'il faille ajouter un fichier wire.conf dans /etc/modprobe.d avec ce contenu :

options wire max_slave_count=50

Si tout fonctionne, on doit alors voir un dossier au nom de la sonde apparaître dans le dossier /sys/bus/w1/devices :

cd /sys/bus/w1/devices
ls
>> 28-000005330085 w1_bus_master1

'' 28-000005330085'' est le nom de la sonde installée. Si nous avions plusieurs sondes sur le bus, nous verrions un dossier avec un nom unique pour chaque sonde. Si on entre dans le dossier, on accède aux différentes valeurs retournées par la sonde : le fichier w1_slave contient la température sur la 2e ligne en millièmes de degré Celsius :

4c 01 4b 46 7f ff 04 10 f5 : crc=f5 YES
4c 01 4b 46 7f ff 04 10 f5 t=20750

La petite ligne bash suivante (en remplaçant bien sûr le nom de ma sonde par celui de la vôtre !) extrait alors la température en °C :

cat /sys/bus/w1/devices/28-000005330085/w1_slave | grep "t=" | awk -F "t=" '{print $2/1000}'
>> 20.75

Relevons la température avec Munin

J'ai déjà évoqué Munin ici. Munin est un logiciel utilisé par le adminsys pour suivre les variables vitales de serveurs. Mais l'outil peut tout à fait être utilisé aussi pour suivre n'importe quelle variable accessible sur un ordinateur, par exemple la valeur de la température relevée par notre sonde !



Je ne détaillerai pas ici le paramétrage du serveur Munin (qui récolte régulièrement les données des clients, génère les graphes et les rend disponibles au travers d'un serveur http) mais seulement du client Munin.

On installe un client (noeud dans le vocabulaire de Munin) sur le Pi avec cette commande :

aptitude install munin-node

Le noeud/client munin fonctionne en récoltant les variables de scripts stockés dans /etc/munin/plugins : par défaut les plugins seront en fait des liens relatifs vers les scripts par défaut disponibles dans /usr/share/munin/plugins/. Si vous ne souhaitez suivre aucune variable vitale du Pi, vous pouvez supprimer tous les liens dans /etc/munin/plugins (si vous changez d'avis il suffira de les reprendre depuis /usr/share/munin/plugins).

Nous allons donc créer un nouveau script Munin pour collecter la température. Les scripts Munin sont tout simples - ils comprennent 2 parties : une partie qui décrit le graphique (et les éventuelles options graphiques que l'on souhaite voir appliquées) et une seconde partie imprime chaque variable et sa valeur sur chaque ligne. Par exemple, le script "memory" de Munin retourne les valeurs suivantes :

slab.value 8949760
swap_cache.value 0
page_tables.value 638976
vmalloc_used.value 954368
apps.value 21979136
free.value 291938304
buffers.value 35708928
cached.value 99397632
swap.value 0
committed.value 51347456
mapped.value 6803456
active.value 64913408
inactive.value 85291008

Nous allons donc générer un script qui imprime la valeur de notre sonde de la même façon dans /etc/munin/plugins :

nano temperature_1

et voici le contenu du script :

#!/bin/sh

case $1 in
   config)
        cat <<'EOM'
graph_title Temperature probe 1
graph_vlabel temperature_1
temperature_1.label temperature_1
EOM
        exit 0;;
esac

printf "temperature_1.value "
cat /sys/bus/w1/devices/28-000005330085/w1_slave | grep "t=" | awk -F "t=" '{print $2/1000}'

Si on exécute ce script (./temperature_1) voici la sortie :

temperature.value 21.5

On peut alors redémarrer le client Munin.

Lors de la prochaine collecte des données, le serveur Munin viendra récupérer la sortie du script temperature_1 et proposera alors les graphes standards de Munin pour cette valeur.

Si l'on dispose de plusieurs sondes, on peut alternativement multiplier les scripts (un script par sonde) ou alors demander au script d'imprimer les valeurs de chacune des sondes : les différentes valeurs seront alors affichées sur un même graphe !

ambient_temperature-day.png

Bon suivi de température !

Monday, November 10 2014

Obtenir une bonne note chez SSLLabs avec Pound

J'utilise Pound dans mon infrastructure, notamment pour sa capacité d'assurer tout le chiffrement en SSL/TLS entre mes serveurs et les clients.

Cependant, la version stable de Pound dans Debian Wheezy n'est pas patchée pour écarter les récentes "attaques" sur SSL/TLS à commencer par la corruption de SSLv3 (faille baptisée Poodle).

Si la version 2.7, la prochaine stable, disposera de tous les derniers raffinements, seule une branche non officielle pourra satisfaire le plus scrupuleux adminsys. Cette branche non officielle est maintenue par Joe Gooch (qu'il soit permis ici de le remercier !) et est disponible ici : https://github.com/goochjj/pound/tree/pcidss/v2.6.

Voici comment Joe décrit cette branche :

The other is called pcidss/v2.6, which is Pound 2.6, plus cipher and protocol patches necessary (initially) to pass PCI compliance, and as part of that is the directive to disable SSL3.

Compiler Pound 2.6-pcidss

  • Télécharger la dernière version ici : https://github.com/goochjj/pound/archive/pcidss/v2.6.zip
  • Dé-zipper l'archive et se rendre dans le dossier
  • Réaliser ensuite la compilation (le système devra bien sûr comporter tout le nécessaire à cela : gcc, build-essentials, libssl-dev...) :
./configure
make
make install
  • dans Debian, il semble que pound 2.6-pcidss s'installe dans /usr/local/sbin/pound alors que le paquet original l'installe dans /usr/sbin/pound. On peut donc remplacer l'ancienne version par la nouvelle et vérifier que l'utilitaire par défaut correspond bien à la nouvelle version :
pound -V

qui doit retourner 2.6-pcidss.

  • on peut alors modifier la configuration de Pound avec ces paramètres :
	DisableSSLv2
	DisableSSLv3

	Ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:-RC4:EECDH+aRSA+RC4:EECDH+RC4:EDH+aRSA+RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:RC4+SHA"
    	SSLHonorCipherOrder 1
	SSLAllowClientRenegotiation     0
  • et redémarrer Pound

Normalement, vous devriez désormais disposer d'un chiffrement SSL de qualité susceptible de vous faire obtenir un A (yes!) sur https://www.ssllabs.com/ssltest/ (si votre certificat est de bonne qualité - SSLLabs disqualifie tout de suite tout certificat auto-signé !).

StartSSL pour des certificats SSL "wildcard" à petit prix

Disposant de plusieurs domaines pour mes activités personnelles et professionnelles, j'utilisais jusqu'ici des certificats auto-signés pour sécuriser mes connexions avec SSL/TLS. Cependant, habituer l'utilisateur à "ajouter une exception de sécurité" sans réfléchir me déplaisait au plus haut point. J'ai donc finalement, poussé aussi par mon beau-frère, mis en place de jolis certificats validés par StartCom Ltd. (StartSSL).

Les tarifs pratiqués par StartCom Ltd./StartSSL sont beaucoup plus doux que ceux pratiqués par d'autres acteurs du domaine. Chez eux, on paye en effet le processus de validation d'identité mais ensuite l'émission des certificats est gratuite. Voilà qui est tout à fait intéressant et économique pour couvrir plusieurs domaines !

Ouvrir un compte chez StartSSL

La première étape consiste à se connecter sur http://startssl.com et à choisir "Sign-up" pour ouvrir un nouveau compte. On saisit ses informations personnelles (il faut qu'elles soient exactes si l'on prévoit de faire valider son identité !) puis le site installe automatiquement dans le navigateur un certificat/clé qui autorise ce seul navigateur à se connecter au site. Une bonne pratique consistera à sauvegarder de manière sûre ce certificat pour conserver l'accès au site StartSSL !

Profiter des certificats de niveau 1

Sans rien payer, il est alors possible de faire valider un domaine via le 'Validations Wizard' (la validation d'un domaine consiste à recevoir un courriel envoyé par exemple à postmaster@le-domaine-en-question.fr et à saisir le code de validation reçu) puis de créer des certificats de niveau 1.

Les certificats de niveau 1 sont une bonne base pour débuter mais il n'est notamment pas possible avec ce niveau de disposer de certificats "wildcard" (i.e. pour tous les sous-domaines d'un domaine). Pour bénéficier de cette fonctionnalité, il faut disposer d'un niveau 2.

Obtenir le niveau 2

Pour passer niveau 2, il faut d'une part :

  • soumettre des documents pour prouver son identité (photocopies de 2 pièces d'identité, éventuellement justificatif de domicile, éventuellement recevoir un appel de StartSSL sur son numéro de téléphone)
  • s'acquitter de la somme de 59,90$ (environ 48 euros)

Tout le processus s'effectue en ligne via le 'Validations Wizard', catégorie 'Personal identity validation'. Les gens de StartCom StartSSL sont extrêmement réactifs.

Dans mon cas, après quelques heures et quelques échanges par courriel et téléphone, mon identité a été vérifiée et mon niveau 2 validé.

Créer un certificat 'wildcard'

Une fois niveau 2, voici la marche à suivre :

  • sur le serveur que l'on souhaite protéger, nous allons générer une clé privée et un Certificate Sining Request (CSR) par la commande
openssl req -nodes -newkey rsa:4096 -sha256 -keyout cle-privee.key -out serveur.csr

Il est à noter que ce processus génère une clé privée sans mot de passe. Il est tout à fait possible de générer une clé avec mot de passe mais il faudra alors préciser le mot de passe correspondant aux logiciels serveurs qui utiliseront la clé pour crypter les échanges.

Au cours du processus, OpenSSL va demander quelques informations d'identité. Il est important de préciser dans le champ 'Common Name' le nom d'hôte à protéger : en l'occurrence *.le-domaine-en-question.fr si l'on souhaite bénéficier d'un certificat 'wildcard' pour le-domaine-en-question.fr.

Country Name (2 letter code) [AU]: FR
State or Province Name (full name) [Some-State]: Ile-de-France
Locality Name (eg, city) []: Mary-sur-Marne
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MaSociété
Organizational Unit Name (eg, section) []: 
Common Name (eg, YOUR name) []: *.le-domaine-en-question.fr
Email Address []: postmaster@le-domaine-en-question.fr
A challenge password []: 
An optional company name []:
  • on peut alors afficher le contenu du CSR par
cat serveur.csr

et le conserver précieusement

  • de retour sur le site de StartSSL, se rendre dans le 'Certificates wizard'
  • choisir 'Webserver SSL/TLS certificate'
  • passer (bouton SKIP) l'étape de génération d'une clé privée puisque nous avons créé nous-même notre clé privée sur le serveur
  • copier alors le contenu du CSR dans le champ texte
  • sélectionner le domaine à protéger : seuls les domaines déjà validés peuvent être utilisés. On pourra par exemple saisir *.le-domaine-en-question.fr.
  • et voilà le certificat qui apparaît à l'écran. Il convient de copier ce certificat précieusement, par exemple dans un fichier wildcard.le-domaine-en-question.fr.crt.

Utiliser son tout nouveau certificat

Cette étape dépend ensuite du serveur utilisé (Apache, Pound, Nginx, ...). La plupart du temps, on regroupera le certificat obtenu de la part de l'autorité de certification et la clé privée dans un même fichier .pem. On pourra également inclure les certificats intermédiaires de l'autorité : https://www.startssl.com/certs/ca.pem et https://www.startssl.com/certs/sub.class2.server.ca.pem.

cat wildcard.le-domaine-en-question.fr.crt cle-privee.key ca.pem sub.class2.server.ca.pem > wildcard.le-domaine-en-question.pem

On pourra alors utiliser ce .pem sur son serveur, en s'assurant toutefois de bien le garder secret, car il contient notre clé privée !

Bon courage pour votre génération de certificats !

Saturday, November 1 2014

Xournal, génial pour annoter des PDFs

Xournal est un très simple et très pratique outil pour annoter des PDFs. Indispensable aujourd'hui quand nous recevons des formulaires par dizaines sous format PDF ou qu'il est habituel de collaborer sur des documents PDF.

L'emploi est fort simple : on ouvre le PDF avec Xournal, on utilise l'un des outils d'écriture ou de dessin (crayon, surligneurs, règle...) pour annoter puis on exporte le nouveau PDF.

Xournal.png

Xournal est disponible au téléchargement ici : http://xournal.sourceforge.net/. Sur Linux, vous le trouverez sans doute dans votre système de paquets, sur Windows, vous pourrez télécharger la petite archive contenant l'exécutable et ses dépendances.

Souhaitant déployer l'outil sur tous les postes informatiques (Windows) de mon entreprise, j'ai fabriqué un installateur simple pour l'outil à l'aide de NSIS. Par défaut, les installateurs de NSIS acceptent d'être appelés en mode silencieux à l'aide du paramètre "/S" et l'installateur généré peut être utilisé pour un déploiement en masse avec un outil comme Updatengine.

Télécharger l'installateur

Testé fonctionnel sur Windows 7 32 bits et 64 bits. xournal-0.4.8-win32-installer.exe

Le code de génération de l'installateur avec NSIS :

!define APPNAME "Xournal"
!define DESCRIPTION "Annotate PDF"
# These three must be integers
!define VERSIONMAJOR 0
!define VERSIONMINOR 4
!define VERSIONBUILD 8
!define INSTALLSIZE 7233
 
RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on)
 
InstallDir "$PROGRAMFILES\${APPNAME}"
 
# This will be in the installer/uninstaller's title bar
Name "${APPNAME}"
Icon "xournal.ico"
outFile "xournal-0.4.8-win32-installer.exe"
 
!include LogicLib.nsh
 
# Just 2 pages - install location and installation
page directory
Page instfiles
 
!macro VerifyUserIsAdmin
UserInfo::GetAccountType
pop $0
${If} $0 != "admin" ;Require admin rights on NT4+
        messageBox mb_iconstop "Administrator rights required!"
        setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED
        quit
${EndIf}
!macroend
 
function .onInit
	setShellVarContext all
	!insertmacro VerifyUserIsAdmin
functionEnd
 
section "install"
	# Files for the install directory - to build the installer, these should be in the same directory as the install script (this file)
	setOutPath $INSTDIR
	# Files added here should be removed by the uninstaller (see section "uninstall")
	file "xournal.exe"
	file "xournal.ico"
	file "README.txt"
	file "*.dll"
	file /r "etc"
	file /r "html-doc"
	file /r "lib"
	file /r "pixmaps"
	file /r "share"
	# Add any other files for the install directory (license files, app data, etc) here
 
	# Uninstaller - See function un.onInit and section "uninstall" for configuration
	writeUninstaller "$INSTDIR\uninstall.exe"
 
	# Start Menu
	createDirectory "$SMPROGRAMS\${APPNAME}"
	createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\xournal.exe" "" "$INSTDIR\xournal.ico"
	createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall ${APPNAME}.lnk" "$INSTDIR\uninstall.exe" "" ""
 
	# Registry information for add/remove programs
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME} - ${DESCRIPTION}"
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$"$INSTDIR\uninstall.exe$""
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$"$INSTDIR\uninstall.exe$" /S"
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$"$INSTDIR$""
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$"$INSTDIR\xournal.ico$""
	WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}"
	WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMajor" ${VERSIONMAJOR}
	WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMinor" ${VERSIONMINOR}
	# There is no option for modifying or repairing the install
	WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1
	WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1
	# Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size
	WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "EstimatedSize" ${INSTALLSIZE}
sectionEnd
 
 
# Uninstaller
function un.onInit
	SetShellVarContext all
 
	#Verify the uninstaller - last chance to back out
	MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next
		Abort
	next:
	!insertmacro VerifyUserIsAdmin
functionEnd
 
section "uninstall"
	# Remove Start Menu launcher
	delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk"
	delete "$SMPROGRAMS\${APPNAME}\Uninstall ${APPNAME}.lnk"
	# Try to remove the Start Menu folder - this will only happen if it is empty
	rmDir "$SMPROGRAMS\${APPNAME}"
 
	# Remove files
	delete $INSTDIR\xournal.exe
	delete $INSTDIR\xournal.ico
	delete $INSTDIR\README.txt
	delete $INSTDIR\*.dll
	rmDir /r $INSTDIR\etc
	rmDir /r $INSTDIR\html-doc
	rmDir /r $INSTDIR\lib
	rmDir /r $INSTDIR\pixmaps
	rmDir /r $INSTDIR\share
 
	# Always delete uninstaller as the last action
	delete $INSTDIR\uninstall.exe
 
	# Try to remove the install directory - this will only happen if it is empty
	rmDir $INSTDIR
 
	# Remove uninstaller information from the registry
	DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
sectionEnd

Friday, September 26 2014

Contrôleur RAID Dell PERC H310 (PowerEdge R220) et Linux, tout fonctionne !

La nouvelle gamme de serveur Dell PowerEdge R220 est équipée du contrôleur PERC H310.

Outre être compatible sans problème avec Debian Wheezy, ce contrôleur a le bon goût de pouvoir être suivi ("monitoré" si vous me pardonnez l'anglicisme) depuis Linux. En effet, comme tout le monde le sait, il est indispensable de suivre l'état d'un RAID tout au long de sa vie pour intervenir au plus vite en cas de panne de l'un des disques pour effectuer son remplacement.

Vérifier que vous avez bien un PERC H310

Le rendu de la commande

lspci

doit contenir cette ligne :

01:00.0 RAID bus controller [0104]: LSI Logic / Symbios Logic MegaRAID SAS 2008 [Falcon] ![1000:0073] (rev 03)

Charger le module du kernel Linux adéquat

Cette carte est gérée par le module

megaraid_sas

que l'on peut charger, si nécessaire, avec la commande

modprobe megaraid_sas

Installer les utilitaires adaptés

Les paquets adaptés sont disponibles sur hwraid.le-vert.net. On peut les installer en ajoutant cette ligne dans /etc/apt/sources.list :

deb http://hwraid.le-vert.net/debian wheezy main

puis

aptitude update
aptitude install megactl megaraid-status

Il est désormais possible de surveiller l'état du RAID avec la commande :

megasasctl

ou

megasasctl -B

(si, comme le PERC H310, votre carte ne comporte pas de batterie donc vous ne voulez pas avoir d'alerte pour batterie manquante)

Aussi, en installant megaraid-status, un démon de surveillance du RAID a été installé. Il enverra un courriel à root lors tout défaut sur le RAID. Je vous invite à tester cette fonctionnalité en détériorant manuellement (en débranchant un disque de la grappe par exemple - en environnement de test hein !) le RAID. Voici le style de message reçu :

This is a RAID status update from megaraidsas-statusd.  The megaraidsas-status
program reports that one of the RAIDs changed state:

-- Arrays informations --
-- ID | Type | Size | Status
a0d0 | RAID 1 | 465GiB | DEGRADED

-- Disks informations
-- ID | Model | Status | Warnings
a0e*s0 | ATA TOSHIBA DT01ACA0 465GiB | rebuild
a0e*s1 | ATA TOSHIBA DT01ACA0 465GiB | online

There is at least one disk/array in a NOT OPTIMAL state.

Report from /etc/init.d/megaraidsas-statusd on cefepime

Recevoir les courriels système envoyés à root

Si vous ne voulez pas d'un serveur courriel compliqué sur votre serveur, vous pouvez déployer le rapide et simple nullmailer. Il se chargera de renvoyer vers l'adresse spécifiée dans /etc/nullmailer/adminaddr tout message envoyé à root.

Bonne surveillance de RAID sur PERC H310 !

Thursday, August 28 2014

wget pour télécharger intelligement le contenu d'un espace webdav

Qu'on l'aime ou qu'on ne l'aime pas, la technologie webdav est assez répandue et largement utilisée par certains hébergeurs pour partager des données. On trouve sous Linux toute un panel de logiciels capables de travailler avec webdav, et vous connaissez sans doute davfs2 qui permet de monter un partage webdav comme une partition locale.

Cependant, davfs2 fonctionne à l'aide d'un cache (sensé rendre l'usage plus fluide et confortable). Ainsi, à chaque ouverture de fichier, celui est d'abord copié en zone cache (par défaut /var/cache/davfs2/) avant d'être rendu disponible. Si ce comportement est très intéressant pour des usages classiques, il devient problématique lorsque le partage est distant et les fichiers atteignent des tailles massives (plusieurs Go) avec une grosse lenteur causée par la mise en cache !

J'ai notamment trouvé ce comportement problématique avec rsync : tentant de synchroniser avec l'excellent rsync le contenu d'un partage webdav comprenant plusieurs fichiers >10 Go (partage monté avec davfs2), je me retrouvais avec rsync bloqué, apparemment sans activité et l'impossibilité de tuer les processus. Et pour cause, davfs2 faisait tout son possible pour basculer le fichier en cache avant de laisser rsync (gelé en attente) travailler dessus... Pas idéal !

Je décidais alors de remplacer rsync par wget pour mon travail de synchronisation à sens unique :

wget -c -r -nH --cut-dirs=1 -N --user="user" --password="password" http://server.tld/webdav/
  • -c pour reprendre le téléchargement s'il a été interrompu en cours de travail
  • -r pour télécharger le répertoire de manière récursive (en suivant donc les liens au sein du partage webdav)
  • -nH et --cut-dirs=1 pour ne pas copier le nom d'hôte et le premier nom de dossier dans l'arborescence locale
  • -N pour ne télécharger depuis la source que les fichiers qui n'existent pas ou n'ont pas la même taille en local

Au passage, on "gagne" la barre de progression propre à wget dont rsync ne dispose pas par défaut.

Bien évidemment, wget n'est pas rsync et wget n'a certainement pas toutes les fonctionnalités de synchronisation avancées (et diablement intelligentes) de rsync. Cependant, il se défend admirablement pour télécharger le contenu d'un espace webdav de manière intelligente et sans bloquer sur le mécanisme de cache de davfs2 !

Mais wget, le vénérable, m'a encore bien dépanné !

Une résolution DNS propre à chaque sous-réseau avec Dnsmasq !

Dnsmasq est un léger (mais performant) client DNS et DHCP. J'ai découvert dernièrement une très intéressante fonction que je m'empresse de partager avec vous : localise-queries.

Imaginez la situation suivante : votre machine est accessible depuis plusieurs interfaces réseau (par exemple plusieurs instances d'OpenVPN) et vous souhaitez offrir une résolution DNS aux clients qui se connectent sur chaque interface. Or, chaque interface dispose de sa propre adresse et de son sous-réseau propre. Comment offrir une résolution de nom qui prenne en compte le sous-réseau d'origine et adapte ses réponses en conséquence ?

Dnsmasq dispose de la fonction localise-queries pour ce faire !

On ajoute donc la ligne

localise-queries

dans le fichier de configuration /etc/dnsmasq.conf.

Puis, dans /etc/hosts (pour mémoire dnsmasq s'inspire de /etc/hosts pour établir la liste des correspondances IP/nom), nous allons définir plusieurs résolutions correspondant chacune à un sous-réseau :

10.8.300.1   nomA
10.8.301.1   nomA
10.8.302.1   nomA
10.8.300.1   nomB
10.8.301.1   nomB
10.8.302.1   nomB

On redémarre alors dnsmasq (service dnsmasq restart) et le tour est joué !

Quand on sera connecté via la sous-réseau 10.8.301.x, alors nomA sera résolu en 10.8.301.1. En revanche, lors d'une connexion via le sous-réseau 10.8.302.x, alors nomA sera résolu en 10.8.302.1 !

"Fortiche" dnsmasq !

Sunday, May 11 2014

Atom, l'éditeur texte de GitHub, compilé sous Debian Jessie

GitHub a récemment annoncé la publication des sources d'Atom, son éditeur texte moderne qui se veut une alternative à d'autres outils comme LightTable ou Brackets. Réjouissons-nous de la publication de cet outil en open source et espérons qu'il ne s'agisse pas, comme certains (pessimistes ?) le disent, une libération avant abandon !

Une version compilée pour Linux n'étant pas encore disponible, il est nécessaire d'effectuer la compilation soi-même. Je détaille ici les opérations nécessaires pour aboutir à une version compilée d'Atom sous Debian Jessie 64 bits.

Pré-requis :

  • Debian Testing/Jessie 64 bits
  • node.js v0.10.x (aptitude install nodejs)
  • npm v1.4.x (aptitude install npm)
  • libgnome-keyring-dev (aptitude install libgnome-keyring-dev)
  • exécuter la commande suivante en root ou avec sudo : npm config set python /usr/bin/python2 -g

Avant de commencer :

La compilation ne passe par défaut chez moi car il semble que node_gyp ne comprenne pas l'option 'no-parallel' envoyée par le script de compilation. Je vous conseille donc de lancer une première fois la compilation et si l'erreur "--no-parallel" est rencontrée alors effectuer l'opération suivante : modifier le fichier atom/build/node_modules/npm/node_modules/node-gyp/lib/configure.js en commentant la ligne :

argv.push('--no-parallel')

Compilation :

On récupère d'abord le code d'Atom :

git clone https://github.com/atom/atom

puis

cd atom
script/build

La version compilée se trouve dans /tmp/atom-build. Si l'on souhaite installer Atom sur le système (dans /usr/local/bin/atom) :

sudo script/grunt install

et pour générer un paquet .deb (génération du fichier dans /tmp/atom-build):

script/grunt mkdeb

Avant d'exécuter Atom, il semble qu'il faille également régler un lien de dépendance cassé :

sudo ln -sf /lib/x86_64-linux-gnu/libudev.so.1 /lib/x86_64-linux-gnu/libudev.so.0

Et voilà !

Atom est maintenant exécutable sur votre système. Mon paquet .deb est disponible au téléchargement ici (atom-0.95.0-amd64.deb). Il devrait fonctionner sur les machines Debian Testing/Jessie 64 bits.

IMPORTANT: la version 0.124 est désormais disponsible dans ce nouvel article.

Il n'y a plus qu'à découvrir ce nouvel éditeur de texte, assez sympathique il faut le reconnaître, mais dont seul l'usage prolongé pourra faire découvrir les vraies qualités !

Apache, protéger par mot de passe tout un hôte virtuel sauf certaines adresses : utilisation de LocationMatch

Il est assez classique d'utiliser les fonctions d'authentification d'Apache, par exemple auth_digest, pour sécuriser l'accès à un répertoire ou une application web propulsée par Apache.

Toutefois, il est parfois souhaitable de laisser en accès sans mot de passe une adresse spécifique, correspondant par exemple à une page publique ou à une fonctionnalité de l'application qu'un utilisateur lambda doit pouvoir déclencher.

Apache permet cela grâce à la direction "LocationMatch" et à des expressions régulières.

Par exemple, avec l'exemple ci-dessous placé dans un hôte virtuel correspondant à mon-app.domaine.tld :

<LocationMatch "^(?!/zone-publique)">
        AuthType Digest
        AuthName "mon-app"
        AuthDigestProvider file
        AuthUserFile /path/to/digest-password-file
        Require valid-user
</LocationMatch>

tout accès à l'hôte virtuel sera protégé par mot de passe sauf l'adresse http://mon-app.domaine.tld/zone-publique qui sera accessible à tous sans mot de passe.

Bons paramétrages !

Sunday, March 23 2014

Une soif immodérée pour les flux de données - car ils donnent le sentiment d'exister !

Avez-vous remarqué dernièrement la soif croissante de nos contemporains pour les flux de données, particulièrement quand il s'agit du soi ? Nous sommes entrés dans l'ère du 'Quantified self' pour reprendre les propos de Gary Wolf.

Nous devenons accrocs aux "tableaux de bord", au suivi au temps réel, à la tendance et à la statistique. D'aucuns ne peuvent s'empêcher de consulter leur compte bancaire tous les jours (et ce n'est plus le relevé ligne à ligne insipide des décennies passées mais ce sont des affichages léchés et attractifs qui regroupent les données en masses utiles), d'autres investissent dans des pèse-personnnes connectés, des montres et téléphones intelligents munis de capteurs corporels (température, rythme cardiaque, glycémie...). Et chez soi, c'est le compteur électrique ou le thermostat qui enregistrent des données qu'un esprit analytique pourra alors étudier, recouper, disséquer.

Cette passion nouvelle ne se limite cependant pas à la collecte : c'est la capacité de rétroaction qui attire tant ! On analyse des données (ou plus couramment on laisse un service externe le faire pour nous) pour les corréler à son quotidien et infléchir le cours des choses et mesurer l'impact de nos efforts. Grand bonheur pour l'être humain car ses actions modifient les variables de son tableau de bord personnel - il existe donc indubitablement - "je change la valeur donc je suis" ! Mesurer l'impact de ses actions flatte l'orgueil humain. On aimera suivre la courbe de sa masse musculaire augmenter peu à peu jour après jour en pratiquant un sport - on aimera voir s'afficher en temps réel l'économie (pécunière et environnementale) réalisée en contrôlant plus finement l'allumage du chauffe-eau et en optimisant l'utilisation de la bouilloire... La toute puissance d'une courbe dont on inverse la tendance (sic) par sa propre volonté !

Quelles perspectives ?

Je pense que l'attrait pour les tableaux de bord n'en est qu'à son début. Je suis persuadé que d'ici peu (si ce n'est pas déjà le cas) des services proposeront de collecter tous nos flux de données pour les retourner sous forme digérée, classées et analysées. Ces grandes plateformes centralisées afficheront un résumé de toutes ces variables et une notation globale : de la lettre de A (avec un beau vert satisfaisant) à E (et le rouge cramoisi qui poussera à la ré-action) en fonction d'objectifs fixés (longévité, respect de l'environnement, économie financière...).

Et si l'on détecte une glycémie anormale, alors une alimentation spécifique sera proposée. Si l'on détecte un réfrigérateur trop ancien et consommateur dans les données du compteur électrique, et qu'en plus l'historique d'achats en supermarché montre un taux de remplissage faible, on recevra une publicité pour une appareil plus petit, plus économe et plus adapté. Comment résister alors à l'impulsion de l'achat si celui-ci est rationnel, presque scientifiquement démontré comme bon ? Qu'on ne se méprenne pas ici, je ne dis pas que toutes les démarches seront mercantiles et opportunistes. Et certaines permettront sans doute de vraies optimisations et des modes de vie plus adaptés.

Mais dès lors, prenons garde à ne pas vivre avec les yeux rivés sur les variables. Une courbe ne traduit pas une vie et la statistique ne doit pas complètement décider et prendre le pas sur le libre-arbitre.

Et surtout, préparons-nous à devoir lutter pour garder le contrôle des 'variables du soi'. En France, nous savons déjà que nos prochains compteurs électriques collecteront et analyseront sans notre consentement. Méfions-nous des outils qui exploiteront nos données personnelles et nous en déposséderont. Apprêtons-nous à appliquer à nos données les exigences de liberté qui nous animent dans le logiciel libre. Commençons dès aujourd'hui à réfléchir et proposer des services libres et alternatifs pour l'analyse de nos données. La soif pour les flux de données et les tableaux de bord est peut-être immodérée - mais oeuvrons alors à ce que les tableaux de bord soient libres, auto-hébergés et parfaitement contrôlés par l'individu qui les utilise !

Sunday, November 10 2013

Installation et paramétrage d'un serveur avec conteneurs LXC chez Online.net/Dedibox

Nous allons décrire ici l'installation et la paramétrage d'un serveur dédié chez Online.net (offres Dedibox). La description de l'installation ne sera peut-être pas exhaustive et se concentrera sur les points clés, ceux qui par exemple ont été bloquants lors de notre déploiement.

Au niveau des technologies utilisées...

Nous allons déployer une version Debian stable (7.x à l'écriture de ces lignes) avec LVM2 (pour le découpage de l'espace disque) étant entendu que le RAID est géré matériellement et ne demande pas de paramétrage au niveau du système. La technologie LXC (LinuX Containers) sera utilisée pour séparer les servicse dans plusieurs conteneurs indépendants.

Pour le réseau, chaque conteneur disposera de sa propre IPv6 et sera donc accessible directement. En IPv4 en revanche, on déploiera un réseau local IPv4 avec un NAT pour répartir le trafic sur les différents conteneurs.

Paramétrage du réseau IPv6 chez Online.net

Chez Online.net, un bloc /48 est attribué avec chaque serveur dédié. Pour gérer l'IPv6 sur le serveur, il faudra installer le client Dibbler (un client DHCPv6) :

aptitude install dibbler-client

puis modifier la clé DUID dans le fichier /var/lib/dibbler/client-duid pour insérer celle attribuée par Online.net dans l'interface d'administration du système. Enfin, on modifiera le fichier de configuration /etc/dibbler/client.conf tel que suit :

log-level 7
iface br0 {
    pd
    option dns-server
    option domain
}

On modifie alors le fichier /etc/network/interfaces pour contenir les éléments suivants :

auto br0
iface br0 inet static
    address 88.123.123.123
    netmask 255.255.255.0
    gateway 88.123.123.1
    bridge_ports eth0

iface br0 inet6 static
    address 2001:abcd:abcd:abcd::
    gateway fe80::123:1234:1234:1234
    netmask 56

Vous aurez bien sûr pris le soin de remplacer 2001:abcd:abcd:abcd:: par l'adresse IPv6 correspondant au bloc /56 que vous avez décidé d'attribuer à votre serveur dédié et de spécifier la bonne passerelle (la passerelle par défaut est aussi l'adresse du routeur auquel est connecté votre Dedibox, vous pourrez trouver dans les logs de Dibbler l'adresse de ce routeur). Et remplacer 88.123.123.123 par l'adresse IPv4 qui vous a été attribuée (et spécifier la passerelle correspondante).

Ce paramétrage correspond à la mise en place d'un pont réseau (bridge) ce qui permettra à toutes les machines virtuelles de communiquer entre elles et de partager les communications réseau.

On redémarre alors le réseau :

/etc/init.d/networking restart

(si vous êtes connecté en SSH, il faudra peut-être se reconnecter en utiliser les nouvelles adresses spécifiées - pour forcer la connexion SSH en IPv6 il faudra utiliser ssh -6 et ssh -4 pour forcer l'IPv4)

puis on redémarre Dibbler par les commandes habituelles :

/etc/init.d/dibbler-client stop 
/etc/init.d/dibbler-client start

Une fois les conteneurs en place, nous reviendrons sur ce paramétrage pour y apporter quelques légères modifications.

Création de volumes virtuels avec LVM pour héberger les conteneurs

Chaque conteneur sera contenu dans un espace logique géré par LVM. Cela permettra notamment une manipulation aisée pour le redimensionnements, les sauvegardes...

Lors de l'installation initiale, nous avons donc pris le soin de garder une grosse partition /dev/sdaX non utilisée - c'est elle que nous allons déclarer comme volume physique pour LVM.

Il faut d'abord s'assurer que /dev/sdaX n'est pas mentionné dans /etc/fstab et le cas échéant commenter la ligne correspondante.

Puis on crée le volume physique :

pvcreate /dev/sdaX
vgcreate vg /dev/sdaX

et 2 volumes logiques de 50 Go :

lvcreate -n Nom1 -L 50g vg
lvcreate -n Nom2 -L 50g vg
mkfs.ext4 /dev/vf/Nom1
mkfs.ext4 /dev/vf/Nom2

Installation de LXC et déploiement du premier conteneur

aptitude install lxc lxc lxctl bridge-utils debootstrap unzip

installera les éléments nécessaires. Puis on modifiera /etc/fstab pour contenir :

cgroup        /sys/fs/cgroup        cgroup        defaults    0    0

La commande lxc-checkconfig permet de vérifier si tout est paré et donné des aides pour la résolution d'éventuels problèmes. Une fois que tous les paramètres de lxc-checkconfig sont au vert, on se lance pour de vrai !

A noter que le template Debian 7 inclus par défaut pour LXC dans Debian 7 est défectueux (cf. 'The Debian 7 template is broken' in [https://wiki.debian.org/LXC |https://wiki.debian.org/LXC] et la solution proposée ici par Rob van der Hoeven). Les lignes ci-dessous correspondent à la solution proposée par Rob.

On déploie un template fonctionnel :

cd /usr/share/lxc/templates/
wget http://freedomboxblog.nl/wp-content/uploads/lxc-debian-wheezy.gz
gzip -d lxc-debian-wheezy.gz
chmod u+x lxc-debian-wheezy

et on lance la création du premier conteneur :

lxc-create -n myfirstcontainer -t debian-wheezy

On déplace alors le conteneur dans le premier disque logique LVM que nous avions créé précédement :

cd /var/lib/lxc/
mv myfirstcontainer myfirstcontainer-tmp
mkdir myfirstcontainer
mount /dev/vg/Nom1 myfirstcontainer
cd myfirstcontainer-tmp
cp -R * ../myfirstcontainer/
cd ..
rm -Rf myfirstcontainer-tmp

et on paramètre le conteneur comme suit dans /var/lib/lxc/myfirstcontainer/config :

lxc.utsname = container1
lxc.network.type = veth
lxc.network.veth.pair = vethcontainer1
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 192.168.0.101/24  #on attribue une adresse IPv4 de réseau local
lxc.network.ipv4.gateway = 192.168.0.1  #la passerelle, nous allons attribuer cette adresse ensuite à l'hôte physique
lxc.network.hwaddr = 00:11:D0:14:84:BE  #attention, à modifer par une valeur aléatoire si vous installez plusieurs machines pour qu'il n'y ait pas collision !
lxc.network.ipv6 = 2001:abcd:abcd:abcd::101/56  #une adresse appartenant au bloc /56 attribué au serveur dédié

et on modifie les paramétrages réseau au sein du conteneur dans /var/lib/lxc/myfirstcontainer/rootfs/etc/network/interfaces :

auto eth0
iface eth0 inet static
    address 192.168.0.101

iface eth0 inet6 static
    address 2001:abcd:abcd:abcd::101
    netmask 56
    post-up ip -6 route add default via 2001:abcd:abcd:abcd::

Sur la machine hôte, on modifie alors les paramètres tel que suit :

  • on indique à Dibbler de ne pas chercher à paramétrer l'interface virtuelle vethcontainer1 en ajoutant dans la configuration de Dibbler :
iface vethcontainer1 no-config
  • on met en place le réseau IPv4 par :
ip addr add 192.168.0.1 dev br0
ip route add 192.168.0.0/16 dev br0
iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
  • on met en place le réseau IPv6 par :
ip -6 route add 2001:abcd:abcd:abcd::101 dev br0
  • on modifie les paramétrages réseau du système en modifiant /etc/sysctl.conf :
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra = 2

et sysctl -p pour prendre en compte ces paramétrages.

Si la connectivité IPv6 disparaît, alors il faudra se reconnecter en IPv4 et lancer les commandes suivantes :

ip -6 route add aa:bb:cc:dd:ee::/64 dev br0
ip -6 route add default via aa:bb:cc:dd:ee::1 dev br0
/etc/init.d/dibbler-client stop
/etc/init.d/dibbler-client start

en remplaçant aa:bb:cc:dd:ee::1 par l'adresse de la passerelle IPv6 (cette adresse est normalement communiquée par les Router Advertisements).

Tout semble alors prêt pour le démarrage du conteneur !

Lancement du conteneur

lxc-start -d -n myfirstcontainer

et on peut alors s'y connecter en console via :

lxc-console -n myfirstcontainer

Par défaut, le mot de passe root est root (c'est le paramétrage par défaut du template que nous avons utilisé - il va de soi que nous allons rapidement modifier ce paramétrage).

Pour quitter la console LXC, il faudra faire Ctrl+a puis d.

Dans le conteneur, on pourra vérifier que :

  • ping 192.168.0.1 fonctionne (ping de la machine hôte physique)
  • ping 8.8.8.8 fonctionne (ping vers l'extérieur, le web)
  • ping -6 2001:abcd:abcd:abcd:: fonctionne (ping de la machine hôte physique en IPv6)
  • ping -6 2001:4860:4860::8888 fonctionne (ping vers le web en IPv6)

Si tout fonctionne comme attendu, on peut alors poursuivre l'installation du système. On pourra par exemple :

  • créer des conteneurs additionnels (en adaptant quelque peu le paramétrage réseau afférent)
  • paramétrer iptables et ip6tables sur l'hôte physique et les conteneurs pour protéger les systèmes et rediriger le trafic IPv4 sur les conteneurs
  • installer Pound comme reverse proxy pour diriger le trafic HTTP/HTTPS IPv4 vers les différents conteneurs sous-jacents

Exemple de configuration iptables sur l'hôte physique

#!/bin/bash
IPTABLES='/sbin/iptables';

CT1_HOST="192.168.0.101";
CT2_HOST="192.168.0.102";
MONITORING_ONLINE="88.190.254.18";
LAN="192.168.0.0/24";
WAN_IFACE="br0";
WAN_IP="88.123.123.123";
# Flushing tables
$IPTABLES -F
$IPTABLES -X
$IPTABLES -t nat -F
# Define default policy
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT

$IPTABLES -A INPUT -j ACCEPT -d $LAN;
$IPTABLES -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED

# Temporary - SSH access open to all IPs on port 22 but Fail2ban is working.$
$IPTABLES -A INPUT -j ACCEPT -p tcp --dport 22
# Opens to ping from online monitoring
$IPTABLES -A INPUT -j ACCEPT -p icmp -s $MONITORING_ONLINE

# Accepts connection to ports 80 and 443
$IPTABLES -A INPUT -j ACCEPT -p tcp --dport 80
$IPTABLES -A INPUT -j ACCEPT -p tcp --dport 443

# Rediriger le port 123 vers le container 1
$IPTABLES -t nat -A PREROUTING -p tcp --dport 123 -d $WAN_IP -j DNAT --to-destination $CT2_HOST:123

# Rediriger un port 456 vers le container 2
$IPTABLES -t nat -A PREROUTING -p tcp --dport 456 -d $WAN_IP -j DNAT --to-destination $PAB2_HOST:456

# Activating masquerade FROM local network
$IPTABLES -t nat -A POSTROUTING -o $WAN_IFACE -s $LAN -j MASQUERADE

Exemple de configuration de pound sur l'hôte physique

User		"www-data"
Group		"www-data"
RootJail	"/chroot/pound"

## Logging: (goes to syslog by default)
##	0	no logging
##	1	normal
##	2	extended
##	3	Apache-style (common log format)
LogFacility local0
LogLevel 1

## check backend every X secs:
Alive		180

## use hardware-accelleration card supported by openssl(1):
#SSLEngine	"<hw>"

# poundctl control socket
Control "/var/run/pound/poundctl.socket"

ListenHTTP
	Address 88.123.123.123
	Port	80

	## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
	xHTTP		2

        #Les services à envoyer sur le premier conteneur
	Service
		HeadRequire "Host: .*(domaine1.fr|domaine2.fr|domaine3.fr).*"
		BackEnd
			Address	192.168.0.101
			Port	8080
		End
	End

        #Les services à envoyer sur le second conteneur
        Service
                HeadRequire "Host: .*(domaine4.fr|domaine5.fr).*"
                BackEnd
                        Address 192.168.0.102
                        Port    8080
                End
        End

End

ListenHTTPS
        Address 88.123.123.123
        Port    443
	Cert    "/path/to/certificate/pound.pem"

	HeadRemove "X-Forwarded-Proto"
        AddHeader "X-Forwarded-Proto: https"

        ## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
        xHTTP           2

        #Les services à envoyer sur le premier conteneur
	Service
		HeadRequire "Host: .*(domaine1.fr|domaine2.fr|domaine3.fr).*"
		BackEnd
			Address	192.168.0.101
			Port	8080
		End
	End

        #Les services à envoyer sur le second conteneur
        Service
                HeadRequire "Host: .*(domaine4.fr|domaine5.fr).*"
                BackEnd
                        Address 192.168.0.102
                        Port    8080
                End
        End

End

- page 4 of 6 -