Mot-clé - adminsys

Fil des billets

vendredi 18 décembre 2015

Xivo/Asterisk, message audio personnalisé pour la messagerie

Si, comme moi, vous avez longuement cherché le moyen de modifier le message d'absence dans l'interface de Xivo, ne cherchez plus ! Il se paramètre très facilement sans passer par l'interface graphique en plaçant le fichier .wav adapté à cet emplacement :

/var/spool/asterisk/voicemail/contexte_du_client/numéro_boite_vocale/unavail.wav

Il suffit de le savoir !

Apache 2 : SetEnvIf et variables d'environnement, e.g. n'autoriser que certaines IP ou UserAgent à se connecter

Le serveur web Apache est extrêmement modulable quand il s'agit de filtrer des requêtes. Si tout le monde connaît les habituelles commandes Require all denied, Require all granted, Require Host example.org, nous allons voir ici comment utiliser une variable interne d'environnement et l'utiliser comme contrôle d'accès à un hôte virtuel.

Imaginons par exemple le cas suivant : nous souhaitons n'autoriser que certaines IP à se connecter, sauf pour les navigateurs dotés d'un User-Agent très spécifique.

Avant toute chose, il est nécessaire d'activer le module SetEnvIf (https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html) qui permet de paramétrer une variable d'environnement d'Apache. Sous Debian (ou dérivé), cela se fera par :

a2enmod setenvif

Commençons par placer une condition sur l'IP :

SetEnvIf Remote_Addr 1.2.3.4 variable

ou alors si le serveur se trouve derrière un proxy qui fournit l'adresse d'origine dans le champ X-Forwarded-For :

SetEnvIf X-Forwarded-For 1.2.3.4 variable

La valeur fixe 1.2.3.4 peut-être remplacée par toute expression régulière de son choix.

Puis filtrons sur le User-Agent :

SetEnvIf User-Agent ^MaValeurPerso variable

Et finalement, expliquons à Apache qu'il faut interdire l'accès si aucune des conditions n'a été atteinte :

Require env variable

Dès lors, une fois la configuration rechargée, Apache n'autorisera l'accès qu'aux requêtes provenant de 1.2.3.4 ou émises par un navigateur au User-Agent correspondant à l'expression régulière ^MaValeurPerso. Ces éléments de configuration offrent beaucoup de richesse !

samedi 12 septembre 2015

Réparer PG::UniqueViolation: ERROR: Duplicate Key Value Violates Unique Constraint 'nom_de_votre_table_pkey'

Postgresql conserve en mémoire la valeur maximale attribuée au champ 'id' et utilise cette valeur pour générer un nouvel 'id' quand un nouvel enregistrement est pris en base. Cependant, si vous avez importé des données (par exemple depuis un fichier csv avec pgadmin3, important ainsi leurs 'id' initiaux), il se peut que la valeur maximale gardée en mémoire ne corresponde plus à la table existante. Lors d'un nouvel enregistrement, si la liste importée était plus longue que la liste initiale, ce message d'erreur risque d'apparaître :

PG::UniqueViolation: ERROR: Duplicate Key Value Violates Unique Constraint 'nom_de_votre_table_pkey'

Pour corriger l'information dans la base Postgresql, il est possible d'exécuter cette commande :

SELECT setval('nom_de_votre_table_id_seq', (SELECT MAX(id) FROM nom_de_votre_table));

SELECT MAX(id) FROM nom_de_votre_table) calcule la valeur maximale d'id existant dans les données de la table. SELECT setval('nom_de_votre_table_id_seq', value) attribue une nouvelle à la chaîne 'nom_de_votre_table_id_seq').

samedi 29 août 2015

Xivo, Polycom IP 7000 et DTMF

Pour que le DTMF d'une pieuvre Polycom IP 7000 fonctionne avec Xivo, il faut forcer l'usage du DTMF selon la RFC 2833 tel que ci-dessous :

2015-08-27_15_16_23-XiVO_-__xivo_.png

samedi 15 août 2015

Xivo et extensions Snom D715 : une intégration fort efficace

Cette article fait suite aux précédents sur l'installation et le paramétrage de Xivo (ici, ici et ici) : nous allons décrire ici l'installation des téléphones Snom D715.

Les téléphones Snom D715

La société Snom est une société allemande (il est sympathique de faire travailler nos voisins européens), elle a conçu et distribue le Snom D715 : un appareil de très bonne facture avec un excellent rapport qualité prix.

20150815-Snom-D715.jpg

Brièvement, la qualité du son est excellente, les finitions sont bonnes et le téléphone dégage dans l'ensemble une apparence de robustesse et de professionnalisme. Il accepte bien sûr une alimentation POE et dispose d'un switch intégré Gigabit qui permet de relier à des réseaux rapides mais également d'étendre le réseau à un ordinateur proche. Enfin, il dispose d'une prise pour casque, d'un port USB (pour les éventuelles extensions, mais qui délivre aussi suffisamment de courant pour recharger un téléphone portable) et est fourni avec un câble RJ45 de catégorie 6 et un support solide en plastique.

Comme il est nativement supporté par Xivo, c'est un excellent choix pour déployer un réseau VOIP à un coût acceptable : environ 90€ HT par poste.

L'installation chez Xivo

Installer le plugin Xivo pour Snom

La première étape est d'installer le plugin 'provisionning' pour les téléphones Snom. Cela se fait aisément dans Configuration > Provisioning > Plugins, puis on clique sur la petite icône 'planète terre' pour mettre à jour la liste des plugins depuis internet et, une fois les plugins visibles, on choisit "xivo-snom" puis 715-fw (correspondants aux Snom 715 & D715). Dès lors, Xivo saura communiquer avec les téléphones Snom.

Préparer un modèle de configuration qui sera déployé sur tout téléphone qui se connectera au système de provisioning Snom

Dans Configuration > Provisioning > Template device, on peut paramétrer les options qui seront données par défaut aux téléphones Snom : langue, fuseau horaire, protocole, adresse du serveur NTP et, important, les noms d'utilisateurs et mot de passe qui seront déployés sur chaque téléphone. Dans l'onglet 'Advanced', on peut alors encore un peu plus loin dans le paramétrage des téléphones.

20150815-template-device.png

Si vous comptez effectuer le provisioning avec le module DHCP de Xivo, vous pouvez sans doute vous arrêter là. En revanche, si vous escomptez ne pas utiliser le DHCP de Xivo (par exemple car vos téléphones sont sur votre réseau principal et vous ne souhaitez pas remplacer le DHCP par celui de Xivo) et préférez le provisioning http (i.e. que les téléphones interrogent le serveur de paramétrage), alors il est nécessaire de faire une petite modification supplémentaire.

Dans /var/lib/xivo-provd/plugins/xivo-snom-*/var/tftpboot/snom-general.xml, on peut trouver cette ligne :

<provisioning_order perm="R">dhcp:stop</provisioning_order>

Elle signifie que l'on demande au téléphone d'arrêter toute autre procédure après avoir reçu une réponse (même incomplète) d'un DHCP. Ce paramétrage sera transféré aux téléphones lorsqu'ils viendront se configurer auprès de Xivo.

On peut remplacer cette ligne par :

<provisioning_order perm="R">redirection:proceed dhcp:proceed</provisioning_order>

qui ordonnera au téléphone de ne pas arrêter sa configuration après l'obtention DHCP.

Démarrer les téléphones et leur indiquer l'adresse du serveur de configuration

On peut alors démarrer chaque téléphone, se connecter à l'interface de configuration du téléphone via HTTP, se rendre dans On the Setup > Advanced > Update et saisir ce paramétrage :

config_server_snom.png

On pourra également modifier le paramétrage "allow rtp on mute" tel que détaillé ici. J'imagine, mais je n'ai pas testé, que ce paramétrage peut également être paramétré dans snom-general.xml avec une ligne qui ressemblerait à :

<allow_rtp_on_mute perm="PERMISSIONFLAG">on</allow_rtp_on_mute> 

On re-démarre alors les téléphones. Ils ont se connecter à Xivo, se configurer et bientôt ils apparaîtront dans la liste des périphériques connectés à Xivo.

Et ensuite ?

Il est alors possible de créer les utilisateurs, de leur attribuer des lignes et des terminaisons, et hop le tour est joué !

vendredi 14 août 2015

Xivo, activer l'annuaire inversé pour que les téléphones affichent un nom plutôt qu'un numéro

Il est souvent plus commode de voir s'afficher le nom de son correspondant plutôt qu'un numéro. Cela est bien sûr possible sur Xivo (au moins avec les terminaisons VOIP compatibles, mais je subodore non testé cependant que cela fonctionnerait pour toutes).

Nous allons voir ici comment faire.

Sur les téléphones

Il n'y a rien à faire :-)

Sur le serveur Xivo

Nous allons procéder en 3 temps :

  1. nous allons d'abord activer la fonction d'annuaire inversée sur Xivo en précisant quel(s) annuaires doivent être consultés pour la fonctionnalité
  2. nous allons ensuite paramétrer les champs qui seront interrogés pour la requête inversée
  3. et enfin nous définirons le champ retourné pour affichage si le numéro est reconnu*

Activer l'annuaire inversé

Il faut se rendre dans Services > CTI server > Directories > Reverse directories : 20150804-xivo-reverse.png puis faire glisser vers la boîte de droite les annuaires que l'on veut voir utilisés pour la fonction d'annuaire inversé.

Paramétrer les champs utilisés pour la requête inversée

Dans Services > CTI server > Directories > Definitions, on choisit de modifier l'annuaire xivodir : 20150804-xivo-reverse-2.png

Dans le champ Match reverse directories, on spécifie chaque champ qui est utilisé pour retrouver le numéro de téléphone de l'appelant, par ex.

phonebooknumber.office.number,phonebooknumber.mobile.number,phonebooknumber.home.number

Attention ! Il est très important d'avoir une ligne dans "Mapped fields" pour chacun des champs ! Ainsi, si Match reverse directories contient "phonebooknumber.office.number,phonebooknumber.mobile.number,phonebooknumber.home.number" alors il faut voir une ligne pour chacun dans la liste ci-dessous. On peut ajouter une nouvelle ligne à l'aide du bouton plus.

image4144.png

Paramétrer le champ affiché

Lorsqu'un numéro est trouvé dans l'annuaire, c'est le contenu du champ "reverse" qui est envoyé au téléphone pour affichage. Par défaut, "reverse" pointe vers "phonebook.fullname" : vous pouvez modifier ce champ à votre gré.

Redémarrer les services pour la bonne forme

Pour la bonne ferme, on pourra redémarrer les services en charge des annuaires :

service xivo-ctid restart
service xivo-agid restart

Xivo, ajouter un annuaire consultable depuis les téléphones

Il est pratique de pouvoir consulter un annuaire directement depuis des postes téléphoniques (VOIP) connectés au PBX Xivo.

Sur les postes téléphoniques

Si les téléphones utilisés sont compatibles avec Xivo (et sont auto-provisionnés, i.e. qu'ils sont configurés automatiquement par Xivo), alors l'accès à l'annuaire doit être fonctionnel très facilement. Il faudra bien sûr localiser, si elle existe, la touche du téléphone qui permet d'ouvrir l'annuaire. Aucune action spécifique n'est à effectuer.

Sur le serveur Xivo

Nous allons commencer par autoriser une plage d'IPs à se connecter à l'annuaire Xivo : pour cela, il faut se rendre dans IPBX > General settings > Phonebook. Puis cliquer sur le signe '+' pour ajouter un hôte à la liste des hôtes autorisés à se connecter à l'annuaire. On peut alors ajouter l'adresse IP d'un téléphone autorisé à afficher l'annuaire. Alternativement, on peut ajouter toute une plage d'IP par ex. 192.168.1.0 pour tous les postes dont l'IP appartiendra à la plage 192.168.1.x.

20150814-xivo-open-phonebook.png

La deuxième étape consiste à peupler d'adresses l'annuaire. Il faut aller dans IPBX Services > Phonebook et cliquer sur le '+' visible dans la barre bleue.

20150814-xivo-add-in-phonebook.png et 20150814-xivo-add-in-phonebook-2.png

On peut alors ajouter une entrée manuellement ou bien importer une liste à partir d'un fichier CSV. Le fichier CSV devra contenir une première ligne d'en-têtes donnant la teneur de chaque colonne, les champs devront être séparés par |. La liste des champs obligatoires (il y en a) et autorisés se trouve ici : http://xivo.readthedocs.org/en/latest/administration/phonebook.html.

Et voilà, les téléphones VOIP connectés à Xivo peuvent désormais consulter l'annuaire téléphonique !

Xivo, un PBX libre et français : installation et premiers paramétrages

Xivo est un logiciel libre d'autocommutateur privé (PBX) basé sur Asterisk et Debian, et (cerise sur le gateau) développé par des français : que des bons arguments. Nous allons détailler ici l'installation de Xivo et quelques paramétrages pour bien démarrer.

logo-xivo.jpg

Installation à partir de l'iso Xivo sur une machine physique

La dernière version peut être téléchargée sur le site de Xivo : http://www.xivo.io/. Une fois placée sur une clé USB ou tout autre périphérique bootable, on peut lancer le processus d'installation qui est basé sur l'installateur de Debian.

Si Xivo ne m'a apporté que du bonheur une fois installé, il faut noter que l'installation a été quelque peu difficile. Avec l'installateur non graphique, en fin d'installation, on a l'impression que l'installateur se fige (souvent sur console-setup à 97%). Ce bug est déjà rapporté ici. Toutefois, dans mon expérience, le gel n'est qu'apparent : si l'on exécute Ctrl+Alt+F1 puis Ctrl+Alt+F2 on rafraîchit manuellement l'affichage. Clairement pas idéal, mais au moins cela permet d'achever l'installation.

Il se lit sur internet que l'installation ne pose pas de problème en mode graphique, je recommanderai donc ce choix par défaut à ceux qui veulent tenter l'aventure !

20150814-xivo-install.png

Il est également possible d'installer Xivo depuis une installation fraîche de Debian Wheezy en suivant les instructions détaillées ici. Cela fonctionne plutôt bien, cela me semble une bonne alternative !

Et pour le test ?

Xivo se déploie sans peine sur Virtualbox (4.3.30_Debian) à condition d'installer une version minimale de Debian Wheezy puis d'exécuter le script d'installation tel que détaillé ici. Pratique !

Premier démarrage

Là encore, mon premier démarrage n'a pas été aussi facile qu'espéré. Après plusieurs essais infructueux, je présente ici la suite d'actions qui a fonctionné chez moi. Notez que cela n'est pas tout à fait identique à la documentation officielle. Je vous conseille de suivre d'abord la documentation officielle et de n'utiliser ma petite "méthode" qu'en cas de besoin. Dans mon cas, le démon xivo-provd ne démarrait pas lors du premier démarrage de la machine ce qui bloquait la configuration avec l'interface web...

Au premier démarrage de la machine xivo, si nécessaire, on modifie la configuration réseau dans /etc/network/interfaces puis on affecte la valeur startup = yes dans /etc/default/xivo. Et on redémarre.

Une fois la machine à nouveau prête, on peut se connecter à l'interface d'administration de Xivo depuis une autre machine en saisissant l'adresse http://192.168.a.b où 192.168.a.b est l'adresse IP de la machine Xivo.

Et on peut alors se laisser guider dans la configuration avec l'utilitaire assisté.

wizard_step4_configuration.png

Quelques ressources pour bien démarrer

Paramétrer un SIP trunk

Si vous avez l'ambition d'atteindre l'extérieur depuis les postes connectés au PBX Xivo, il est probable que vous souhaitiez connecter un SIP trunk. Tout se passe dans IPBX > Trunk management > SIP protocol.

Pour ce faire, vous pouvez suivre cette documentation : http://xivo.readthedocs.org/en/latest/administration/interconnections/xivo_with_voip_provider.html

En sus des paramétrages évoqués, j'ai ajouté ces 2 options :

  • DTMF : RFC2833, cela a ensuite fonctionné sans souci avec un SIP trunk d'OVH
  • Monitoring : 2000ms, car la machine Xivo se trouve derrière un NAT

20150814-extra-params-xivo.png

Retrouver un mot de passe perdu

Si vous avez égaré le mot de passe d'accès à l'interface web de Xivo, pas de panique : cette commande exécutée en root sur la machine vous permettra de le retrouver :

sudo -u postgres psql -c 'select login, passwd from "user"' asterisk

mercredi 12 août 2015

Dnsmasq, mon meilleur ami aussi pour le boot PXE !

Dnsmasq est un super petit serveur DNS et DHCP à destination des bricoleurs : fort simple à déployer et utiliser, il est parfait pour les installations domestiques ou celles des petites entreprises (on en a déjà parlé ici, ici et ici). Dnsmasq est par exemple employé au sein du micrologiciel (firmware) pour routeur Tomato car il est léger et en même temps très puissant.

J'ai découvert aujourd'hui une nouvelle corde à l'arc de Dnsmasq : il possède des fonctionnalités TFTP (Trivial File Transfer Protocol) qui permettent de l'utiliser pour booter un ordinateur (un serveur par exemple) en mode PXE (Preboot Execution Environment) en quelques lignes de configuration seulement.

L'usage est fort simple, tout se règle dans le fichier de configuration /etc/dnsmasq.conf :

dhcp-boot=pxelinux.0,pxeserver,192.168.18.11
pxe-service=x86PC, "Install Linux", pxelinux
enable-tftp
tftp-root=/tmp/tftp

Les 4 lignes sont assez explicites :

dhcp-boot=pxelinux.0,pxeserver,192.168.18.11
pxe-service=x86PC, "Install Linux", pxelinux

propose à chaque système en faisant la requête de démarrer en mode PXE en interrogeant 192.168.18.11 comme serveur de boot PXE. Pour que la suite fonctionne, il faut évidemment que 192.168.18.11 pointe vers l'hôte hébergeant le service Dnsmasq lui-même.

Puis

enable-tftp

active le TFTP de Dnsmasq.

Et enfin,

tftp-root=/tmp/tftp

indique où trouver le répertoire qui sera servi au travers de TFTP.

Si l'on veut démarrer l'installation de Debian par exemple, on aura préalablement décompressé netboot.tar.gz dans ce dossier ! Et miracle, tout périphérique cherchant à démarrer avec PXE sur le réseau va interroger Dnsmasq et récupérer le nécessaire pour le boot. Démarrer un serveur en PXE devient alors très facile !

mardi 11 août 2015

Déployer silencieusement TightVNC Server sur un parc de machines

TightVNC Server se déploie assez facilement sur un parc de machines Windows à l'aide de la commande :

msiexec /i tightvnc-2.7.10-setup-64bit.msi /quiet /norestart ADDLOCAL="Server" VIEWER_ASSOCIATE_VNC_EXTENSION=1 SERVER_REGISTER_AS_SERVICE=1 SERVER_ADD_FIREWALL_EXCEPTION=1 VIEWER_ADD_FIREWALL_EXCEPTION=1 SERVER_ALLOW_SAS=1 SET_USEVNCAUTHENTICATION=1 VALUE_OF_USEVNCAUTHENTICATION=1 SET_PASSWORD=1 VALUE_OF_PASSWORD=unmotdepasse SET_USECONTROLAUTHENTICATION=1 VALUE_OF_USECONTROLAUTHENTICATION=1 SET_CONTROLPASSWORD=1 VALUE_OF_CONTROLPASSWORD=autremotdepasse

Les paramètres fournis à l'installateur sont assez explicites : on demande au serveur de s'enregistrer comme un service, on paramètre les mots de passe d'accès pour le client mais aussi pour le changement de configuration du serveur...

Le déploiement se passe à merveille avec Updatengine dont nous avons déjà parlé ici :

20150811-tightvnc.png

dimanche 26 juillet 2015

Message d'erreur récurrent sur Debian Jessie avec MariaDB

/etc/cron.daily/logrotate:
error: error running shared postrotate script for '/var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log /var/log/mysql/error.log '
run-parts: /etc/cron.daily/logrotate exited with return code 1

est le message reçu ponctuellement sur une machine Debian Jessie équipée de MariaDB.

Après une petite recherche au sein des scripts de logrotate, je réalisais que cette ligne :

MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"

appelait la configuration placée dans /etc/mysql/debian.cnf qui ressemble à :

[client]
host     = localhost
user     = root
password = 
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = root
password =
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

On note bien l'absence de mot de passe pour l'utilisateur root qui explique la non-complétion du script de logrotate.

Pour régler temporairement le problème, on peut :

  • créer un utilisateur "debian-sys-maint" avec les droits administrateurs sur le serveur MariaDB
  • donner un mot de passe aléatoire à cet utilisateur
  • compléter le fichier /etc/mysql/debian.cnf de manière adéquate :
[client]
host     = localhost
user     = debian-sys-maint
password = motdepassealeatoire
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = debian-sys-maint
password = motdepassealeatoire
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

dimanche 7 juin 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.

dimanche 17 mai 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 !

samedi 16 mai 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.

dimanche 4 janvier 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

Tomato, VLAN & WAN: this is poorly documented!

It is not obvious to change the VLAN for the WAN port on a router using the Tomato firmware. This might be a necessity when the PPPoE infrastructure of your internet provider requires such a setting.

This is the case in France with the Orange provider (not for DSL but for fiber access): the internet traffic should transit on the VLAN 835.

To do so with Tomato:

  1. choose the PPPoE connection for the WAN (do not forget username and password if needed)
  2. get to the Advanced settings, VLAN page and change the VID for the WAN to correspond to the required VLAN. With some routers (such as the Asus RT-N16), changing the VID does not work and you should in fact add an offset and change the VLAN number. As an example, for VLAN 835, you have to choose a VID offset of 832 and set the WAN to the VLAN 3. Then VID should automatically change to 835.
  3. save and reboot, the WAN connection should now work

You can see below the appropriate setting for a WAN over VLAN 835 as requested by French Orange provider.

vlan835-orange-tomato.png

Hope this helps!

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.

vendredi 2 janvier 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.

dimanche 28 décembre 2014

Errors were encountered while processing: sane-utils

Petit problème rencontré avec Debian lors d'une mise à jour :

The following partially installed packages will be configured:
  sane-utils 
No packages will be installed, upgraded, or removed.
0 packages upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
Need to get 0 B of archives. After unpacking 0 B will be used.
Setting up sane-utils (1.0.24-7) ...
saned:x:109:115::/home/saned:/bin/false
Moveing homedir from /home/saned to /var/lib/saned
usermod: user saned is currently used by process 1799
dpkg: error processing package sane-utils (--configure):
 subprocess installed post-installation script returned error exit status 8
Errors were encountered while processing:
 sane-utils
E: Sub-process /usr/bin/dpkg returned an error code (1)
Failed to perform requested operation on package.  Trying to recover:
Setting up sane-utils (1.0.24-7) ...
saned:x:109:115::/home/saned:/bin/false
Moveing homedir from /home/saned to /var/lib/saned
usermod: user saned is currently used by process 1799
dpkg: error processing package sane-utils (--configure):
 subprocess installed post-installation script returned error exit status 8
Errors were encountered while processing:
 sane-utils

Cela semble pouvoir se régler en tuant le processus 1799 puis en effectuant la modification de dossier 'home' manuellement pour l'utilisateur saned :

kill 1799
usermod -d /var/lib/saned saned

Et hop le tour est joué !

Bonne journée.

mercredi 10 décembre 2014

Activer la recherche des commandes historiques dans ZSH

J'ai réalisé que par défaut, il n'était pas possible de rechercher dans l'historique des commandes avec mon shell ZSH (avec la commande Ctrl+R que j'avais déjà utilisée avec d'autres shells). Quà cela ne tienne ! Paramétrons correctement le ~/.zshrc pour réactiver cette fonctionnalité.

Il suffit d'ajouter ces quelques lignes à son .zshrc (celui de son /home ou bien celui général /etc/zsh/zshrc si l'on veut que cela s'applique à tous les utilisateurs) :

bindkey -v
bindkey '^R' history-incremental-search-backward
HISTSIZE=1000
SAVEHIST=1000
HISTFILE=~/.history

pour que désormais Ctrl+R permette d'activer la recherche de commandes historiques, avec par défaut les 1000 dernières commandes saisies enregistrées.

Attention, n'oubliez pas de faire attention alors à tout mot de passe saisi à un moment ou un autre en clair en ligne de commande (par exemple pour se connecter à un FTP, un partage Samba, un webdav...) car alors le mot de passe en clair sera conservé visible dans l'historique jusqu'à sa péremption !

- page 2 de 3 -