ADX - Le Bloghttps://blog.devarieux.net/2022-12-12T08:55:00+01:00Yet Another BlogAuthentification Wifi iPSK avec Cisco ISE2022-12-12T08:55:00+01:002022-12-12T08:55:00+01:00Aldevartag:blog.devarieux.net,2022-12-12:/2022/12/ise-ipsk.html<p>Je vais décrire dans cet article comment configurer Cisco ISE pour authentifier des équipements Wifi sur un réseau en utilisant le protocole RADIUS. Notamment, en fonctions de la PSK utiliser par un client Wifi, nous pourrons lui attribuer un VLAN spécifique. Ces PSK sont nommés iPSK (identity Pre Shared Key …</p><p>Je vais décrire dans cet article comment configurer Cisco ISE pour authentifier des équipements Wifi sur un réseau en utilisant le protocole RADIUS. Notamment, en fonctions de la PSK utiliser par un client Wifi, nous pourrons lui attribuer un VLAN spécifique. Ces PSK sont nommés iPSK (identity Pre Shared Key), justement grace au rôle qu'elles peuvent avoir dans l'attribution de l'identité de l'équipement, permettant de le placer dans le VLAN adequat.</p>
<p>Cisco ISE (Identity Service Engine) est une appliance proposant un grand nombre de fonctionnalités de sécurité. Il peut authentifier les utilisateurs sur le réseau (Wifi, câble ou VPN), il gère le contrôle d'accès, les politiques de groupe et peut également faire du device posturing (s'assurer qu'un équipement est à jour et que son anti-virus est activé avant de lui donner accès au réseau). Les fonctionnalités sont assez complètes et son utilisation demande une certaine expertise.</p>
<p>Pour cet article, le réseau Wifi sur lequel on s'appuit est un réseau Meraki mais je ne doute pas que le fonctionnement doit être grandement similaire avec d'autres constructeurs.</p>
<section id="configuration-meraki">
<h2>Configuration Meraki</h2>
<p>La configuration du SSID se fait dans le menu Wireless > Access Control en choisissant le SSID cible dans le menu déroulant en haut de la page.</p>
<section id="network-access">
<h3>Network Access</h3>
<p>Cette section permet de choisir le mode d'association des équipements. L'option à choisir ici est Identity PSK with Radius. Le chiffrement se fait en WPA2. Si vous avez plusieurs bornes, je vous invite à activer le mode 802.11r (fast-transition) qui améliore les performances lors du roaming.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK01.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK01.png" style="width: 431px" /></a>
</div>
</section>
<section id="splash-page">
<h3>Splash Page</h3>
<p>Nous n'utilisons pas de Splash Page sur ce SSID. Une fois associé et authentifié, l'accès au réseau se fait directement.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK02.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK02.png" style="width: 429px" /></a>
</div>
</section>
<section id="configuration-radius">
<h3>Configuration Radius</h3>
<p>Lors du choix IPSK with Radius dans la section 'Network Access', une nouvelle section dédiée à la configuration Radius apparaît.
On entre les adresses des serveurs Radius, ports et secrets. RADIUS testing est désactivé et le support de CoA est activé. Les serveurs Radius accounting sont activés et paramétrés.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK03.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK03.png" style="width: 429px" /></a>
</div>
</section>
<section id="assignement-de-l-ip">
<h3>Assignement de l'IP</h3>
<p>L'assignement de l'adresse IP de l'équipement se fait en mode Bridge. Les équipements se retrouvent sur le VLAN qui leur est assigné et peuvent recevoir une IP en DHCP via, par exemple, le serveur Cisco ISE.
Le VLAN tagging est activé avec un VLAN par défaut (ici XXX).</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK04.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK04.png" style="width: 329px" /></a>
</div>
</section>
</section>
<section id="configuration-cisco-ise">
<h2>Configuration Cisco ISE</h2>
<p>Voici le flux de données lors d'une authentification iPSK sur un serveur Cisco ISE. Cette image est directement extraite de la documentation officielle Meraki.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK05.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK05.png" style="width: 303px" /></a>
</div>
<section id="ajout-des-ap-et-assignation-a-un-groupe">
<h3>Ajout des AP et assignation à un groupe</h3>
<p>Sur ISE, aller dans Administration > Network Ressources > Network Devices et cliquer sur Add</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK06.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK06.png" style="width: 72px" /></a>
</div>
<p>Remplir les champs pour l'AP à intégrer : Nom de l'AP et adresse IP.</p>
<p>Créer une nouvelle <cite>Location</cite> du nom du lieu où sont placées les AP (par exemple Headquarter ou Agence_Rennes) et un <cite>device type</cite> MR. Ce device type permettra d'y placer l'ensemble des AP de type Meraki MR.
La localisation "Headquarters" va permettre de faire correspondre l'authentification des clients avec la bonne Policy Set (jeu de politique), que l'on verra plus tard.</p>
<p>Cocher Radius Authentication Settings et paramétrer un secret pour ce serveur Radius. Ce secret est celui utilisé dans la configuration Radius du SSID sur Meraki.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK07.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK07.png" style="width: 321px" /></a>
</div>
</section>
<section id="creer-une-policy-set">
<h3>Créer une Policy Set</h3>
<p>Créer une nouvelle Policy Set avec la condition <strong>Device>Location</strong> et sélectionner la localisation Headquarter créée précédemment. Ajouter une seconde condition <strong>Radius > Called-Station-ID Ends_With "Nom_du_SSID"</strong>.</p>
<p>J'insiste sur le fait de bien mettre la condition "Ends_With" et nom "Equals" car lors de l'authentification Radius, le nom du SSID envoyé par MEraki sera précédé d'autres informations. En mettant "Equals" l'authentification ne peut pas fonctionner.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK08.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK08.png" style="width: 436px" /></a>
</div>
<p>Sauvegarder puis se rendre dans la policy en utilisant la flèche à l'extrémité droite. Aller dans <strong>Authentication Policy</strong> et paramétrer la règle comme ci-dessous. S'assurer que le menu déroulant est bien positionné sur <strong>Internal Endpoints</strong> et que l'option <strong>If User not found Continue</strong> est bien sélectionnée. Cette option permet de continuer à vérifier l'authentification d’un équipement qui ne serait pas valide sur cette policy.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK09.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK09.png" style="width: 212px" /></a>
</div>
<p>Se rendre ensuite dans <strong>Authorization Policy</strong>. Sur la règle par défaut, supprimer <em>Deny Access</em> et cliquer sur l'icône + pour créer un nouveau profil avec les paramètres ci-dessous.
Dans <strong>Advanced Attributes</strong>, sélectionner <strong>Radius:Tunnel-Password</strong>. Entrer la PSK utilisée par défaut sur ce SSID puis sauvegarder.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK10.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK10.png" style="width: 303px" /></a>
</div>
<p>Sélectionner ce profil dans la règle par défaut puis sauvegarder.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK11.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK11.png" style="width: 420px" /></a>
</div>
</section>
<section id="creer-un-identity-group">
<h3>Créer un Identity Group</h3>
<p>Aller dans <strong>Work Center > Guest Access > Id Group</strong>.
Cliquer sur <strong>Add</strong> pour ajouter un nouveau groupe qui contiendra les équipements autorisé à s'authentifier sur le réseau Wifi.</p>
</section>
<section id="creer-une-policy-set-pour-chaque-psk">
<h3>Créer une Policy Set pour chaque PSK</h3>
<p>A partir de maintenant, nous pouvons créer une Policy Set pour chaque groupe d'équipement qui utilisera sa propre iPSK. Chaque iPSK identifiera un type d'équipement et le VLAN sur lequel il sera placé.</p>
<p>Ici, nous allons créer la policy set pour le VLAN de bureautique (VLAN 84).
Aller dans <strong>Policy > Policy Elements > Results > Authorization > Authorization Profiles</strong>. Cliquer sur <strong>Add</strong> et créer un nouveau profil. C’est celui-ci qui sera utilisé pour surcharger le VLAN par défaut si besoin.
Les champs importants sont :
- Nom du profil
- Common Tasks > VLAN > 84
- Advances Attributes Settings > Radius:Tunnel-Password ⇒ Entrer la PSK pour les équipements de bureautique (PC portable en général).</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK12.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK12.png" style="width: 252px" /></a>
</div>
<p>Aller ensuite dans <strong>Policy > Policy Sets</strong> et éditer la Policy Set créée précédemment. Dans la section <strong>Authorization Rules</strong> ajouter une nouvelle règle au-dessus de la règle par défaut.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK13.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK13.png" style="width: 246px" /></a>
</div>
<p>Nommer cette règle et lui appliquer la condition suivante, en choissant le groupe créé dans la section <strong>Créer un Identity Group</strong> :</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK14.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK14.png" style="width: 430px" /></a>
</div>
<p>Appliquer ensuite le profil d'autorisation PSK1 créé en juste au-dessus et sauvegarder.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK15.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK15.png" style="width: 426px" /></a>
</div>
</section>
<section id="ajouter-des-euipements-au-groupe">
<h3>Ajouter des éuipements au groupe</h3>
<p>Aller dans <strong>Context Visibility > Endpoints</strong>.
Ajouter un nouvel équipement en prenant soin de l placer dans le groupe créer précédement.</p>
<div class="m-image">
<a href="/images/2022-12-12-ISEiPSK16.png"><img src="https://blog.devarieux.net/images/2022-12-12-ISEiPSK16.png" style="width: 432px" /></a>
</div>
<p>Cette technique d'authentification permet donc de placer les équipements/utilisateurs sur des VLANs différents en fonction de la PSK utilisée, sans créer un SSID différent pour chaque VLAN.</p>
<p>En effet, il est déconseillé de diffuser plus de 5 SSID par AP ou par zone afin de limiter les interférences et optimiser la qualité du signal, notamment lorsqu'on souhaite y faire transiter de la voix et/ou faire du roaming. Grâce à iPSK, nous pouvons segmenter les utilisateurs dans différents VLAN en limitant le nombre de SSID diffusé.</p>
</section>
</section>
Zabbix - Authentification SAML avec Keycloak et provider Google Auth2021-12-29T00:23:00+01:002021-12-29T00:23:00+01:00Aldevartag:blog.devarieux.net,2021-12-29:/2021/12/zabbix-saml-keycloak-google.html<p>Depuis Zabbix 5.0, l'application permet de configurer une authentification SSO SAML. Le protocol SAML est utilisé par des services tel que Microsoft ADFS et Azure AD ou encore Okta.
De mon coté, j'utilise Keycloak pour mon intégration SSO. Un des providers utilisé est Google Auth.</p>
<p>Cela fait plusieurs mois …</p><p>Depuis Zabbix 5.0, l'application permet de configurer une authentification SSO SAML. Le protocol SAML est utilisé par des services tel que Microsoft ADFS et Azure AD ou encore Okta.
De mon coté, j'utilise Keycloak pour mon intégration SSO. Un des providers utilisé est Google Auth.</p>
<p>Cela fait plusieurs mois que ce chantier est mis de coté et je viens enfin de trouver le temps de finaliser la mise en oeuvre de l'authentification des comptes utilisateurs sur Zabbix en SAML, avec Keycloak et le provider Google Auth. Je vais décrire ici les étapes afin d'avoir ce type d'authentification fonctionnelle.
Je pars du principe que vous avez déjà un serveur Keycloak installé et que votre provider Google Auth est configuré.</p>
<p>L'objectif est que, au sein d'une entreprise utilisant Google Workspace, les utilisateurs de Zabbix puissent s'authentifier directement avec leurs comptes Google Workspace. Dans mon cas, Keycloak est le backend d'authentification global de l'entreprise et est utilisé par plusieurs autres applications, qu'elles soient internes ou à destination des clients.</p>
<p>
<br />
</p>
<section id="gestion-des-certificats">
<h2>Gestion des certificats</h2>
<p>La première étape est de générer un certificat pour Zabbix. Cela se passe dans <code class="code">/usr/share/zabbix/conf/certs</code>. On utilise openssl pour le générer.</p>
<div class="highlight"><pre><span></span>cd /usr/share/zabbix/conf/certs
openssl req -x509 -sha256 -newkey rsa:2048 -keyout sp.key -out sp.crt -days 3650 -nodes -subj '/CN=My Zabbix Server'
</pre></div>
<p>Cette commande génère un certificat et une clé privée pour les échanges SAML.</p>
<p>La seconde étape consiste à récupérer le certificat X509 de l'identity provider (IDP) de Keycloak. Pour moi, le plus rapide a été de me rendre sur cette URL pour y copier la chaine du certificat.</p>
<div class="highlight"><pre><span></span>https://<keycloakaddress>/auth/realms/<realmname>/protocol/saml/descriptor
</pre></div>
<p>Cette page doit afficher un bloc XML avec le nom du certificat et le certificat au format X509 entre les balises <code class="code"><ds:X509Certificate></code>. Après avoir copié ce certificat, il faut le coller sur le serveur Zabbix dans le fichier <code class="code">/usr/share/zabbix/conf/certs/idp.crt</code>. Le fichier doit ressembler à ça :</p>
<div class="highlight"><pre><span></span>-----BEGIN CERTIFICATE-----
MIICmSF...........g20plgaFEwvQERGH=
-----END CERTIFICATE-----
</pre></div>
<p>Puis changer les permissions du fichier.</p>
<div class="highlight"><pre><span></span>chmod 755 idp.crt
</pre></div>
<p>
<br />
<br />
</p>
</section>
<section id="configuration-de-keycloak">
<h2>Configuration de Keycloak</h2>
<p>Dans l'interface de Keycloak, sur votre realm, créer un client ayant pour id <code class="code">zabbix</code> et pour protocol <code class="code">SAML</code>.</p>
<div class="m-image">
<a href="/images/Keycloak-Client-Zabbix.png"><img alt="Creation du client Zabbix dans Keycloak" src="https://blog.devarieux.net/images/Keycloak-Client-Zabbix.png" style="width: 535px" /></a>
</div>
<p>
<br />
</p>
<p>Une fois le client ajouté, il faut l'éditer pour terminer sa configuration. Voici les paramètres à configurer <em>(note : mon installation de Zabbix est joignable à la racine du serveur web et non via le chemin /zabbix comme dans la configuration par defaut. Prenez soin de bien mettre le chemin complet vers votre serveur Zabbix)</em> :</p>
<ul>
<li>Master SAML Processing URL : <code>https://zabbix.domain.tld/index_sso.php?acs</code></li>
<li>Valid Redirect URL : <code>https://zabbix.domain.tld/*</code></li>
<li>Dans la section Fine Grain, Logout Service Redirect Binding URL : <code>https://zabbix.domain.tld/index_sso.php?sls</code></li>
<li>Les paramètres devant être sur 'ON' sont : <code>Include AuthnStatement, Sign Document, Force POST Binding, Front Channel Logout et Force Name ID Format.</code></li>
<li>Le Name ID Format est code : <code>email</code></li>
</ul>
<div class="m-image">
<a href="/images/Keycloak-Client-Zabbix-Configuration.png"><img alt="Configuration du client Zabbix dans Keycloak" src="https://blog.devarieux.net/images/Keycloak-Client-Zabbix-Configuration.png" style="width: 519px" /></a>
</div>
<p>
<br />
</p>
<p>Créer ensuite le Mapper, dans l'onglet Mapper du client Zabbix.</p>
<ul>
<li>Name: <code>zabbixuser</code></li>
<li>Mapper Type : <code>User Attribute</code></li>
<li>User Attribute : <code>email</code></li>
<li>Friendly Name : <code>email</code></li>
<li>SAML Attribute Name : <code>email</code></li>
</ul>
<div class="m-image">
<a href="/images/Keycloak-Client-Zabbix-Mapper.png"><img alt="Mapper du client Zabbix dans Keycloak" src="https://blog.devarieux.net/images/Keycloak-Client-Zabbix-Mapper.png" style="width: 524px" /></a>
</div>
<p>
<br />
</p>
<p>Sauvegarder cette configuration.</p>
<p>Dernière étape de la configuration de Keycloak. Aller dans <code class="code">Client Scopes</code> et sélectionner <code class="code">role_list</code> et dans l'onglet Mapper, editer le mapper <code class="code">role list</code>. Activer <code class="code">Single Role Attribute</code>.</p>
<div class="m-image">
<a href="/images/Keycloak-Client-Scopes.png"><img alt="Client Scopes dans Keycloak" src="https://blog.devarieux.net/images/Keycloak-Client-Scopes.png" style="width: 525px" /></a>
</div>
<p>
<br />
<br />
</p>
</section>
<section id="configuration-de-zabbix">
<h2>Configuration de Zabbix</h2>
<p>Connectez-vous sur Zabbix avec un compte Super Admin. Dans Administration > Authentication selectionner l'onglet SAML, l'activer et le configurer de cette façon :</p>
<ul>
<li>IdP entity ID : <code>https://<keycloakaddress>/auth/realms/<realmname></code></li>
<li>SSO service URL :<code>https://<keycloakaddress>/auth/realms/<realmname>/protocol/saml</code></li>
<li>SLO service URL : <code>https://<keycloakaddress>/auth/realms/<realmname>/protocol/saml</code></li>
<li>Username attribute : <code>email</code></li>
<li>SP entity ID : <code>zabbix</code></li>
<li>SP name ID format : <code>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</code></li>
</ul>
<p>Il faut ensuite créer les utilisateurs dans Zabbix. En effet, comme pour l'authentification LDAP / Active Directory, Zabbix s'appuit sur ces services pour authentifier des utilisateurs existants. Il faut au préalable les ajouter dans la base des utilisateurs avec les droits associés à leur compte.</p>
<p>Dans Administration > Users, créer un compte ayant pour Alias l'adresse email de l'utilisateur. Il est nécessaire de lui mettre un mot de passe, même si celui ci ne sera pas utilisé.</p>
<p>Dans une nouvelle fenêtre en navigation privée, vous pouvez vous connecter sur Zabbix en cliquant d'abord sur <strong>Sign in with Single Sign-On (SAML)</strong> puis sur la fenêtre Keycloak qui s'affiche, un bouton Google permet de finaliser l'authentification.</p>
<div class="m-image">
<a href="/images/Zabbix-Auth-SAML.png"><img alt="Page d'Authentification Zabbix avec option SAML" src="https://blog.devarieux.net/images/Zabbix-Auth-SAML.png" style="width: 200px" /></a>
</div>
<p>
<br />
</p>
<div class="m-image">
<a href="/images/Keycloak-Auth-Google.png"><img alt="Page d'Authentification Keycloak avec option Google" src="https://blog.devarieux.net/images/Keycloak-Auth-Google.png" style="width: 251px" /></a>
</div>
<p>
<br />
</p>
<p>Le bouton Logout de Zabbix doit vous ramener sur la page d'authentification de Zabbix et également vous déconnecter de Keycloak.</p>
<p>Pour moi, la prochaine étape est de faire la même chose avec Netbox.</p>
</section>
VPN Meraki et Fedora2021-04-12T18:32:00+02:002021-04-12T18:32:00+02:00Aldevartag:blog.devarieux.net,2021-04-12:/2021/04/vpn-meraki-fedora.html<p>Cela fait plusieurs années que je n'ai pas pu utiliser Linux de façon professionnelle à cause d'applications purement Windows et aussi un peu par facilité. Depuis peu, je n'ai plus à utiliser toutes ces applications je repars donc à la conquête de mon desktop avec une Fedora 33 fraichement installée …</p><p>Cela fait plusieurs années que je n'ai pas pu utiliser Linux de façon professionnelle à cause d'applications purement Windows et aussi un peu par facilité. Depuis peu, je n'ai plus à utiliser toutes ces applications je repars donc à la conquête de mon desktop avec une Fedora 33 fraichement installée.</p>
<p>De même que sous Windows, je dois utiliser des VPN Meraki dans le cadre de mon activité professionnelle. Il parait que sous Ubuntu, les VPN Clients Meraki fonctionnent directement, ce qui n'est pas le cas sous Fedora. Nous allons voir pourquoi et comment y remédier.</p>
<p>Les VPN Clients Meraki utilisent le protocole L2TP/IPSec qui n'est pas installé par defaut sur la distribution. La premièr étape est d'installer le plugin L2TP pour NetworkManager</p>
<div class="highlight"><pre><span></span># dnf install network-manager-l2tp-gnome
</pre></div>
<p>L'installation de ce paquet devrait aussi installer la dépendance network-manager-l2tp.</p>
<p>Avant de procéder à la configuration du VPN, il faut désinstaller le paquet libreswan et installer à la place le paquet strongswan. Libreswan ne supporte pas modp1024 (Diffie Hellman Group 2) pour IPSec car ce groupe DH est déprécié pour des raisons de sécurité. Cependant, les VPN Clients Meraki ne supportent que ce groupe DH pour l'établissement de la phase 1 et de la phase 2 d'IPSec. C'est clairement décevant de la part d'une appliance de sécurité mais pour le moment nous n'avons que ça... Strongswan quant à lui supporte toujours le groupe DH2.</p>
<p>Dans Ubuntu, c'est strongswan qui est installé par défaut, alors que Fedora utilise libreswan. C'est ce qui explique que les VPN Client Meraki fonctionnent directement sous Ubuntu, sans manipulations supplémentaires.</p>
<div class="highlight"><pre><span></span># dnf remove libreswan
# dnf install strongswan
</pre></div>
<p>Une fois cette installation effectuée, la configuration d'un VPN L2TP devient possible dans l'interface de gestion du réseau. Pour cela, il suffit de ce rendre dans les paramètres réseau et ajouter le VPN. Avant de valider, quelques modifications sont à faire pour ne pas conserver les paramètres par défaut.</p>
<img alt="Configuration réseau" class="m-image" src="https://blog.devarieux.net/images/F33-MerakiVPN01.png" style="width: 397px" />
<p>En cliquant sur le + pour ajouter un VPN, on arrive sur cette nouvelle fenêtre. Celle ci permet de choisir le type de VPN à monter.</p>
<img alt="Choix du type de VPN" class="m-image" src="https://blog.devarieux.net/images/F33-MerakiVPN02.png" style="width: 320px" />
<p>On choisi le VPN L2TP puis on arrive sur la configuration du VPN</p>
<img alt="Configuration du VPN L2TP" class="m-image" src="https://blog.devarieux.net/images/F33-MerakiVPN03.png" style="width: 320px" />
<p>Ici, on entre le nom du VPN, l'IP publique du MX Meraki ainsi que le nom d'utilisateur et le mot de passe. Une fois que c'est fait, on clique sur <code class="code">IPsec Settings</code>.</p>
<img alt="Configuration IPsec" class="m-image" src="https://blog.devarieux.net/images/F33-MerakiVPN04.png" style="width: 174px" />
<p>On entre sa PSK puis on déplie les paramètres avancés. Là, il faut fixer les algorithmes de chiffrement des phases 1 et 2 IPsec. Pour chacune de ses phases, il faut entrer :</p>
<div class="highlight"><pre><span></span>aes128-sha1-modp1024,3des-sha1-modp1024!
</pre></div>
<p>C'est ce pramètre qui n'est pas accepté par libreswan. Si vous utilisez libreswan avec ces paramètres IPsec, voici le messages d'erreurs qui va apparaitre dans les logs :</p>
<div class="highlight"><pre><span></span>ike string error: IKE DH algorithm 'modp1024' is not supported
</pre></div>
<p>On ne touche à rien d'autre, on valide cette fenêtre puis on clique sur <code class="code">PPP Settings</code>. Sur cette fenêtre, dans les paramètres d'authentification, on décoche tout sauf PAP et on laisse tout le reste par défaut.</p>
<img alt="Configuration PPP" class="m-image" src="https://blog.devarieux.net/images/F33-MerakiVPN05.png" style="width: 170px" />
<p>Une fois ces paramètres validés, on peut tenter de se connecter au VPN. Cela doit fonctionner de suite. Si ça ne marche pas, il y a 2 moyens pour débuguer :</p>
<ul>
<li><code class="code">journalctl -f</code> dans un terminal pendant la tentative de connexion pour voir ce qu'il se passe.</li>
<li>Sur le dashboard Meraki, se rendre dans Network Wide > Event Log pour visualiser ce que voit le MX.</li>
</ul>
Caddy, OVH et les certificats wildcard2021-04-05T08:55:00+02:002021-04-05T08:55:00+02:00Aldevartag:blog.devarieux.net,2021-04-05:/2021/04/caddy-ovh-acme.html<p>Après avoir présenté dans un <a href="/2021/02/caddy-presentation.html">premier article</a> ce qu'est Caddy et son utilisation de façon basique, puis dans <a href="/2021/02/caddy-api.html">un second</a> le pilotage de Caddy par API ainsi qu'une configuration un peu plus avancée, je souhaites ici aborder le sujet de la génération de certificats TLS via Let's Encrypt avec le …</p><p>Après avoir présenté dans un <a href="/2021/02/caddy-presentation.html">premier article</a> ce qu'est Caddy et son utilisation de façon basique, puis dans <a href="/2021/02/caddy-api.html">un second</a> le pilotage de Caddy par API ainsi qu'une configuration un peu plus avancée, je souhaites ici aborder le sujet de la génération de certificats TLS via Let's Encrypt avec le challenge <a href="https://letsencrypt.org/fr/docs/challenge-types/#d%C3%A9fi-dns-01">DNS-01</a>.</p>
<p>Le challenge DNS à l'avantage de pouvoir être utilisé pour générer un certificat DV wildcard. Une fois passé un certain nombre de sous domaines servis par un reverse proxy, il devient intéressant d'utiliser ce type de certificat afin d'éviter de générer trop de requêtes vers les serveurs de Let's Encrypt. De plus, avec un seul certificat à gérer pour l'ensemble des sous domaines, la gestion devient simplifiée, et notamment la supervision ou même le renouvellement.</p>
<p>Caddy intègre de base la gestion de Let's Encrypt pour les challenges HTTP-01 car celui-ci est universel et ne dépend d'aucun autre services. C'est un échange réalisé directement entre le serveur Caddy et les serveurs de Let's Encrypt. Pour le challenge DNS-01, il y a un intermédiaire. Cet intermédiaire est le serveur DNS du domaine pour lequel on souhaite générer un certificat wildcard. De part la multitude de serveurs disponibles et de prestataires fournissant ces services, il est difficile d'avoir un protocole unifié de modification distante des entrées DNS. A ma connaissance, le seul standard qui existe pour cela est la <a href="https://tools.ietf.org/html/rfc2136">RFC 2136</a> qui ne semble pas être implémentée chez la plupart des fournisseurs de services DNS.</p>
<p>Nous allons donc voir comment, avec Caddy, générer un certificat wildcard avec OVH en fournisseur de service DNS. La procédure est assez similaire avec les autres fournisseurs qui ont, je l'espère, pris plus de soin dans la documentation de cette fonctionnalité.</p>
<p>Caddy n'intègre pas, de base, l'ensemble des plugins permettant de résoudre les challenges DNS de tous les fournisseurs. Pour intégrer le bon plugin, il est nécessaire de compiler Caddy. L'opération est particulièrement simple à réaliser et à l'avantage de produire en sortie un binaire unique qu'il est ensuite facile de déployer sur ses serveurs. La compilation de Caddy est assez bien expliquée dans <a href="https://caddyserver.com/docs/build#xcaddy">la documentation</a> et voici la liste des <a href="https://caddyserver.com/docs/modules/">plugins disponible</a>. A ce jour, aucun plugin spécifique n'a été écrit pour OVH, il faut donc se rabattre sur le module <a href="https://github.com/caddy-dns/lego-deprecated">Lego Deprecated</a>. Ce module utilise une ancienne API mais est actuellement le seul qui permet de gérer un grand nombre de fournisseurs de DNS, dont OVH.</p>
<section id="compilation-de-caddy">
<h2>Compilation de Caddy</h2>
<p>Pour compiler Caddy, nous avons besoin de 2 choses. Golang et le binaire xcaddy qui permet de facilement compiler caddy avec les modules spécifiés. On commence donc par installer Golang et déclarer son binaire dans le PATH.</p>
<div class="highlight"><pre><span></span># wget https://golang.org/dl/go<version>.linux-amd64.tar.gz
# tar -C /usr/local -xzf go<version>.linux-amd64.tar.gz
# rm -f go<version>.linux-amd64.tar.gz
</pre></div>
<p>On édite le fichier <code>/etc/profile</code> pour ajouter le binaire go dans le PATH. A la fin du fichier on ajoute :</p>
<div class="highlight"><pre><span></span>export PATH=$PATH:/usr/local/go/bin
</pre></div>
<p>Puis, on source le fichier pour mettre à jour le PATH et on s'assure que go est bien installé en affichant la version (ici 1.16).</p>
<div class="highlight"><pre><span></span># source /etc/profile
# go version
go version go1.16 linux/amd64
</pre></div>
<p>Puis on récupère le binaire xcaddy et on le rend exécutable. Lors de la rédaction cet article, la dernière version disponible est la 0.1.8.</p>
<div class="highlight"><pre><span></span># wget https://github.com/caddyserver/xcaddy/releases/download/v0.1.8/xcaddy_0.1.8_linux_amd64.tar.gz
# tar xvzf xcaddy_0.1.8_linux_amd64.tar.gz
# ls
LICENSE README.md xcaddy xcaddy_0.1.8_linux_amd64.tar.gz
# chmod o+x xcaddy
</pre></div>
<p>Enfin, avec l'aide de xcaddy, on compile caddy avec le plugin lego-deprecated. On se retrouve avec le binaire caddy dans le répertoire.</p>
<div class="highlight"><pre><span></span>./xcaddy build --with github.com/caddy-dns/lego-deprecated
# ls
LICENSE README.md caddy xcaddy xcaddy_0.1.8_linux_amd64.tar.gz
</pre></div>
</section>
<section id="configuration-d-ovh">
<h2>Configuration d'OVH</h2>
<p>Il faut autoriser Caddy à créer et supprimer des entrées DNS sur les serveurs d’OVH. Pour cela, il faut créer une application chez OVH, via ce lien : <a class="m-link-wrap" href="https://eu.api.ovh.com/createApp/">https://eu.api.ovh.com/createApp/</a></p>
<p>On rentre son account ID et mot de passe. On choisit un nom d’application ici <code>xcaddy-dns-challenge</code> ainsi qu’une description. OVH affiche alors l’Application Key et l’Application Secret. On les conserve bien au chaud pour la suite.</p>
<p>Ensuite, il faut donner des droits à cette application. On réalise cela par un call API directement sur la console OVH.</p>
<div class="highlight"><pre><span></span>curl -XPOST -H "X-Ovh-Application: <Application Key>" -H "Content-type: application/json" https://eu.api.ovh.com/1.0/auth/credential -d '{"accessRules":[{"method":"POST","path":"/domain/zone/<Nom De Domaine>/record"},{"method":"POST","path":"/domain/zone/<Nom De Domaine>/refresh"},{"method":"DELETE","path":"/domain/zone/<Nom De Domaine>/record/*"}],"redirection": "https://www.foo.com"}'
</pre></div>
<p>La partie redirection a la fin ne nous intéresse pas mais est obligatoire. Elle indique vers quelle page l’application doit être redirigée une fois connectée.</p>
<p>En retour, on obtient un JSON avec la consumer Key. C’est cette info qu’il faut conserver.</p>
<div class="highlight"><pre><span></span><span class="p">{</span><span class="nt">"validationUrl"</span><span class="p">:</span><span class="s2">"https://eu.api.ovh.com/auth/?credentialToken=xxxxxxxxxxxxxxx"</span><span class="p">,</span><span class="nt">"consumerKey"</span><span class="p">:</span><span class="s2">"<The Consumer Key>"</span><span class="p">,</span><span class="nt">"state"</span><span class="p">:</span><span class="s2">"pendingValidation"</span><span class="p">}</span><span class="w"></span>
</pre></div>
<p>On voit que l'état est “Pending Validation”. Afin de valider, il faut se rendre sur le lien validationUrl.</p>
<p>Sur ce lien, on entre de nouveau ses codes d'accès OVH puis on choisi la durée de validité de l’accès.
On a maintenant toutes les infos dont nous avons besoin :</p>
<ul>
<li>Application Key</li>
<li>Application Secret</li>
<li>Consumer Key</li>
</ul>
</section>
<section id="configuration-de-caddy">
<h2>Configuration de Caddy</h2>
<p>Voyons maintenant comment générer un certificat wildcard pour un domaine puis servir plusieurs sous-domaines en dessous. J'ai mis un peu de temps à trouver la bonne façon de faire, la voici servie pour vous sur un plateau :)
Voici un extrait de mon fichier de configuration, je vais décrire en dessous les différentes sections.</p>
<div class="highlight"><pre><span></span>*.domain.com {
tls {
dns lego_deprecated ovh
}
@backend host backend.domain.com
reverse_proxy @backend 10.0.0.2:3001
@prodapi {
host prod.domain.com
path /api/v1/*
}
@prod {
host prod.domain.com
not path /api/v1/
}
reverse_proxy @prodapi 10.0.0.1:3001
reverse_proxy @prod 10.0.0.1:3000
}
</pre></div>
<p>On déclare d'abord <code>*.domain.com</code> qui est le domaine pour lequel on souhaite que Caddy génère un certificat wildcard. Pour cela, une première section tls avec l'entrée <code>dns lego_deprecated ovh</code> signifie :</p>
<ul>
<li>dns: Résolution du challenge DNS-01</li>
<li>lego_deprecated: Utilisation du module lego_deprecated</li>
<li>ovh: Parmi les providers proposés par lego_deprecated, utiliser OVH.</li>
</ul>
<p>L'entrée <code>@backend host backend.domain.com</code> est un <code>matcher</code>. C'est à dire qu'on place sous le nom <code>backend</code> l'ensemble des requêtes dont le SNI est <code>backend.domain.com</code>. Puis, juste en dessous, l'ensemble des requêtes qui matchent <code>@backend</code> sont reverse proxyfiées (oui, je sais...) vers 10.0.0.2:3001.</p>
<p>Les 2 entrées suivantes sont un peu similaires au matcher <code>@backend</code> mais comme je devais spécifié plusieurs filtres (1 sur le SNI et 1 sur le path), les filtres sont placés dans un bloc d'accolades. Ensuite, les matchers <code>@prodapi</code> et <code>@prod</code> sont également reverse proxyfiés (oui, bon, ça va...) vers leurs serveurs respectifs.</p>
<p>On est prêt à lancer Caddy. Il faut cependant trouver un moyen de lui spécifier les clés et secret OVH pour que le module lego_deprecated puisse se connecter et générer les entrées DNS. Pour cela, plusieurs solutions. La plus simple est d'executer Caddy depuis le terminal avec les variables d'environnement, de cette façon :</p>
<div class="highlight"><pre><span></span>OVH_APPLICATION_KEY=<Application Key> OVH_APPLICATION_SECRET=<Application Secret> OVH_CONSUMER_KEY=<Consumer Key> OVH_ENDPOINT=ovh-eu ./caddy run --config Caddyfile
</pre></div>
<p>C'est bien, ça fonctionne mais c'est pas vraiment production ready. L'autre solution est de placer ces variables d'environnement directement dans le fichier systemd de Caddy. Dans la section <code>[Service]</code> on peut ajouter des variables d'environnement de cette façon :</p>
<div class="highlight"><pre><span></span>[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
Environment='OVH_APPLICATION_KEY=<Application Key>'
Environment='OVH_APPLICATION_SECRET=<Application Secret>'
Environment='OVH_CONSUMER_KEY=<Consumer Key>'
Environment='OVH_ENDPOINT=ovh-eu'
</pre></div>
<p>Normalement, dans les logs, on devrait voir quelque chose comme ça. En tout cas, c'est ce qu'on vise :)</p>
<div class="highlight"><pre><span></span>systemd[1]: Started Caddy.
caddy[575954]: caddy.HomeDir=/var/lib/caddy
caddy[575954]: caddy.AppDataDir=/var/lib/caddy/.local/share/caddy
caddy[575954]: caddy.AppConfigDir=/var/lib/caddy/.config/caddy
caddy[575954]: caddy.ConfigAutosavePath=/var/lib/caddy/.config/caddy/autosave.json
caddy[575954]: caddy.Version=v2.3.0
caddy[575954]: runtime.GOOS=linux
caddy[575954]: runtime.GOARCH=amd64
caddy[575954]: runtime.Compiler=gc
caddy[575954]: runtime.NumCPU=1
caddy[575954]: runtime.GOMAXPROCS=1
caddy[575954]: runtime.Version=go1.16
caddy[575954]: os.Getwd=/
caddy[575954]: LANG=C.UTF-8
caddy[575954]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
caddy[575954]: HOME=/var/lib/caddy
caddy[575954]: LOGNAME=caddy
caddy[575954]: USER=caddy
caddy[575954]: OVH_APPLICATION_KEY=<Application Key>
caddy[575954]: OVH_APPLICATION_SECRET=<Application Secret>
caddy[575954]: OVH_CONSUMER_KEY=<Consumer Key>
caddy[575954]: OVH_ENDPOINT=ovh-eu
caddy[575954]: {"level":"info","ts":1615295347.2837744,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
caddy[575954]: {"level":"info","ts":1615295347.294112,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019",enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
caddy[575954]: {"level":"info","ts":1615295347.2947812,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
caddy[575954]: {"level":"info","ts":1615295347.2949548,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy[575954]: {"level":"info","ts":1615295347.2992623,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["*.domain.com"]}
caddy[575954]: {"level":"info","ts":1615295347.3005319,"msg":"autosaved config","file":"/var/lib/caddy/.config/caddy/autosave.json"}
caddy[575954]: {"level":"info","ts":1615295347.3007138,"msg":"serving initial configuration"}
caddy[575954]: {"level":"info","ts":1615295347.3020074,"logger":"tls.obtain","msg":"acquiring lock","identifier":"*.domain.com"}
caddy[575954]: {"level":"info","ts":1615295347.3032272,"logger":"tls.obtain","msg":"lock acquired","identifier":"*.domain.com"}
caddy[575954]: {"level":"info","ts":1615295347.3185842,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0009a20e0"}
caddy[575954]: {"level":"info","ts":1615295347.3187766,"logger":"tls","msg":"cleaned up storage units"}
caddy[575954]: {"level":"info","ts":1615295348.2573807,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["*.domain.com"]}
caddy[575954]: {"level":"info","ts":1615295348.2576807,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["*.domain.com"]}
caddy[575954]: {"level":"info","ts":1615295348.582178,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"*.domain.com","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
caddy[575954]: {"level":"info","ts":1615295360.2630491,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-v02.api.letsencrypt.org/acme/order/11111/2222222"}
caddy[575954]: {"level":"info","ts":1615295361.126138,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-v02.api.letsencrypt.org/acme/cert/aaaaaaaabbbbbbb"}
caddy[575954]: {"level":"info","ts":1615295361.1281288,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"*.domain.com"}
Mcaddy[575954]: {"level":"info","ts":1615295361.1286106,"logger":"tls.obtain","msg":"releasing lock","identifier":"*.domain.com"}
</pre></div>
<p>Cet article ne fait qu'effleurer les possiblités offerte par Caddy. Comme toujours, je vous invite à vous plonger dans la documentation du logiciel et à parcourir la liste des plugins disponible. Si vous souhaitez voir d'autres fonctionnalités de Caddy détaillées sur ce blog n'hésitez pas à m'en faire part directement.</p>
</section>
L'ingé qui veut des responsabilités2021-03-17T22:30:00+01:002021-03-17T22:30:00+01:00Aldevartag:blog.devarieux.net,2021-03-17:/2021/03/senior.html<p>Cela fait un moment que cet article est dans mes brouillons et que je tente de formuler correctement mes idées. Il est maintenant temps de le publier, un peu sous la forme d'un coup de gueule contre une partie de la profession.</p>
<p>Durant mes quelques années d'expérience et en progressant …</p><p>Cela fait un moment que cet article est dans mes brouillons et que je tente de formuler correctement mes idées. Il est maintenant temps de le publier, un peu sous la forme d'un coup de gueule contre une partie de la profession.</p>
<p>Durant mes quelques années d'expérience et en progressant dans ma carrière, j'ai pu constater une évolution de la façon dont se présentent les problèmes que j'ai à résoudre. A mes débuts, ces problèmes étaient assez simples dans le sens où, même si je rencontrais des difficultés techniques pour les résoudre, la solution était connue et il suffisait de trouver comment procéder à la mise en œuvre. Je parle là des problèmes communs pour un junior, tel que trouver la bonne configuration pour Apache ou Nginx, comment mettre en place VRRP, comment migrer un serveur OpenLDAP, comment gérer le quorum d'un cluster etc.</p>
<p>En prenant plus d'assurance et de responsabilité, en devenant de plus en plus autonome, la définition des problèmes intéressants évolue. L'intérêt n'est plus dans la technique pure, même si cela reste toujours un plaisir (et un moyen pour moi aujourd'hui de retourner de temps en temps dans ma zone de confort). La plupart des problèmes qui méritent d'être résolus sont vagues, mal définis. Ils contiennent plus de questions que de réponses. Souvent, on ne sait même pas s'il existe de bonnes réponses, et encore moins où commencer à chercher pour en trouver. On rencontre ce type de problèmes par exemple lors de design d'architecture (assumer les compromis), de planification des évolutions d'une infrastructure (asusmer les choix et les hypothèses d'évolution), pour ne parler que des aspects ops que je connais.</p>
<p>Le rôle d'ingénieur principal, responsable d'équipe, tech lead, senior etc. est (ou devrait être) attribué à celles et ceux qui gèrent bien cette incertitude et qui parviennent à apporter des solutions à ces problèmes vagues et mals définis. Cela impose aussi d'avoir la capacité à convertir les idées ou les propositions des autres (qu'ils viennent ou pas du milieu technique) en projets ou en tâches, tickets pour les juniors. Plus on accumule d'experience ou plus on monte dans la hiérarchie, moins on est impliqué dans la construction proprement dite.</p>
<p>Au-delà des injonctions de bienveillances, j'estime que beaucoup d'ingénieurs ne sont pas prêts à assumer l'autonomie et la liberté qu'ils demandent. C'est vrai dans les métiers d'ops mais aussi pour les devs. Lorsqu'on s'estime assez bon, assez talentueux ou experimenté pour réclamer l'autonomie de résoudre un problème comme on le souhaite, il faut aussi s'attendre à assumer les responsabilités qui incombent.</p>
<p>Plusieurs fois j'ai pu observer des coéquipiers avec lesquels le dialogue était particulièrement difficile à cause justement de ce manque d'assomption Malheureusement dans l'esprit de ces collaborateurs, le mechant est souvent celui qui le place face à ses errements.</p>
<p>Faire des erreurs fait parti du processus, nous en faisons tous. J'ai cependant beaucoup de mal à tolérer que les erreurs ne soient pas assumées ou pire que la faute soit rejetée sur quelqu'un d'autre. Un ingénieur senior doit comprendre la complexité, appréhender les aléas et les doutes et enfin assumer ses choix.</p>
Utilisation d'un DNS interne avec Umbrella sous Cisco Meraki2021-03-02T22:20:00+01:002021-03-02T22:20:00+01:00Aldevartag:blog.devarieux.net,2021-03-02:/2021/03/meraki-umbrella-and-internal-dns.html<p>Cisco Umbrella (anciennement Open DNS) est un DNS menteur qui permet de se protéger des sites malveillant et notamment des ransomwares. Le service évolue de plus en plus vers une offre SASE complète même si sa fonctionnalité première est la protection DNS.</p>
<p>Les équipements Cisco Meraki peuvent nativement rediriger les …</p><p>Cisco Umbrella (anciennement Open DNS) est un DNS menteur qui permet de se protéger des sites malveillant et notamment des ransomwares. Le service évolue de plus en plus vers une offre SASE complète même si sa fonctionnalité première est la protection DNS.</p>
<p>Les équipements Cisco Meraki peuvent nativement rediriger les requêtes DNS vers Cisco Umbrella. En interceptant les requêtes DNS et en les envoyant vers Umbrella, l'équipement wifi (MR) Meraki forge une réponse DNS renvoyé au client. Que ce passe-t-il lorsqu'une organisation utilise un DNS interne pour la résolution d'un nom de domaine local?</p>
<p>J'ai récemment été confronté à ce scénario et j'ai pu observer différents comportements.</p>
<p>Lorsque le domaine interne est un domaine "bidon", comme par exemple <code class="code">mycompany.local</code>, les requêtes DNS ne sont pas interceptées et le client recoit directement une réponse du serveur local. Aucun problème à ce niveau là. Par contre, lorsque le domaine de base existe, même si l'entreprise utilise un sous domaine dédié, cela créé des comportements aberrants.</p>
<p>Prenons l'exemple d'une entreprise qui dipose du nom de domaine public <code class="code">entreprise.com</code>. Pour ses besoins internes, l'entreprise utilise le sous domaine <code class="code">internal.entreprise.com</code>. La configuration réseau de l'ensemble des postes et des serveurs de l'entreprise spécifie l'utilisation du serveur DNS interne <code class="code">10.0.0.1</code> qui sert spécifiquement ce domaine. Avec cette configuration, l'ensemble des requêtes DNS qui traversent l'équipement Meraki est intercepté et envoyé vers Umbrella. Comme le sous domaine n'existe pas publiqueme, on se retrouve avec une réponse vide ou <code class="code">NXDOMAIN</code> pour domaine non existant.</p>
<p>Personnellement, j'ai mis beaucoup de temps à comprendre ce qui se passait. Je recevais bien une réponse <code class="code">NXDOMAIN</code> mais les captures de paquets m'indiquaient clairement que les requêtes n'arrivaient pas jusqu'au serveur DNS local. Jusqu'à ce que je jette un oeil au Meraki MR.
Afin d'empêcher Umbrella d'intercepter les requêtes DNS pour un domaine spécifique, il suffit de le préciser dans la configuration.
Cela se passe dans Wireless - Firewall & traffic shaping. En choisissant le bon SSID dans le menu déroulant en haut de la page, il possible de définir une liste de domaines dont les requêtes DNS ne seront pas routées vers Cisco Umbrella.</p>
<img alt="Whitelist Meraki Umbrella" class="m-image" src="https://blog.devarieux.net/images/2021-03-02-22_12_36-Meraki-Umbrella.png" style="width: 392px" />
Zabbix et TimescaleDB 2 - Erreur Z30052021-02-23T21:45:00+01:002021-02-23T21:45:00+01:00Aldevartag:blog.devarieux.net,2021-02-23:/2021/02/zabbix-timescaledb2.html<p>Depuis que Zabbix supporte officiellement le plugin PostreSQL TimescaleDB, je n'utilise plus que ce mode d'installation pour les différentes instances que j'ai à déployer.</p>
<p>TimescaleDB est une time serie database et est donc particulièrement adapaté pour stocker des métriques de supervision. Le logiciel se présente comme un plugin à PostgreSQL …</p><p>Depuis que Zabbix supporte officiellement le plugin PostreSQL TimescaleDB, je n'utilise plus que ce mode d'installation pour les différentes instances que j'ai à déployer.</p>
<p>TimescaleDB est une time serie database et est donc particulièrement adapaté pour stocker des métriques de supervision. Le logiciel se présente comme un plugin à PostgreSQL et permet de transformer certaines tables d'une base en mode time series. Le gros avantage est que cela permet de stocker l'ensemble des informations dans un endroit unique, que ce soit la configuration du logiciel (utilisateurs, droits d'accès, paramètres...) et aussi les métriques récupérées par le système de supervision. En plus de cela, timescaleDB propose le partitionnemet automatique des tables ainsi que la compression des données ayant plus de 7 jours.</p>
<p>On a donc d'un coté un gain opérationnel car on n'a plus q'une base de données à gérer et de l'autre un gain en ressources car les tables sont adaptées à ce qu'elles stockent et peuvent être compréssées pour des économies de stockage substantielles.</p>
<p>Lors de ma dernière installation, j'ai pu voir que le plugin TimescaleDB était sorti en version 2. La documentation de Zabbix ne spécifiant pas la version de TimescaleDB à installer, j'ai naturellement installé cette dernière version.</p>
<p>Mal m'en a pris! Cette version 2 n'est pas compatible avec Zabbix 5.2! J'ai pu le voir rapidement lors du démarrage du service <code class="code">zabbix-server</code> avec ces logs que vous n'êtes pas obligé lire en entier. C'est un gros vomi d'erreurs comme on n'aime pas en voir (TL;DR - Plusieurs erreurs Z3005 - query failed - clairement en rapport avec TimescaleDB)</p>
<div class="highlight"><pre><span></span>[Z3005] query failed: [0] PGRES_FATAL_ERROR:ERROR: relation "_timescaledb_config.bgw_policy_compress_chunk s" does not exist
LINE 1: select (p.older_than).integer_interval from _timescaledb_con...
^
[select (p.older_than).integer_interval from _timescaledb_config.bgw_policy_compress_chunks p inner join _timescaledb_catalog.hypertable h on (h.id = p.hypertable_id) where h.table_name='history']
0000000000000 [Z3005] query failed: [0] PGRES_FATAL_ERROR:ERROR: function add_compress_chunks_policy(unknown, integer) does not exist
LINE 1: select add_compress_chunks_policy('history', integer '612000...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
[select add_compress_chunks_policy('history', integer '612000')]
0000000000000 failed to add compression policy to table 'history'
0000000000000 [Z3005] query failed: [0] PGRES_FATAL_ERROR:ERROR: relation "_timescaledb_config.bgw_policy_compress_chunk s" does not exist
LINE 1: select (p.older_than).integer_interval from _timescaledb_con...
^
[select (p.older_than).integer_interval from _timescaledb_config.bgw_policy_compress_chunks p inner join _timescaledb_catalog.hypertable h on (h.id = p.hypertable_id) where h.table_name='history_uint']
0000000000000 [Z3005] query failed: [0] PGRES_FATAL_ERROR:ERROR: function add_compress_chunks_policy(unknown, integer) does not exist
LINE 1: select add_compress_chunks_policy('history_uint', integer '6...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
[select add_compress_chunks_policy('history_uint', integer '612000')]
0000000000000 failed to add compression policy to table 'history_uint'
</pre></div>
<p>Cette erreur provient d'une incompatibilité entre Zabbix 5.2 et TimescaleDB 2. Cette incompatibilité est causée par des modifications de certaines fonctions de l'API de TimescaleDB, entre autre la fonction <a href="https://docs.timescale.com/latest/api#add_compression_policy">add_compression_policy</a>. A partir de là, on a deux solutions.</p>
<ul>
<li>Soit on refait l'installation de TimescaleDB avec la dernière version 1.X.</li>
<li>Soit on tente de corriger ces erreurs.</li>
</ul>
<p>J'ai opté pour la seconde option. En fouillant, j'ai trouvé un <a href="https://support.zabbix.com/projects/ZBX/issues/ZBX-18854">ticket sur le Jira</a> de Zabbix qui aborde ce problème. Dans les échanges, un utilisateur propose une solution avec quelques lignes à envoyer vers la db pour corriger tout ça. Voici comment la mettre en oeuvre.</p>
<p>On commence par se préparer à mettre à jour la base de données</p>
<div class="highlight"><pre><span></span># systemctl stop zabbix-server
# sudo -u postgres psql zabbix
</pre></div>
<p>On peut maintenant envoyer le code SQL suivant :</p>
<div class="highlight"><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">TYPE</span><span class="w"> </span><span class="n">_timescaledb_catalog</span><span class="p">.</span><span class="n">ts_interval</span><span class="w"> </span><span class="k">AS</span><span class="w"></span>
<span class="p">(</span><span class="n">is_time_interval</span><span class="w"> </span><span class="nb">BOOLEAN</span><span class="p">,</span><span class="w"> </span><span class="n">time_interval</span><span class="w"> </span><span class="nb">INTERVAL</span><span class="p">,</span><span class="w"> </span><span class="n">integer_interval</span><span class="w"> </span><span class="nb">BIGINT</span><span class="p">);</span><span class="w"></span>
<span class="k">ALTER</span><span class="w"> </span><span class="k">TYPE</span><span class="w"> </span><span class="n">_timescaledb_catalog</span><span class="p">.</span><span class="n">ts_interval</span><span class="w"> </span><span class="k">OWNER</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">zabbix</span><span class="p">;</span><span class="w"></span>
<span class="k">CREATE</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="k">REPLACE</span><span class="w"> </span><span class="k">VIEW</span><span class="w"> </span><span class="n">_timescaledb_config</span><span class="p">.</span><span class="n">bgw_policy_compress_chunks</span><span class="w"> </span><span class="k">AS</span><span class="w"></span>
<span class="k">SELECT</span><span class="w"> </span><span class="n">job_id</span><span class="p">,(</span><span class="n">config</span><span class="o">->></span><span class="s1">'hypertable_id'</span><span class="p">)::</span><span class="nb">INTEGER</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">hypertable_id</span><span class="p">,</span><span class="w"></span>
<span class="p">(</span><span class="k">FALSE</span><span class="p">,</span><span class="k">NULL</span><span class="p">,</span><span class="n">config</span><span class="o">->></span><span class="s1">'compress_after'</span><span class="p">)::</span><span class="n">_timescaledb_catalog</span><span class="p">.</span><span class="n">ts_interval</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">older_than</span><span class="w"></span>
<span class="k">FROM</span><span class="w"> </span><span class="n">timescaledb_information</span><span class="p">.</span><span class="n">jobs</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">proc_name</span><span class="o">=</span><span class="s1">'policy_compression'</span><span class="p">;</span><span class="w"></span>
<span class="k">ALTER</span><span class="w"> </span><span class="k">VIEW</span><span class="w"> </span><span class="n">_timescaledb_config</span><span class="p">.</span><span class="n">bgw_policy_compress_chunks</span><span class="w"> </span><span class="k">OWNER</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">zabbix</span><span class="p">;</span><span class="w"></span>
<span class="k">CREATE</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="k">REPLACE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">add_compress_chunks_policy</span><span class="w"></span>
<span class="p">(</span><span class="n">hypertable</span><span class="w"> </span><span class="n">regclass</span><span class="p">,</span><span class="n">older_than</span><span class="w"> </span><span class="n">anyelement</span><span class="p">,</span><span class="n">if_not_exists</span><span class="w"> </span><span class="nb">BOOLEAN</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">FALSE</span><span class="p">)</span><span class="w"></span>
<span class="k">RETURNS</span><span class="w"> </span><span class="nb">INTEGER</span><span class="w"> </span><span class="k">LANGUAGE</span><span class="w"> </span><span class="k">sql</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="err">$$</span><span class="w"></span>
<span class="k">SELECT</span><span class="w"> </span><span class="n">add_compression_policy</span><span class="p">(</span><span class="n">hypertable</span><span class="p">,</span><span class="n">older_than</span><span class="p">,</span><span class="n">if_not_exists</span><span class="p">)</span><span class="w"></span>
<span class="err">$$</span><span class="p">;</span><span class="w"></span>
<span class="k">ALTER</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">add_compress_chunks_policy</span><span class="w"> </span><span class="k">OWNER</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">zabbix</span><span class="p">;</span><span class="w"></span>
<span class="k">CREATE</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="k">REPLACE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">drop_chunks</span><span class="w"></span>
<span class="p">(</span><span class="n">older_than</span><span class="w"> </span><span class="n">anyelement</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">::</span><span class="k">UNKNOWN</span><span class="p">,</span><span class="k">table_name</span><span class="w"> </span><span class="n">NAME</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">::</span><span class="n">NAME</span><span class="p">)</span><span class="w"></span>
<span class="k">RETURNS</span><span class="w"> </span><span class="k">SETOF</span><span class="w"> </span><span class="nb">TEXT</span><span class="w"> </span><span class="k">LANGUAGE</span><span class="w"> </span><span class="k">sql</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="err">$$</span><span class="w"></span>
<span class="k">SELECT</span><span class="w"> </span><span class="n">drop_chunks</span><span class="p">(</span><span class="k">table_name</span><span class="p">::</span><span class="n">regclass</span><span class="p">,</span><span class="n">older_than</span><span class="p">,</span><span class="k">NULL</span><span class="p">,</span><span class="k">FALSE</span><span class="p">)</span><span class="w"></span>
<span class="err">$$</span><span class="p">;</span><span class="w"></span>
<span class="k">ALTER</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">drop_chunks</span><span class="p">(</span><span class="n">anyelement</span><span class="p">,</span><span class="n">NAME</span><span class="p">)</span><span class="w"> </span><span class="k">OWNER</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">zabbix</span><span class="p">;</span><span class="w"></span>
</pre></div>
<p>On peut maintenant redémarrer le service zabbix-server (<code class="code">systemctl start zabbix-server</code>) et on voit dans les logs que les erreurs ont disparu.
Zabbix devrait rapidement corriger cela, dans un premier temps en mettant à jour la documentation et dans un second temps en adaptant l'application.</p>
Pilotage de Caddy par API2021-02-21T00:23:00+01:002021-02-21T00:23:00+01:00Aldevartag:blog.devarieux.net,2021-02-21:/2021/02/caddy-api.html<p>Comme promis dans l'article précédent sur Caddy, je vais parler de l'utilisation de l'API de Caddy. Un prochain article décrira comment générer un certificat wildcard pour un domaine hébergé chez OVH.</p>
<p>En plus de permettre de lire la configuration, l'API de Caddy permet aussi d'en pousser une nouvelle, en totalité …</p><p>Comme promis dans l'article précédent sur Caddy, je vais parler de l'utilisation de l'API de Caddy. Un prochain article décrira comment générer un certificat wildcard pour un domaine hébergé chez OVH.</p>
<p>En plus de permettre de lire la configuration, l'API de Caddy permet aussi d'en pousser une nouvelle, en totalité ou en partie. L'avantage est que, si la configuration envoyée est valide, celle ci est chargée à chaud et sinon un code retour autre que 200 est renvoyé, précisant l'erreur rencontrée.</p>
<p>Attention au mode d'execution du service Caddy lorsqu'on commence à le configurer par API. Il est nécessaire d'utiliser le fichier de service décrit <a href="https://caddyserver.com/docs/install#linux-service">dans la documentation</a>. Sans cela, les modifications apportées seront perdues au prochain redémarrage du service.</p>
<p>L'API est disponible par defaut seulement sur la boucle locale, port 2019. On peut déjà commencer par visualiser la configuration avant de commencer à en pousser une nouvelle.</p>
<div class="highlight"><pre><span></span>curl http://localhost:2019/config/ | python3 -m json.tool
</pre></div>
<p>Le pipe vers la commande python permet d'obtenir directement un affichage json en mode pretty print.</p>
<section id="pousser-une-configuration-complete">
<h2>Pousser une configuration complète</h2>
<p>La configuration à envoyer vers Caddy est préparée dans un fichier, qu'on va appeler <code class="code">config.json</code>. Ce fichier sera ensuite envoyé en tant que payload dans l'appel API.</p>
<p>Première configuration simple avec un reverse proxy.</p>
<div class="highlight"><pre><span></span><span class="p">{</span><span class="w"></span>
<span class="nt">"apps"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"http"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"servers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"srv0"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"listen"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">":443"</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">"routes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"handle"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"handler"</span><span class="p">:</span><span class="w"> </span><span class="s2">"reverse_proxy"</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">"upstreams"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"dial"</span><span class="p">:</span><span class="w"> </span><span class="s2">"10.0.0.1:80"</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
<p>Avec cette configuration, on a la génération du certificat TLS via Let's Encrypt ainsi que la redirection HTTP vers HTTPS. On pousse cette configuration avec la commande suivante :</p>
<div class="highlight"><pre><span></span>curl 127.0.0.1:2019/load -X POST -H "Content-Type: application/json" -d @config.json
</pre></div>
<p>Passons maintenant à l'étape suivante. Nous allons ajouter plusieurs éléments de configuration</p>
<div class="highlight"><pre><span></span><span class="p">{</span><span class="w"></span>
<span class="nt">"admin"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"listen"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1:2019"</span><span class="w"></span>
<span class="p">},</span><span class="w"></span>
<span class="nt">"apps"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"http"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"servers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"srv0"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"listen"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">":443"</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">"routes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"handle"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"handler"</span><span class="p">:</span><span class="w"> </span><span class="s2">"reverse_proxy"</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">"transport"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"protocol"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http"</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">"tls"</span><span class="p">:</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">"upstreams"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"dial"</span><span class="p">:</span><span class="w"> </span><span class="s2">"10.0.0.1:443"</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">"match"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"host"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">"sub.domain.com"</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">"tls_connection_policies"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"certificate_selection"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"any_tag"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">"companycert"</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">"tls"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"certificates"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"load_files"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">"certificate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/etc/pki/tls/certs/companycert.crt"</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/etc/pki/tls/private/companycert.key"</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">"tags"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">"companycert"</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
<p>Qu'avons nous exactement?
Premièrement, nous créons une route qui utilise un handle. Un handle est un processus de Caddy qui permet d'activer certaines fonctionnalités spécifiques. Ici nous utilisons le handle <code class="code">reverse_proxy</code> mais il y en a <a href="https://caddyserver.com/docs/json/apps/http/servers/routes/handle/">bien d'autres</a>.</p>
<p>Ensuite, avec la directive <code class="code">"upstream" "dial"</code>, on spécifie le serveur de backend à utiliser. En précisant <code class="code">:443</code>, on force le reverse proxy à se connecter au backend en HTTPS.</p>
<p>Puis la directive <code class="code">"match" "host"</code> permet de répondre aux requêtes destinées à <code class="code">sub.domain.com</code>.</p>
<p>On termine enfin avec la configuration TLS. D'une part, on indique la politique TLS du serveur "srv0". La possibilitée d'utiliser des tags est assez pratique pour ne pas avoir à répéter les chemins des certificats lorsqu'on utilise plusieurs éléments "server" dans la même configuration. Il est même possible de spécifier plusieurs tags, correspondant à plusieurs certificats. Caddy choisira le certificat le plus adapté au SNI de destination.</p>
<p>De la même façon, on pousse la configuration complète vers Caddy.</p>
<div class="highlight"><pre><span></span>curl 127.0.0.1:2019/load -X POST -H "Content-Type: application/json" -d @config.json
</pre></div>
</section>
<section id="mettre-a-jour-une-partie-de-la-configuration">
<h2>Mettre à jour une partie de la configuration</h2>
<p>Pour mettre à jour ou remplacer une partie de la configuration, on va utiliser le chemin JSON qu'on souhaite mettre à jour et changer de verbe HTTP.</p>
<dl>
<dt>POST /config/[chemin]</dt>
<dd>Configure ou remplace un objet. Si l'objet est une liste, l'élément est ajouté à la liste.</dd>
</dl>
<p>Voici par exemple comment ajouter l'écoute sur le port 80, ce qui désactive la redirection automatique de HTTP vers HTTPS</p>
<div class="highlight"><pre><span></span>curl -X POST -H "Content-Type: application/json" -d '":80"' "http://127.0.0.1:2019/config/apps/http/servers/srv0/listen"
</pre></div>
<dl>
<dt>PUT /config/[chemin]</dt>
<dd>Créé un nouvel objet. Insert dans un liste</dd>
</dl>
<p>Pour continuer sur l'exemple du port d'écoute, on peut ajouter le port d'écoute 80 de cette façon :</p>
<div class="highlight"><pre><span></span>curl -X PUT -H "Content-Type: application/json" -d '":80"' "http://127.0.0.1:2019/config/apps/http/servers/srv0/listen/0"
</pre></div>
<dl>
<dt>PATCH /config/[chemin]</dt>
<dd>Remplace un objet ou une liste</dd>
</dl>
<p>Dison qu'on souhaite remettre en place la redirection du port 80 vers 443. Cela est automatique lorsqu'on demande à Caddy d'écouter seulement sur le port 443. Cette commande va remplacer la liste <code class="code">[":80", ":443"]</code> par simplement <code class="code">[":443"]</code>.</p>
<div class="highlight"><pre><span></span>curl -X PATCH -H "Content-Type: application/json" -d '":443"' "http://127.0.0.1:2019/config/apps/http/servers/srv0/listen/"
</pre></div>
<p>Voilà pour un tour rapide de l'utilisation de l'API de Caddy. Dans un prochain article j'expliquerai comment compiler Caddy avec des plugins et comment générer un certificat wildcard pour un domaine hébergé chez OVH, en remplissant le challenge DNS proposé par Let's Encrypt.</p>
</section>
Présentation de Caddy2021-02-19T06:55:00+01:002021-02-19T06:55:00+01:00Aldevartag:blog.devarieux.net,2021-02-19:/2021/02/caddy-presentation.html<p>Dans un tweet récent, j'expliquais voir trop peu de publications d'articles sur le serveur web / reverse proxy <a href="https://caddyserver.com/">Caddy</a>. Je pense que Caddy gagne a être connu, voici donc un premier article de présentation.</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="fr" dir="ltr">Je vois pas mal de partage d'articles sur Traefik dans mon fil Twitter. J'aime beaucoup …</p></blockquote><p>Dans un tweet récent, j'expliquais voir trop peu de publications d'articles sur le serveur web / reverse proxy <a href="https://caddyserver.com/">Caddy</a>. Je pense que Caddy gagne a être connu, voici donc un premier article de présentation.</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="fr" dir="ltr">Je vois pas mal de partage d'articles sur Traefik dans mon fil Twitter. J'aime beaucoup Traefik mais je lui préfère <a href="https://twitter.com/caddyserver?ref_src=twsrc%5Etfw">@caddyserver</a>.<br>Je profite donc de la reprise des activités sur mon blog pour vous préparer quelques articles sur Caddy et l'utilisation de son API.</p>— Alain Devarieux (@landvarx) <a href="https://twitter.com/landvarx/status/1362078709436592130?ref_src=twsrc%5Etfw">February 17, 2021</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><p>Caddy est un serveur web, de même que Apache ou Nginx. Il dispose également d'une fonctionnalité de reverse proxy et utilise des options de sécurités avancées par défaut (HTTPS par défaut avec Let's Encrypt ou ZeroSSL, TLS 1.3, OCSP Stapling, Cipher Suite modernes). Le logiciel est écrit en Go.
En plus de ces fonctionnalités de sécurités, Caddy est multiplateforme, il fonctionne avec un seul binaire, supporte les plugins et supporte plusieurs types de challenges ACME.</p>
<p>Je ne vais pas revenir sur son installation, parfaitement décrite dans <a href="https://caddyserver.com/docs/install">la documentation</a>.</p>
<section id="configuration">
<h2>Configuration</h2>
<p>Caddy peut se configurer de deux manières. Via le fichier de configuration, appelé <code class="code">Caddyfile</code> ou via son API avec un payload JSON. L'utilisation de l'API sera décrite dans un prochain article.
J'utilise Caddy principalement pour ses fonctionnalités de reverse proxy. Voyons donc quelques exemples de configuration de Caddy via le Caddyfile.</p>
<div class="highlight"><pre><span></span>sub.domain.com {
reverse_proxy 10.0.0.1:8000
log {
output file /var/log/caddy/sub.domain.com_access.log
}
}
</pre></div>
<p>Bien, avec ça, nous avons un reverse proxy qui écoute sur le port 80 et 443, avec redirection automatique HTTP vers HTTPS. Les logs seront renvoyés vers un fichier. Avec cette configuration, le certificat Let's Encrypt est généré (si le DNS est bien configuré et que Caddy est accessible depuis l'exterieur) et seuls les protocoles TLS 1.2 et 1.3 sont supportés. Niveau sécurité, on est pas mal.</p>
<p>De la même façon, le header <code class="code">X-Forwarded-For</code> est automatiquement intégré dans l'entête HTTP envoyé au serveur de backend. Cette intégration permet de gagner quelques lignes de configuration.
Voyons maintenant comment gérer l'utilisation de deux backends différents pour des URI différentes.</p>
<div class="highlight"><pre><span></span>sub.domain.com {
reverse_proxy /api/v1/* 10.0.0.2:4000
reverse_proxy / 10.0.0.1:3000
log {
output file /var/log/caddy/sub.domain.com_access.log {
roll_size 10MiB
roll_keep 10
}
}
}
</pre></div>
<p>Là encore, c'est assez simple. On traite d'abord les requêtes vers <code class="code">/api/v1</code> qui sont envoyées vers un premier backend et le reste des requêtes est envoyé vers <code class="code">10.0.0.1</code>. J'en ai profité pour ajouter une rotation des logs.</p>
<p>Tout cela fonctionne bien quand on a un site disponible publiquement et pour lequel Caddy peut générer un certificat Let's Encrypt. Voyons maintenant comment intégrer son propre certificat (autosigné ou non). Pour cet exemple, je m'appuie sur une configuration de Caddy pour servir un serveur Graylog</p>
<div class="highlight"><pre><span></span>logs.domain.com {
reverse_proxy 127.0.0.1:9000
header X-Graylog-Server-URL https://logs.domain.com/
tls /etc/pki/tls/certs/companycert.crt /etc/pki/tls/private/companycert.key
log {
output file /var/log/caddy/graylog.log {
roll_size 10MiB
roll_keep 10
}
}
}
</pre></div>
<p>L'option <code class="code">tls</code> permet de passer directement le certificat puis la clé privée du certificat. L'ajout d'un header se fait de façon assez simple ici aussi.</p>
<p>Enfin, comment faire lorsqu'on souhaite servir son site en plain HTTP, sans TLS. L'option est assez simple et plutot ingénieuse. Il suffit de forcer le site en HTTP dans l'URL.</p>
<div class="highlight"><pre><span></span>http://sub.domain.com {
reverse_proxy 10.0.0.1:8000
log {
output file /var/log/caddy/sub.domain.com_access.log
}
}
</pre></div>
<p>Avec cette configuration, Caddy ne va pas tenter de générer le certificat Let's Encrypt ni proposer de redirection HTTP vers HTTPS.</p>
<p>Dans le prochain article nous verrons comment utiliser l'API de Caddy en lecture et en écriture totale ou partielle de configuration.</p>
</section>
VPN Meraki et Windows 102021-02-17T21:47:00+01:002021-02-17T21:47:00+01:00Aldevartag:blog.devarieux.net,2021-02-17:/2021/02/vpn-meraki-win10.html<p>Un des avantages du VPN Meraki est qu'il ne nécessite pas de client de spécifique pour Windows. Le problème principal est que sa configuration nécessite quelques manipulations. Beaucoup de nos prestatiares rencontrent des difficultés pour s'y connecter et nous remontent régulièrement qu'ils ont des échecs de connexions avec le code …</p><p>Un des avantages du VPN Meraki est qu'il ne nécessite pas de client de spécifique pour Windows. Le problème principal est que sa configuration nécessite quelques manipulations. Beaucoup de nos prestatiares rencontrent des difficultés pour s'y connecter et nous remontent régulièrement qu'ils ont des échecs de connexions avec le code erreur 628, ou encore le message "The connection was terminated by the remote computer before it could be completed.".
Voici donc comment configurer un VPN Meraki sous Windows 10. Avec en bonus, la configuration de la base de registre en cas d'erreur 809 qui apparait lorsque le client VPN se trouve derrière du NAT.</p>
<section id="configuration-du-client-vpn-l2tp">
<h2>Configuration du client VPN L2TP</h2>
<p>Dans les paramètres VPN de Windows 10, ajouter un nouveau VPN et y entrer les informations de connexion. Jusque là, rien de bien compliqué.</p>
<img alt="Windows 10 - Add VPN" class="m-image" src="https://blog.devarieux.net/images/Meraki_VPN_WIN10_Settings.png" style="width: 254px" />
<p>Ensuite, il faut se rendre dans les options d'adaptateurs (Change adapter options). Cela ouvre le Control Panel. Clique droit sur la connexion VPN concernée puis Propriété. Ici, dans l'onglet Securité, dans le second menu déroulant, il faut sélectionner "Require Encryption (Disconnect if server decline)".
Puis, dans le partie Authentication, il faut cocher Allow these protocols puis 'Unencrypted password (PAP). Cette option n'envoie pas le mot de passe en clair sur le réseau. Celui ci transit par un canal chiffré entre le poste client et le MX Meraki.</p>
<img alt="Windows 10 - VPN Properties" class="m-image" src="https://blog.devarieux.net/images/Meraki_VPN_Win10_Properties01.png" style="width: 239px" />
<p>Ensuite, il faut cliquer sur le bouton 'Advanced Settings' et entrer la PSK dans la fenêtre qui s'ouvre.
On peut enfin valider le tout et se connecter au VPN. Si cela ne fonctionne pas, il est possible que ce soit une option de Windows dans la base de registre qui empêche la communication a travers les réseaux natés. Pour corriger cela, il faut ouvrir la base de registre en mode administrateur puis créer cette clé :</p>
<pre class="code">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PolicyAgent
Nom : AssumeUDPEncapsulationContextOnSendRule
Type: DWORD
Valeur: 2
Base: Decimal</pre>
<p>Après un reboot, la connexion devrait fonctionner.</p>
</section>
Migrer des règles de NAT VyOS vers NSX-V2021-02-10T09:22:00+01:002021-02-10T09:22:00+01:00Aldevartag:blog.devarieux.net,2021-02-10:/2021/02/migrate-nat-vyos-nsxv.html<p>Il y a quelques temps, j'ai procédé une modification majeure de l'architecture BGP d'un hébergeur. Cette modification imposait de transposer les règles de NAT présentent sur les routeurs BGP VyOS vers les routeurs NSX-V, plus proche du coeur de réseau.
Il y avait environ 400 règles de NAT à transposer …</p><p>Il y a quelques temps, j'ai procédé une modification majeure de l'architecture BGP d'un hébergeur. Cette modification imposait de transposer les règles de NAT présentent sur les routeurs BGP VyOS vers les routeurs NSX-V, plus proche du coeur de réseau.
Il y avait environ 400 règles de NAT à transposer. Ceux qui ont déjà fait du NAT sur NSX savent que réaliser ce genre de manipulation manuellement n'est pas une sinécure. L'interface n'est clairement pas adaptée pour ce genre de tâche. Par contre, NSX dispose d'une API plutot bien documentée.
De l'autre coté, VyOS. VyOS est un système d'exploitation réseau, basé sur Debian avec des commandes similaires à ce qu'on peut trouver sur un routeur.</p>
<p>En discutant avec <a href="https://baturin.org/">Daniil Baturin</a>, principal mainteneur de VyOS, sur la meilleur façon de procéder, celui ci m'a indiqué la <a href="https://github.com/vyos/vyos-1x/blob/current/python/vyos/configtree.py">lib configtree</a> qui permet de manipuler un fichier de configuration VyOS. Avec l'aide de cette lib, j'ai pu écrire ce script Python qui lit le fichier vyos.conf préalablement récupéré par mes soins et génére puis pousse les règles de NAT vers NSX-V.</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal"> 10</span>
<span class="normal"> 11</span>
<span class="normal"> 12</span>
<span class="normal"> 13</span>
<span class="normal"> 14</span>
<span class="normal"> 15</span>
<span class="normal"> 16</span>
<span class="normal"> 17</span>
<span class="normal"> 18</span>
<span class="normal"> 19</span>
<span class="normal"> 20</span>
<span class="normal"> 21</span>
<span class="normal"> 22</span>
<span class="normal"> 23</span>
<span class="normal"> 24</span>
<span class="normal"> 25</span>
<span class="normal"> 26</span>
<span class="normal"> 27</span>
<span class="normal"> 28</span>
<span class="normal"> 29</span>
<span class="normal"> 30</span>
<span class="normal"> 31</span>
<span class="normal"> 32</span>
<span class="normal"> 33</span>
<span class="normal"> 34</span>
<span class="normal"> 35</span>
<span class="normal"> 36</span>
<span class="normal"> 37</span>
<span class="normal"> 38</span>
<span class="normal"> 39</span>
<span class="normal"> 40</span>
<span class="normal"> 41</span>
<span class="normal"> 42</span>
<span class="normal"> 43</span>
<span class="normal"> 44</span>
<span class="normal"> 45</span>
<span class="normal"> 46</span>
<span class="normal"> 47</span>
<span class="normal"> 48</span>
<span class="normal"> 49</span>
<span class="normal"> 50</span>
<span class="normal"> 51</span>
<span class="normal"> 52</span>
<span class="normal"> 53</span>
<span class="normal"> 54</span>
<span class="normal"> 55</span>
<span class="normal"> 56</span>
<span class="normal"> 57</span>
<span class="normal"> 58</span>
<span class="normal"> 59</span>
<span class="normal"> 60</span>
<span class="normal"> 61</span>
<span class="normal"> 62</span>
<span class="normal"> 63</span>
<span class="normal"> 64</span>
<span class="normal"> 65</span>
<span class="normal"> 66</span>
<span class="normal"> 67</span>
<span class="normal"> 68</span>
<span class="normal"> 69</span>
<span class="normal"> 70</span>
<span class="normal"> 71</span>
<span class="normal"> 72</span>
<span class="normal"> 73</span>
<span class="normal"> 74</span>
<span class="normal"> 75</span>
<span class="normal"> 76</span>
<span class="normal"> 77</span>
<span class="normal"> 78</span>
<span class="normal"> 79</span>
<span class="normal"> 80</span>
<span class="normal"> 81</span>
<span class="normal"> 82</span>
<span class="normal"> 83</span>
<span class="normal"> 84</span>
<span class="normal"> 85</span>
<span class="normal"> 86</span>
<span class="normal"> 87</span>
<span class="normal"> 88</span>
<span class="normal"> 89</span>
<span class="normal"> 90</span>
<span class="normal"> 91</span>
<span class="normal"> 92</span>
<span class="normal"> 93</span>
<span class="normal"> 94</span>
<span class="normal"> 95</span>
<span class="normal"> 96</span>
<span class="normal"> 97</span>
<span class="normal"> 98</span>
<span class="normal"> 99</span>
<span class="normal">100</span>
<span class="normal">101</span>
<span class="normal">102</span>
<span class="normal">103</span>
<span class="normal">104</span>
<span class="normal">105</span>
<span class="normal">106</span>
<span class="normal">107</span>
<span class="normal">108</span>
<span class="normal">109</span>
<span class="normal">110</span>
<span class="normal">111</span>
<span class="normal">112</span>
<span class="normal">113</span>
<span class="normal">114</span>
<span class="normal">115</span>
<span class="normal">116</span>
<span class="normal">117</span>
<span class="normal">118</span>
<span class="normal">119</span>
<span class="normal">120</span>
<span class="normal">121</span>
<span class="normal">122</span>
<span class="normal">123</span>
<span class="normal">124</span>
<span class="normal">125</span>
<span class="normal">126</span>
<span class="normal">127</span>
<span class="normal">128</span>
<span class="normal">129</span>
<span class="normal">130</span>
<span class="normal">131</span>
<span class="normal">132</span>
<span class="normal">133</span>
<span class="normal">134</span>
<span class="normal">135</span>
<span class="normal">136</span>
<span class="normal">137</span>
<span class="normal">138</span>
<span class="normal">139</span>
<span class="normal">140</span>
<span class="normal">141</span>
<span class="normal">142</span>
<span class="normal">143</span>
<span class="normal">144</span>
<span class="normal">145</span>
<span class="normal">146</span>
<span class="normal">147</span>
<span class="normal">148</span>
<span class="normal">149</span>
<span class="normal">150</span>
<span class="normal">151</span>
<span class="normal">152</span>
<span class="normal">153</span>
<span class="normal">154</span>
<span class="normal">155</span>
<span class="normal">156</span>
<span class="normal">157</span>
<span class="normal">158</span>
<span class="normal">159</span>
<span class="normal">160</span>
<span class="normal">161</span>
<span class="normal">162</span>
<span class="normal">163</span>
<span class="normal">164</span>
<span class="normal">165</span>
<span class="normal">166</span>
<span class="normal">167</span>
<span class="normal">168</span>
<span class="normal">169</span>
<span class="normal">170</span>
<span class="normal">171</span>
<span class="normal">172</span>
<span class="normal">173</span>
<span class="normal">174</span>
<span class="normal">175</span>
<span class="normal">176</span>
<span class="normal">177</span>
<span class="normal">178</span>
<span class="normal">179</span>
<span class="normal">180</span>
<span class="normal">181</span>
<span class="normal">182</span>
<span class="normal">183</span>
<span class="normal">184</span>
<span class="normal">185</span>
<span class="normal">186</span>
<span class="normal">187</span>
<span class="normal">188</span>
<span class="normal">189</span>
<span class="normal">190</span>
<span class="normal">191</span>
<span class="normal">192</span>
<span class="normal">193</span></pre></div></td><td class="code"><div><pre><span></span> <span class="kn">import</span> <span class="nn">vyos.configtree</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">from</span> <span class="nn">requests.auth</span> <span class="kn">import</span> <span class="n">HTTPBasicAuth</span>
<span class="c1"># Set variables for edg_id and nsxmanager</span>
<span class="n">edge_id</span> <span class="o">=</span> <span class="s1">'edge-XXX'</span>
<span class="n">nsx_manager</span> <span class="o">=</span> <span class="s1">'nsxmanager.localdomain'</span>
<span class="k">def</span> <span class="nf">get_nat_dest_rule</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="sd">'''</span>
<span class="sd"> From VyOS config section "nat destination rule X"</span>
<span class="sd"> Return the DNAT rule X as dict</span>
<span class="sd"> '''</span>
<span class="n">rule</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"dstaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"source"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"srcaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"source"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"inbound-interface"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"inbound-interface"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"inbound-interface"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"log"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"log"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"log"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"protocol"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"protocol"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"protocol"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"description"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"description"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"description"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"translation"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"translateaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"translation"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">return</span> <span class="n">rule</span>
<span class="k">def</span> <span class="nf">get_nat_source_rule</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="sd">'''</span>
<span class="sd"> From VyOS config section "nat source rule X"</span>
<span class="sd"> Return the SNAT rule X as dict</span>
<span class="sd"> '''</span>
<span class="n">rule</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"source"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"srcaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"source"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"dstaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"outbound-interface"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"outbound-interface"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"outbound-interface"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"log"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"log"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"log"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"protocol"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"protocol"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"protocol"</span><span class="p">])</span>
<span class="k">if</span> <span class="n">config</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"translation"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">]):</span>
<span class="n">rule</span><span class="p">[</span><span class="s2">"translateaddr"</span><span class="p">]</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">return_value</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="s2">"translation"</span><span class="p">,</span> <span class="s2">"address"</span><span class="p">])</span>
<span class="k">return</span> <span class="n">rule</span>
<span class="k">def</span> <span class="nf">create_dstnat_payload</span><span class="p">(</span><span class="n">natdst</span><span class="p">):</span>
<span class="sd">'''</span>
<span class="sd"> From all VyOS DNAT rules, create a XML payload that can be sent to NSX</span>
<span class="sd"> '''</span>
<span class="n">start_payload</span> <span class="o">=</span> <span class="s2">"<natRules>"</span>
<span class="n">end_payload</span> <span class="o">=</span> <span class="s2">"</natRules>"</span>
<span class="n">mid_payload</span> <span class="o">=</span> <span class="s2">""</span>
<span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">natdst</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="s2">"<natRule><action>dnat</action></span><span class="se">\</span>
<span class="s2"> <originalAddress></span><span class="si">{0}</span><span class="s2"></originalAddress></span><span class="se">\</span>
<span class="s2"> <translatedAddress></span><span class="si">{1}</span><span class="s2"></translatedAddress></span><span class="se">\</span>
<span class="s2"> <loggingEnabled>false</loggingEnabled></span><span class="se">\</span>
<span class="s2"> <enabled>true</enabled></span><span class="se">\</span>
<span class="s2"> <originalPort>any</originalPort></span><span class="se">\</span>
<span class="s2"> <translatedPort>any</translatedPort>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'dstaddr'</span><span class="p">],</span> <span class="n">rule</span><span class="p">[</span><span class="s1">'translateaddr'</span><span class="p">])</span>
<span class="k">if</span> <span class="s2">"description"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="n">descr_payload</span> <span class="o">=</span> <span class="s2">"<description></span><span class="si">{0}</span><span class="s2"></description>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'description'</span><span class="p">])</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">descr_payload</span>
<span class="k">if</span> <span class="s2">"protocol"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="k">if</span> <span class="n">rule</span><span class="p">[</span><span class="s1">'protocol'</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"all"</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol>any</protocol>"</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol></span><span class="si">{0}</span><span class="s2"></protocol>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'protocol'</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol>any</protocol>"</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">proto_payload</span>
<span class="k">if</span> <span class="s2">"srcaddr"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="n">src_payload</span> <span class="o">=</span> <span class="s2">"<dnatMatchSourceAddress></span><span class="si">{0}</span><span class="s2"></dnatMatchSourceAddress>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'srcaddr'</span><span class="p">])</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">src_payload</span>
<span class="n">mid_payload</span> <span class="o">=</span> <span class="n">mid_payload</span> <span class="o">+</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="s2">"</natRule>"</span>
<span class="n">payload</span> <span class="o">=</span> <span class="n">start_payload</span> <span class="o">+</span> <span class="n">mid_payload</span> <span class="o">+</span> <span class="n">end_payload</span>
<span class="k">return</span> <span class="n">payload</span>
<span class="k">def</span> <span class="nf">create_srcnat_payload</span><span class="p">(</span><span class="n">natsrc</span><span class="p">):</span>
<span class="sd">'''</span>
<span class="sd"> From all VyOS SNAT rules, create a XML payload that can be sent to NSX</span>
<span class="sd"> '''</span>
<span class="n">start_payload</span> <span class="o">=</span> <span class="s2">"<natRules>"</span>
<span class="n">end_payload</span> <span class="o">=</span> <span class="s2">"</natRules>"</span>
<span class="n">mid_payload</span> <span class="o">=</span> <span class="s2">""</span>
<span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">natsrc</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="s2">"<natRule><action>snat</action></span><span class="se">\</span>
<span class="s2"> <originalAddress></span><span class="si">{0}</span><span class="s2"></originalAddress></span><span class="se">\</span>
<span class="s2"> <translatedAddress></span><span class="si">{1}</span><span class="s2"></translatedAddress></span><span class="se">\</span>
<span class="s2"> <loggingEnabled>false</loggingEnabled></span><span class="se">\</span>
<span class="s2"> <enabled>true</enabled></span><span class="se">\</span>
<span class="s2"> <originalPort>any</originalPort></span><span class="se">\</span>
<span class="s2"> <translatedPort>any</translatedPort>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'srcaddr'</span><span class="p">],</span> <span class="n">rule</span><span class="p">[</span><span class="s1">'translateaddr'</span><span class="p">])</span>
<span class="k">if</span> <span class="s2">"description"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="n">descr_payload</span> <span class="o">=</span> <span class="s2">"<description></span><span class="si">{0}</span><span class="s2"></description>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'description'</span><span class="p">])</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">descr_payload</span>
<span class="k">if</span> <span class="s2">"protocol"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="k">if</span> <span class="n">rule</span><span class="p">[</span><span class="s1">'protocol'</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"all"</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol>any</protocol>"</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol></span><span class="si">{0}</span><span class="s2"></protocol>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'protocol'</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">proto_payload</span> <span class="o">=</span> <span class="s2">"<protocol>any</protocol>"</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">proto_payload</span>
<span class="k">if</span> <span class="s2">"dstaddr"</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">:</span>
<span class="n">src_payload</span> <span class="o">=</span> <span class="s2">"<snatMatchDestinationAddress></span><span class="si">{0}</span><span class="s2"></snatMatchDestinationAddress>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rule</span><span class="p">[</span><span class="s1">'dstaddr'</span><span class="p">])</span>
<span class="n">base_payload</span> <span class="o">=</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="n">src_payload</span>
<span class="n">mid_payload</span> <span class="o">=</span> <span class="n">mid_payload</span> <span class="o">+</span> <span class="n">base_payload</span> <span class="o">+</span> <span class="s2">"</natRule>"</span>
<span class="n">payload</span> <span class="o">=</span> <span class="n">start_payload</span> <span class="o">+</span> <span class="n">mid_payload</span> <span class="o">+</span> <span class="n">end_payload</span>
<span class="k">return</span> <span class="n">payload</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"vyos.conf"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">config_string</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">config</span> <span class="o">=</span> <span class="n">vyos</span><span class="o">.</span><span class="n">configtree</span><span class="o">.</span><span class="n">ConfigTree</span><span class="p">(</span><span class="n">config_string</span><span class="p">)</span>
<span class="c1"># We start with DNAT rules</span>
<span class="n">destrulesid</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">list_nodes</span><span class="p">([</span><span class="s2">"nat"</span><span class="p">,</span> <span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"rule"</span><span class="p">])</span>
<span class="n">natdest_all</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">destruleid</span> <span class="ow">in</span> <span class="n">destrulesid</span><span class="p">:</span>
<span class="sd">'''</span>
<span class="sd"> We build a huge DNAT dict where keys are rules id and items are dict of rule parameter :</span>
<span class="sd"> '1': {'dstaddr': '1.2.3.4',</span>
<span class="sd"> 'outbound-interface': 'eth1',</span>
<span class="sd"> 'log': 'enable',</span>
<span class="sd"> 'protocol': 'all',</span>
<span class="sd"> 'translateaddr': '10.1.2.3'}</span>
<span class="sd"> '''</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"nat"</span><span class="p">,</span> <span class="s2">"destination"</span><span class="p">,</span> <span class="s2">"rule </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">destruleid</span><span class="p">)]</span>
<span class="n">natdest</span> <span class="o">=</span> <span class="n">get_nat_dest_rule</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
<span class="n">natdest_all</span><span class="p">[</span><span class="n">destruleid</span><span class="p">]</span> <span class="o">=</span> <span class="n">natdest</span>
<span class="c1">#print(natdest_all)</span>
<span class="c1"># Continue with SNAT rules</span>
<span class="n">srcrulesid</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">list_nodes</span><span class="p">([</span><span class="s2">"nat"</span><span class="p">,</span> <span class="s2">"source"</span><span class="p">,</span> <span class="s2">"rule"</span><span class="p">])</span>
<span class="n">natsrc_all</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">srcruleid</span> <span class="ow">in</span> <span class="n">srcrulesid</span><span class="p">:</span>
<span class="sd">'''</span>
<span class="sd"> Same as the DNAT dict</span>
<span class="sd"> '''</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"nat"</span><span class="p">,</span> <span class="s2">"source"</span><span class="p">,</span> <span class="s2">"rule </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">srcruleid</span><span class="p">)]</span>
<span class="n">srcdest</span> <span class="o">=</span> <span class="n">get_nat_source_rule</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
<span class="n">natsrc_all</span><span class="p">[</span><span class="n">srcruleid</span><span class="p">]</span> <span class="o">=</span> <span class="n">srcdest</span>
<span class="c1">#print(natsrc_all)</span>
<span class="c1"># We now have two huge dictionnaries with DNAT and SNAT rules from VyOS</span>
<span class="c1"># We are going to process them and POST them to NSX :crossed_fingers:</span>
<span class="c1"># Replace edge-XXX with the right edge-id</span>
<span class="n">url</span> <span class="o">=</span> <span class="s2">"https://</span><span class="si">{0}</span><span class="s2">/api/4.0/edges/</span><span class="si">{1}</span><span class="s2">/nat/config/rules"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">nsx_manager</span><span class="p">,</span> <span class="n">edge_id</span><span class="p">)</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
<span class="s1">'Accept'</span><span class="p">:</span> <span class="s1">'application/xml'</span><span class="p">,</span>
<span class="s1">'Content-Type'</span><span class="p">:</span> <span class="s1">'application/xml'</span>
<span class="p">}</span>
<span class="n">dstnat_payload</span> <span class="o">=</span> <span class="n">create_dstnat_payload</span><span class="p">(</span><span class="n">natdest_all</span><span class="p">)</span>
<span class="n">srcnat_payload</span> <span class="o">=</span> <span class="n">create_srcnat_payload</span><span class="p">(</span><span class="n">natsrc_all</span><span class="p">)</span>
<span class="c1"># This script is ment to be be run only once</span>
<span class="c1"># Write your Vsphere login and password here</span>
<span class="c1"># Don't commit your login and passord to git!!!!!!!!!</span>
<span class="n">username</span> <span class="o">=</span> <span class="s1">'user'</span>
<span class="n">password</span> <span class="o">=</span> <span class="s1">'password'</span>
<span class="c1"># POST DNAT rules</span>
<span class="c1"># This request append the rules to the existing ones</span>
<span class="c1">#print(dstnat_payload)</span>
<span class="n">dstresponse</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s2">"POST"</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">dstnat_payload</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="n">HTTPBasicAuth</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">),</span> <span class="n">verify</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">dstresponse</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">dstresponse</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'utf8'</span><span class="p">))</span>
<span class="c1"># POST SNAT rules</span>
<span class="c1"># This request append the rules to the existing ones</span>
<span class="c1">#print(srcnat_payload)</span>
<span class="n">srcresponse</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s2">"POST"</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">srcnat_payload</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="n">HTTPBasicAuth</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">),</span> <span class="n">verify</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">srcresponse</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">srcresponse</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'utf8'</span><span class="p">))</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div></td></tr></table></div>
Cisco Hyperflex - Supprimer la configuration réseau de réplication2021-02-03T21:40:00+01:002021-02-03T21:40:00+01:00Aldevartag:blog.devarieux.net,2021-02-03:/2021/02/reset-hyperflex-replication-network.html<p>Cette semaine, j'ai pris le temps de jouer avec une instance de demo Cisco Hyperflex sur <a href="https://dcloud.cisco.com/">dcloud.cisco.com</a>. Cette demo permet de jouer un peu avec deux instances Hyperflex et notamment de mettre en place un PRA entre ces deux instances.
Pour mettre en oeuvre ce PRA, il faut …</p><p>Cette semaine, j'ai pris le temps de jouer avec une instance de demo Cisco Hyperflex sur <a href="https://dcloud.cisco.com/">dcloud.cisco.com</a>. Cette demo permet de jouer un peu avec deux instances Hyperflex et notamment de mettre en place un PRA entre ces deux instances.
Pour mettre en oeuvre ce PRA, il faut au préalable configurer un réseau de réplication (Replication Network) qui doit permettre aux clusters Hyperflex de communiquer entre eux et transférer les données. Malheureusement, par inattention, j'ai fait une erreur lors de la configuration de ce réseau. J'ai paramétré une mauvaise adresse de réseau et une mauvaise gateway et la réplication refusait de fonctionner.</p>
<p>Cette erreur de configuration m'a posé plus de problèmes que ce que je pensais car il n'est pas possible de reconfigurer ce réseau une fois qu'il est enregistré... Cela est indiqué noir sur blanc dans la <a href="https://www.cisco.com/c/en/us/td/docs/hyperconverged_systems/HyperFlex_HX_DataPlatformSoftware/AdminGuide/2_5/b_HyperFlexSystems_AdministrationGuide_2_5/b_HyperFlexSystems_AdministrationGuide_2_5_chapter_01111.html#task_agm_yqs_m1b">documenation Cisco Hyperflex</a>.</p>
<p>Ce problème ne peut pas se régler par l'interface graphique. Il faut passer par la ligne de commande, directement sur le cluster. Ces commandes doivent être exécutées sur une des controller VM du cluster.
Le première commande permet de supprimer un appairage déjà existant entre 2 cluster. La suivante supprime effectivement la confguration du réseau de réplication.</p>
<div class="highlight"><pre><span></span>stcli dp peer forget --all
stcli drnetwork cleanup
</pre></div>
<p>Une fois ces commandes executées, on peut de nouveau configurer le réseau de réplication.</p>
<img alt="Hyperflex Replication Network" class="m-image" src="/images/drnetwork.png" />
Monitoring 101 : Que faut-il surveiller?2017-11-12T16:52:00+01:002017-11-12T16:52:00+01:00Aldevartag:blog.devarieux.net,2017-11-12:/2017/11/monitoring-101-que-surveiller.html<section id="introduction">
<h2>Introduction</h2>
<p>Les métriques sont la partie la plus visible d'une architecture de supervision. Ce sont des données en général facile à récupérer et à stocker. Par conséquent, il arrive souvent qu'on n'investisse pas assez de temps dans la compréhension des données collectées, du pourquoi nous les collectons et ce que …</p></section><section id="introduction">
<h2>Introduction</h2>
<p>Les métriques sont la partie la plus visible d'une architecture de supervision. Ce sont des données en général facile à récupérer et à stocker. Par conséquent, il arrive souvent qu'on n'investisse pas assez de temps dans la compréhension des données collectées, du pourquoi nous les collectons et ce que nous en faisons. Dans la manjorité des architectures de supervision, on se concentre sur la détection simple des problèmes: détecter si un evènement ou un état à eu lieu (une ligne d'erreur dans un log, un processus qui tombe). Puis, quand on reçoit la notification du problème, on se connecte sur la plateforme de supervision pour visualiser les métriques et essayer de comprendre ce qu'il se passe. Dans cette version de la supervision, les métriques sont vues comme un supplément à la detection d'erreurs.</p>
<p>Afin de tenter de sortir de l'ornière et utiliser pleinement les métriques comme moyen d'alerte, nous devons nous mettre d'accord sur la définition de métrique. Je vous donne donc ma version de cette définition.
Les métriques sont les mesures des propriétés d'une partie d'un logiciel ou de materiel. Pour qu'une métrique soit utile, il faut conserver une trace de son état en général en enregistrant l'observation d'une valeur à un temps donné. Une observation contient une valeur, un timestamp et parfois des propriétés (source, tag...)</p>
</section>
<section id="les-metriques">
<h2>Les Métriques</h2>
<p>Il y a 3 catégories de métriques. Les métriques systèmes, les métriques applicatives et les évenements. Chacune de ses catégories se traite différemment et ne sert pas le même objectif.</p>
<section id="les-metriques-systemes">
<h3>Les Métriques Systèmes</h3>
<p>Ce sont les métriques liées à l'infrastructure servant la partie applicative. Cette infrastrcuture est composée de différentes ressources qui peuvent être de bas niveau comme le materiel physique (CPU, RAM, Disques, Réseau) ou de plus haut niveau comme une base de données qui peut aussi être considéré comme une ressource afin qu'une application puisse fournir des résultats. C'est la notion de middleware. Ces métriques peuvent être classées en 3 grandes catégories :</p>
<ul>
<li><strong>Taux de disponiblité</strong>: Pourcentage de temps durant lequel la ressource est capable de répondre à des requêtes.</li>
<li><strong>Taux d'utilisation</strong>: Pourcentage de temps durant lequel la ressource est occupée à répondre à des requêtes.</li>
<li><strong>Contention</strong>: C'est la quantité de requêtes que la ressource ne peut servir car elle est occupée. Cela peut être une file d'attente, des I/O Wait...</li>
</ul>
<p>Voici quelques exemples de métriques systèmes :</p>
<table>
<thead>
<tr><th>Ressource</th>
<th>Disponibilité</th>
<th>Utilisation</th>
<th>Contention</th>
</tr>
</thead>
<tbody>
<tr><td>Base de données</td>
<td>% de temps durant
lequel la DB est
joignable</td>
<td>% de temps durant
lequel chaque
connection est occupée</td>
<td>Nombre de requêtes
en file d'attente</td>
</tr>
<tr><td>Mémoire Vive</td>
<td>N/A</td>
<td>% de la RAM totale
utilisée</td>
<td>Utilisation du swap</td>
</tr>
</tbody>
</table>
<p>
<br />
<br />
</p>
</section>
<section id="les-metriques-applicatives">
<h3>Les Métriques Applicatives</h3>
<p>C'est ici qu'est mesurée l'experience utilisateur ainsi que la santé global du service. Comme pour les métriques système, elles sont classées en plusieurs catégories.</p>
<ul>
<li><strong>Performance</strong>: Cette métrique quantifie l'efficacité d'un composant. La métrique de performance la plus commune est la latence, qui représente le temps nécessaire pour accomplir une tâche. Il y a plusieurs façon d'exprimer cette métrique. On peut en faire une moyenne ou utiliser les percentiles, du type "99% des requêtes ont reçu une réponse en moins de 0.2 secondes".</li>
<li><strong>Debit</strong>: ou également <strong>entrées sorties</strong>. C'est la quantité de requêtes traitée par unité de temps. Par exemple, un nombre de pages affichées par seconde.</li>
<li><strong>Succès</strong>: C'est le pourcentage d'entrées sorties traitées dont l'execution s'est bien déroulée. Par exemple, le nombre de code HTTP 2XX.</li>
<li><strong>Echec</strong>: A l'inverse, le pourcentage d'entrée sorties traitées dont l'execution s'est mal déroulée. Par exemple, le nombre de code HTTP 5XX.</li>
</ul>
<p>Ces métriques permettent de rapidement répondre aux questions qui intéressent les utilisateurs finaux du service. Le service est-il disponible et remplit-il sa mission? A quelle vitesse le fait-il? Avec quelles résultats?</p>
<p>Voici quelques exemples de métriques applicatives pour un service web:</p>
<table>
<thead>
<tr><th>Catégorie</th>
<th>Description</th>
<th>Valeur</th>
</tr>
</thead>
<tbody>
<tr><td>Performance</td>
<td>99ème percentil du temps de réponse (s)</td>
<td>0.3</td>
</tr>
<tr><td>Débit</td>
<td>Requêtes par seconde</td>
<td>220</td>
</tr>
<tr><td>Succès</td>
<td>Pourcentage de code retour HTTP 2XX</td>
<td>99.5</td>
</tr>
<tr><td>Echec</td>
<td>Pourcentage de code retour HTTP 5XX</td>
<td>0.2</td>
</tr>
</tbody>
</table>
<p>
<br />
<br />
</p>
</section>
<section id="les-evenements">
<h3>Les Evenements</h3>
<p>En plus des métriques systèmes et applicatives, il y a certaine information qu'on souhaite récupérer de façon plus sporadique. Certains systèmes permettent de superviser des évenements. Les évenements n'ont pas lieu de façon fréquentes et il est souvent difficile voir impossible de les prévoir.</p>
<ul>
<li>Tâche planifiée en échec</li>
<li>Virus détecté dans un système de fichier</li>
<li>Trap SNMP</li>
</ul>
<p>Contrairement aux métriques qui doivent être analysées dans leur context, les évenements contiennent en général en eux-même suffisamment d'informations pour être directement interprétés.</p>
</section>
<section id="conclusion">
<h3>Conclusion</h3>
<p>Dans le doute, ne pas hésiter à collecter les données. Sachant que ces données doivent être <strong>bien comprises</strong> (je sais ce que cette donnée signifie), avoir une <strong>granularité</strong> adequat (si la granularité est trop large, je perds en précision; si la granularité est trop fine je risque d'impacter le système que je supervise) et être <strong>conservée suffisamment</strong> longtemps pour comprendre quels sont les comportements normaux et anormaux.</p>
</section>
</section>
HyperText Acte 12017-11-03T22:45:00+01:002017-11-03T22:45:00+01:00Aldevartag:blog.devarieux.net,2017-11-03:/2017/11/hypertexte-acte-1.html<p>Voici une collection de liens trouvés ou partagés dernièrement. Je les penses suffisamment utiles pour vous les partager à mon tour.</p>
<p>Bienvenue dans Hypertexte Acte 1. Vous trouverez ici des articles en général plutôt techniques et majoritairement en anglais sur différents sujets dont l'administration système, le réseau, la virtualisation ou encore le savoir être en entreprise (soft skill).</p>
<ul>
<li>[EN] Un article de Quinn Norton sur l'état de l'art en developpement. Il compare le developpement des applications actuelles à des constructions de ponts. La comparaison souffre de quelques biais mais l'article vaut vraiment le coup d'être lu : <a href="https://www.emptywheel.net/2017/09/14/software-is-a-long-con/">SOFTWARE IS A LONG CON</a>.</li>
<li>[EN] Suite à la sortie des CPU dédiés serveurs <code>Intel Xeon Scalable</code>, FRANK DENNEMAN passe en revu les nouveautés apportées par ces CPU en terme de virtualisation de l'execution. Un article incontournable si vous administrez des clusters de virtualisation : <a href="http://frankdenneman.nl/2017/09/26/vsphere-focused-guide-intel-xeon-scalable-family/">A vSphere Focused Guide to the Intel Xeon Scalable Family</a>.</li>
<li>[FR] Un podcast, en français, consacré au DevOps. Deux épisodes publiés à ce jour: <a href="https://soundcloud.com/devobs">DevObs</a>. Mon seul regret est qu'il n'y a pas de flux RSS pour ajouter simplement ce podcast dans une appli dédiée.</li>
<li>[EN] Linux : Auditer la suppression des fichiers avec Auditd. Permet de 'trouver le coupable' si on ne sait pas comment des fichiers disparaissent du filesystem : <a href="http://run.tournament.org.il/audit-delete-commands-in-linux/">Audit delete commands in Linux</a>.</li>
<li>Lors de la migration de ce blog en statique via Pelican, je me suis lancé à la recherche d'une solution d'analyse de traffic. Je souhaitais une solution non intrusive (sans code à charger par le navigateur), un peu du style awstat. Je suis tombé sur le <a href="http://goaccess.io">projet Goaccess</a>, que je ne connaissais pas et qui rempli admirablement bien son rôle en faisant de l'analyse des logs apache en temps réel.</li>
<li>[FR] La semaine prochaine, du 7/11 au 9/11 aura lieu l'évenement européen de Nutanix: le .NEXT Europe à Nice. Je participerai à une discussion le 8/11 à 13h afin de faire un retour d'experience sur la mise en oeuvre de cette solution dans mon entreprise. Nutanix a récemment sortie la version 5 d'AOS qui propose un grand nombre de nouvelles fonctionnalités. C'est pourquoi sur VirtualementVotre, on n'hésite plus à poser la question : <a href="http://www.virtualementvotre.ch/blog/2017/10/30/pourquoi-nutanix-ahv-est-une-reelle-option/">Pourquoi Nutanix AHV est une réelle option ?</a>.</li>
<li>[FR] Un looooong article expliquant <a href="https://medium.com/@djo/obsession-service-client-captain-train-cb0b91467fd9">l’obsession du service client chez Captain Train</a>. Vraiment passionant et instructif.</li>
</ul>
<p>C'est ici que ça se termine. N'hésitez pas à revenir dans quelques temps pour le prochain numéro d'hypertexte. En attendant, n'hésitez pas à me <a href="https://twitter.com/landvarx">contacter sur twitter</a> si vous avez un lien qui aurait sa place dans un futur article.</p>
Migration du Blog sur Pelican2017-11-02T22:45:00+01:002017-11-02T22:45:00+01:00Aldevartag:blog.devarieux.net,2017-11-02:/2017/11/migration-blog-pelican.html<p>Migration du blog sur Pelican, generateur de site static en Python.</p>
<p>Après avoir passé plusieurs années avec Wordpress, j'ai décidé de passé le blog en static sur <a href="https://blog.getpelican.com">Pelican</a>. Les raisons de ce choix sont multpiples :</p>
<ul>
<li>Wordpress est très vulnérable aux attaques et demande un grand niveau d'attention pour que le blog reste en sécurité. Notamment pour ce qui concerne les plugins.</li>
<li>Wordpress est très puissant, peut être trop puissant pour un simple blog.</li>
<li>J'avais besoin de nouveauté et de simplicité.</li>
</ul>
<p>Dorénavant, les articles seront rédigés en reStructuredText puis compilés par Pelican afin de générer ce site statique. Dans l'opération, les commentaires ont disparu.</p>
Monitoring 101 : Les alertes durant les astreintes2017-10-29T19:30:00+01:002017-10-29T19:30:00+01:00Aldevartag:blog.devarieux.net,2017-10-29:/2017/10/monitoring-101-alertes-durant-astreintes.html<section id="introduction">
<h2>Introduction</h2>
<p>Après avoir déployé un système de supervision dans une infrastructure de
taille moyenne et avoir passé quelques temps en rotation dans une équipe
d'astreinte, j'ai tiré un certains nombre de conclusions sur ce que
devrait être la supervision et surtout les alertes qui doivent être
levées lors des astreintes …</p></section><section id="introduction">
<h2>Introduction</h2>
<p>Après avoir déployé un système de supervision dans une infrastructure de
taille moyenne et avoir passé quelques temps en rotation dans une équipe
d'astreinte, j'ai tiré un certains nombre de conclusions sur ce que
devrait être la supervision et surtout les alertes qui doivent être
levées lors des astreintes. L'écriture et l'audit de règles d'alertes
doivent respecter certains principes afin que les astreintes se
déroulent le plus sereinement possible:</p>
<ul>
<li>Une alerte envoyée en astreinte doit être urgente, réelle et
concrète. C'est à dire qu'il doit être possible d'intervenir pour
corriger le problème.</li>
<li>Une alerte doit être levée pour des problèmes imminent ou en cours.</li>
<li>Ne pas hésiter à supprimer les alertes générant du bruit. L'excès de
supervision nuit à la supervision.</li>
<li>La meilleur façon de comprendre un problème est d'alerter sur ses
symptômes.</li>
<li>Corollaire : Eviter d'alerter directement sur les causes.</li>
</ul>
<p>Avant de détailler un peu plus ces principes, voici les 3 règles majeurs
qui, à mon sens, doivent servir de guide:</p>
<ul>
<li>A chaque fois que je reçois une alerte, <strong>je dois la considérer comme
urgente</strong> et agir comme tel. Je ne peux agir comme ça trop souvent
avant de ressentir une lassitude.</li>
<li><strong>Chaque alerte doit être concrète</strong>. Je dois pouvoir réaliser une
action pour la corriger.</li>
<li>Chaque action sur alerte doit se faire avec un certain <strong>niveau
d'expertise</strong>. Si le problème peut être traité par un script, alors
je n'aurais pas du être dérangé.</li>
</ul>
<p>Vu comme ça, c'est un peu ambitieux mais ces règles doivent avant tout
servir de guides pour l'écriture et la revue des alertes. Voici quelques
questions qu'on peut se poser lors de l'écriture d'une nouvelle règle:</p>
<ul>
<li>Cette nouvelle règle ne vient-elle pas surcharger une règle déjà
existante qui est elle-même urgente, concrète et impactante.</li>
<li>Vais-je un jour ignorer cette alerte sachant qu'elle est bénigne?
Puis-je affiner cette règle pour éviter cette situation?</li>
<li>Cette alerte se lève-t-elle pour une condition qui va réellement
impacter les utilisateurs?</li>
<li>Il y a-t-il des actions à mener en réponse à cette alerte? Cette
action doit-elle être réalisée tout de suite ou peut-elle attendre
demain matin, ou lundi, ou le trimestre prochain?</li>
</ul>
<p>Evidemment, aucun système d'alerte dans une infrastructure croissante et
changeante n'est aussi parfait que celui que je viens de décrire mais ce
sont quelques règles qui permettent de s'en approcher autant que
possible.</p>
</section>
<section id="avoir-une-vue-utilisateurs">
<h2>Avoir une vue utilisateurs</h2>
<p>C'est ce que qu'on appelle la "<strong>supervision des symptômes</strong>", opposée
à la "<strong>supervision des causes</strong>". Un petit exemple afin de préciser
le propos : vos utilisateurs se soucient-ils de savoir si votre serveur
SQL est down? Non, ils s'inquiètent si leur requêtes sont en échecs (je
vous entends déjà pleurer sur vos petits check 'SQL Server' Nagios).</p>
<p>En général, les utilisateurs se soucient d'un petit nombre d’éléments:</p>
<ul>
<li><strong>Disponibilité</strong>. Pas d'erreur 500, de requête en attente, de pages
a moitié chargées. Un service qui ne fonctionne pas pleinement doit
être considéré comme un service non disponible.</li>
<li><strong>Latence.</strong> ça doit aller vite!</li>
<li><strong>Exactitude des données</strong>. Les données doivent être en sécurité.
Elles doivent aussi être à jour.</li>
<li><strong>Fonctionnalités.</strong>Le service doit fournir toutes ses
fonctionnalités, même si ce n'est pas une fonction principale du
service. Par exemple, l'auto-complétion dans un champ de recherche.</li>
</ul>
<p>C'est à peu prêt tout.</p>
<p>La différence entre un serveur de base de données <em>down</em> et des données
utilisateurs non disponible est très importante. La première est une
cause, la seconde est un symptôme et l’indisponibilité des données peu
provenir de plusieurs choses. On peut avoir un problème d'I/O ou de CPU
sur le serveur de BDD, rendant les temps de réponses trop long. Vous
n'allez pas pour autant lever une alerte chaque fois que le CPU est à
100% ou chaque fois que l'I/O Wait monte à 60%. Avoir une vue
utilisateur permet de directement savoir si un problème nécessite une
intervention.</p>
</section>
<section id="alerter-sur-les-causes-c-est-nul-mais-parfois-on-n-a-pas-le-choix">
<h2>Alerter sur les causes, c'est nul! (mais parfois, on n'a pas le choix)</h2>
<p>On sait bien que si le serveur de BDD est down les utilisateurs n'auront
pas accès à leur données et il est très tentant de superviser juste le
serveur de BDD et d'ajouter une supervision sur la bonne connexion du
service à la BDD. Ceci pose d'autres problèmes :</p>
<ul>
<li>Il faudra de toute façon vérifier les symptômes. Peut être avons nous
des déconnexions réseaux intempestives, de la contention sur le CPU
ou sur les performances du stockages (qui a dit backup en cours?) ou
une tonnes d'autres problèmes auxquels on ne pense pas. On doit donc
vérifier les symptômes.</li>
<li>Si on attrape les symptômes et les causes, on se retrouve avec une
redondance des alertes et on a donc soit de la duplication d'alerte
soit la mise en place d'un système de dépendances entre les alertes
qui ajoute de la complexité.</li>
<li>Peut être qu'un cluster de base de données a été créé et qu'on ne se
soucie plus de savoir qu'un serveur est tombé.</li>
</ul>
<p>Mais il est vrai que parfois, les alertes sur les causes sont
nécessaires. Par exemple, en général, il n'y a pas de symptômes sur des
problèmes d'espace disque plein à 95% et il est pourtant nécessaire
d'agir avant qu'un manque d'espace ne vienne perturber le service. Ce
type d'alerte est à utiliser avec parcimonie.</p>
</section>
<section id="des-tickets-des-emails">
<h2>Des tickets, des emails...</h2>
<p>Qu'on le veuille ou non, on se retrouve toujours avec des alertes qu'on
peut qualifier de non critique. Elles méritent qu'on s'en occupe, mais
pas forcement maintenant.</p>
<ul>
<li>Dans ce cas, l'ouverture d'un ticket peut-être utile. Votre
plateforme du supervision ouvre un ticket que vous pourrez traiter
lorsque vous aurez plus de temps (après la nuit par exemple).</li>
<li>Chaque alerte devrait automatiquement être tracée quelque part. Par
seulement les envoyer par e-mail, sur un canal IRC ou dans un canal
Slack. En général, ce type d'envoie permet juste de mieux ignorer les
alertes.</li>
</ul>
<p>Le point soulevé ici est qu'il est important de créer un système
d'astreinte qui limite la lassitude, responsabilise sur la réactivité et
qui ne va pas trop régulièrement réveiller la personne d'astreinte,
l'interrompre dans son dîner ou l'empêcher de passer du temps avec sa
famille.</p>
</section>
<section id="procedure">
<h2>Procédure</h2>
<p>Il est préférable d'avoir une documentation dédiée pour chaque alerte ou
famille d'alerte qui est susceptible d'être levée. Cette documentation
doit expliquer ce que signifie l'alerte et comment elle peut être
résolue.</p>
<p>Cette documentation ne doit pas être un long pavé expliquant toute
l'architecture en long et en large. Elle doit expliquer brièvement les
points à vérifier et les différentes actions à mener.</p>
<p>Inversement, la documentation ne doit pas être une simple commande à
taper ou une action simpliste à réaliser. Cela signifierai que l'action
de correction est scriptable et n'aurait pas du déranger la personne
d'astreinte. L'alerte devrait être levée si l’exécution du script ne
corrige pas le problème et nécessite alors une intervention humaine.</p>
</section>
<section id="ne-soyez-pas-naif">
<h2>Ne soyez pas naïf!</h2>
<p>Voici quelques bonnes raisons de ne pas respecter ces règles :</p>
<ul>
<li><strong>Vous avez une cause connue qui fait qu'un service répond de façon
aléatoire</strong>. Dans ce cas, alerter sur un les symptômes ne sera pas
d'une grande aide et il est plus simple d'alerter sur la cause.</li>
<li><strong>Les symptômes apparaissent quand c'est déjà trop tard</strong>, par
exemple quand il n'y a plus d'espace disque.</li>
<li><strong>Le système d'alerte semble être plus complexe que le problème qu'il
tente de détecter</strong>. Le but est de tendre vers plus de simplicité,
plus de robustesse et des système auto-réparant. Avant d'atteindre
cet objectif sur le moyen terme, il est possible qu'il soit plus
efficace d'avoir un système d'alerte complexe mais qui soit fiable et
ne lève pas trop de faux positifs.</li>
</ul>
</section>
State SaltStack pour déploiement de Zabbix-agent2016-08-10T15:36:00+02:002016-08-10T15:36:00+02:00Aldevartag:blog.devarieux.net,2016-08-10:/2016/08/state-saltstack-deploiement-de-zabbix-agent.html<p>SaltStack est un gestionnaire de configuration comparable à Ansible,
Chef ou Puppet fonctionnant sur le modèle Client/Serveur. Le serveur
Salt est appelé 'master' et les clients des 'minions'. Les states sont
des listes de commandes que le serveur fait exécuter par le client. On
utilise YAML pour écrire les …</p><p>SaltStack est un gestionnaire de configuration comparable à Ansible,
Chef ou Puppet fonctionnant sur le modèle Client/Serveur. Le serveur
Salt est appelé 'master' et les clients des 'minions'. Les states sont
des listes de commandes que le serveur fait exécuter par le client. On
utilise YAML pour écrire les states.</p>
<p>Comme je l'avais promis
à <a href="https://twitter.com/SteveDESTIVELLE">@SteveDESTIVELLE</a> voici le
state SaltStack que nous utilisons pour déployer rapidement et
simplement l'agent Zabbix sur nos serveurs.</p>
<p>Ce state installe zabbix-agent sur les serveur Windows 32 et 64bits, sur
les CentOS 6 et 7 ainsi que sur Debian Wheezy. Il est assez simple d'y
ajouter la prise en charge d'autres OS. Sur les linux, le repository
Zabbix est déployé pour faciliter l'installation et la mise à jour de
l'agent. Enfin, le state pousse également le fichier de configuration de
zabbix-agent. Pensez à bien y ajouter le nom ou l'adresse IP de votre
serveur (fichier files/linux/zabbix/zabbix_agentd.conf et
files/windows/zabbix/conf/zabbix_agentd.win.conf ).</p>
<p>Enfin, le state ouvre le firewall Windows, n'oubliez pas d'ajouter l'IP
de votre serveur Zabbix ligne 122 de init.sls .</p>
<p>Pour télécharger les fichiers, ça se passe <a href="https://github.com/aldevar/Zabbix_SaltState">sur
github</a>.</p>
Superviser un serveur HAproxy avec Zabbix2016-08-01T08:30:00+02:002016-08-01T08:30:00+02:00Aldevartag:blog.devarieux.net,2016-08-01:/2016/08/superviser-serveur-haproxy-zabbix.html<p>Après avoir monté le <a href="/monter-cluster-galera-mariadb.html">cluster MariaDB
Galera</a>
et placé un serveur <a href="/galera-load-balancing-failover-haproxy.html">HAproxy en
frontal</a>,
il me restait encore à mettre en place la supervision de ce cluster. Je
voulais notamment, en dehors de la supervision de base qu'on peut
déployer sur un serveur (classiquement processeurs / RAM / disques /
Réseau) pouvoir visualiser …</p><p>Après avoir monté le <a href="/monter-cluster-galera-mariadb.html">cluster MariaDB
Galera</a>
et placé un serveur <a href="/galera-load-balancing-failover-haproxy.html">HAproxy en
frontal</a>,
il me restait encore à mettre en place la supervision de ce cluster. Je
voulais notamment, en dehors de la supervision de base qu'on peut
déployer sur un serveur (classiquement processeurs / RAM / disques /
Réseau) pouvoir visualiser l'état du cluster rapidement.</p>
<p>Je me suis lancé dans la recherche d'un template Zabbix déjà existant
pour superviser HAproxy mais je n'ai rien trouvé de convainquant. Je me
suis décidé à écrire mon propre template et donc le script qui va avec.</p>
<p>Avant d'utiliser ce script, il faut activer les stats dans le fichiers
de configuration d'HAproxy dans la section [global]</p>
<pre class="code sh"><span class="c1"># turn on stats unix socket
</span>stats socket /var/lib/haproxy/stats</pre>
<p>Le script Python va ensuite lire les données en communiquant avec le
socket d'HAproxy directement et retourner la statistique demandée pour
le couple frontend/serveur.</p>
<p>Voici le script.</p>
<div class="highlight"><pre><span></span><span class="ch">#! /usr/bin/python</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">itertools</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">req</span> <span class="o">=</span> <span class="s2">""</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
<span class="n">px</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sv</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="n">queryStat</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">2</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">4</span><span class="p">:</span>
<span class="nb">print</span> <span class="s2">"Usage: run script with one or three arguments</span><span class="se">\n</span><span class="s2">One argument: </span><span class="se">\n</span><span class="s2"> discovery : json output of discovered pxname and svname </span><span class="se">\n\n</span><span class="s2">Three arguments:</span><span class="se">\n</span><span class="s2"> pxname : pxname in which you want to process the stat</span><span class="se">\n</span><span class="s2"> svname : svname in the pxname in which you want to process the stat</span><span class="se">\n</span><span class="s2"> stat : stat you want to query for pxname,svname"</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">allstats</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="s1">'echo "show stat" | socat /var/lib/haproxy/stats stdio'</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span><span class="o">.</span><span class="n">communicate</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">req</span> <span class="o">==</span> <span class="s2">"discovery"</span><span class="p">:</span>
<span class="n">haDiscovery</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">myLine</span> <span class="ow">in</span> <span class="n">allstats</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">lineStats</span> <span class="o">=</span> <span class="n">myLine</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)</span>
<span class="n">pxname</span> <span class="o">=</span> <span class="n">lineStats</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">svname</span> <span class="o">=</span> <span class="n">lineStats</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">haDiscovery</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s1">'{#PXNAME}'</span> <span class="p">:</span> <span class="n">pxname</span><span class="p">,</span> <span class="s1">'{#SVNAME}'</span> <span class="p">:</span> <span class="n">svname</span><span class="p">})</span>
<span class="nb">print</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span> <span class="s2">"data"</span><span class="p">:</span> <span class="n">haDiscovery</span><span class="p">})</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="n">statNameList</span> <span class="o">=</span> <span class="n">allstats</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)</span>
<span class="n">monDico</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">myLine</span> <span class="ow">in</span> <span class="n">allstats</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">statList</span> <span class="o">=</span> <span class="n">myLine</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)</span>
<span class="k">if</span> <span class="n">px</span> <span class="o">==</span> <span class="n">statList</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">and</span> <span class="n">sv</span> <span class="o">==</span> <span class="n">statList</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">monDico</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">izip</span><span class="p">(</span><span class="n">statNameList</span><span class="p">,</span><span class="n">statList</span><span class="p">))</span>
<span class="nb">print</span> <span class="n">monDico</span><span class="p">[</span><span class="n">queryStat</span><span class="p">]</span>
</pre></div>
<p>Une fois toutes ces métriques récupérées, j'ai pu construire un
dashboard Grafana afin d'avoir rapidement sous les yeux l'état général
du cluster.</p>
<div class="m-image">
<a href="/images/Grafana-Galera.png"><img src="https://blog.devarieux.net/images/Grafana-Galera.png" /></a>
</div>
<p>Le script, le template Zabbix et le fichier de paramétrage de l'agent
sont disponible <a href="https://github.com/aldevar/Zabbix_HAproxy">sur
Github</a></p>
Zabbix - Superviser un cluster Ceph2016-07-05T21:45:00+02:002016-07-05T21:45:00+02:00Aldevartag:blog.devarieux.net,2016-07-05:/2016/07/zabbix-superviser-cluster-ceph.html<p>Ceph est une solution open source de stockage distribué avec réplication
des données et une forte tolérance aux pannes. Différentes commandes
existent pour vérifier l'état du cluster et nous allons voir comment les
exploiter avec des scripts Python pour que Zabbix puisse récupérer les
métriques.</p>
<p><img alt="Ceph_Logo" class="m-image" src="/images/Ceph_Logo.png" /></p>
<p>Je suis parti d'un <a href="https://github.com/thelan/ceph-zabbix">template …</a></p><p>Ceph est une solution open source de stockage distribué avec réplication
des données et une forte tolérance aux pannes. Différentes commandes
existent pour vérifier l'état du cluster et nous allons voir comment les
exploiter avec des scripts Python pour que Zabbix puisse récupérer les
métriques.</p>
<p><img alt="Ceph_Logo" class="m-image" src="/images/Ceph_Logo.png" /></p>
<p>Je suis parti d'un <a href="https://github.com/thelan/ceph-zabbix">template déjà
existant</a>, avec un script bash
qui exécute les commandes, parse la sortie et retourne la métrique
attendue. Ce script, à mon avis, a cependant un problème. A chaque
exécution, il exécute toutes les commandes, parse toutes les réponses et
retourne enfin la métrique attendue suivant l'argument passé en entrée.
Ce comportement peu optimisé induit que parfois, suivant la charge du
serveur, l’exécution du script peut prendre trop de temps et l'item
Zabbix tombe en timeout. Ce n'est évidemment pas un comportement que
nous souhaitons avoir.</p>
<p>Puisqu'il fallait reprendre le script, je me suis lancé dans sa complète
réécriture en Python. J'ai pu ainsi profiter du format json proposé par
les outils Ceph pour l'output des données et également du module json
inclus dans Python. Cela m'a permis de gagner du temps (pour moi et le
processeur) car je peux parser les données plus facilement. Le script
bash utilise beaucoup d'expressions régulières via sed. Dorénavant, je
n'ai qu'à appeler le bon objet json et l'afficher.</p>
<p>La version actuel du template comporte 3 scripts. Je peux encore
optimisé tout cela en 1 seul fichier, ce sera pour la prochaine version.
Le premier script nommé cephpools.py permet la découverte automatique
des pools rados Ceph. Le second, cephimages.py, permet quant à lui la
découverte automatique des images rbd de chaque pool. C'est également ce
script qui est appelé pour récupérer la taille des images.</p>
<p>Enfin, le script principal ceph-status.py s'occupe de retourner les
valeurs des métriques à Zabbix : état des pg, santé du cluster, IOPS,
état des mon etc.</p>
<p>Vous pouvez retrouver ces scripts et template zabbix <a href="https://github.com/aldevar/ceph-zabbix">sur la page github
dédiée</a></p>
Zimbra : Envoi de mails via un relais SMTP authentifié2016-06-24T08:30:00+02:002016-06-24T08:30:00+02:00Aldevartag:blog.devarieux.net,2016-06-24:/2016/06/relais-smtp-authentifie-zimbra.html<p>Héberger soi même ses données c'est bien, le faire correctement c'est
mieux. Le problème majeur lorsqu'on souhaite héberger soi même ses mails
est qu'il est difficile de s'assurer que les mails soient bien reçus par
nos correspondants.</p>
<p>Il arrive souvent que l'IP fournie par l’hébergeur fasse partie d'un
bloc …</p><p>Héberger soi même ses données c'est bien, le faire correctement c'est
mieux. Le problème majeur lorsqu'on souhaite héberger soi même ses mails
est qu'il est difficile de s'assurer que les mails soient bien reçus par
nos correspondants.</p>
<p>Il arrive souvent que l'IP fournie par l’hébergeur fasse partie d'un
bloc d'IP bannie par plusieurs serveur SMTP. Il est toujours possible de
se faire débloquer des principales blacklists mais la plupart des
services mails possèdent leur propre blacklist (coucou barracuda). Même
un SPF et un DKIM bien configuré ne suffisent pas à outrepasser ces
blocages.</p>
<p>Plusieurs solutions s'offraient à moi pour contourner ce problème.</p>
<ul>
<li>Changer d'adresse IP: ça peut fonctionner mais impossible de savoir
tant qu'on a pas testé la nouvelle IP. Forte probabilité que cette
IP fasse également partie d'un bloc blacklisté</li>
<li>Passer sur un hébergeur Zimbra : Intéressant, mais souvent très cher.
De l'ordre de 5€/mois et par compte minimum.</li>
<li>Passer par un relais SMTP : J'ai opté pour cette solution même si
elle n'est pas idéal car cela ajoute intermédiaire et une dépendance
pour le service.</li>
</ul>
<p>Pour mettre cette solution en oeuvre, j'ai choisi le service smtp2go. Il
y en a beaucoup d'autres et la plupart proposent des services gratuits
pour un envoi limité de mails. Avec smtp2go, le service est gratuit
jusqu'à 1000 mails par mois ce qui devrait être suffisant.</p>
<p>Une fois l'inscription effectuée, il faut encore configurer Zimbra pour
qu'il utilise ce relais. L'interface web d'administration propose bien
d'ajouter des relais SMTP mais impossible de s'y authentifier. La
configuration d'un relais STMP authentifié doit être faite en ligne de
commande.</p>
<pre>[root@monzimbra]# su - zimbra
## On ajoute le relais SMTP
[root@monzimbra]# zmprov ms monzimbra.mondomaine.com zimbraMtaRelayHost relaissmtp.relaisdomaine.com:port
## On créé un fichier text de mapping login/mdp pour le relais
[root@monzimbra]# echo relaissmtp.relaisdomaine.com USERNAME:PASSWORD > /opt/zimbra/conf/relay_password
## Création de la table postfix
[root@monzimbra]# postmap /opt/zimbra/conf/relay_password
## Pour tester. Cette commande doit retourner le couple login/mdp
[root@monzimbra]# postmap -q relaissmtp.relaisdomaine.com /opt/zimbra/conf/relay_password
## Configuration de postfix pour qu'il utilise la map de login/mdp
[root@monzimbra]# zmprov ms monzimbra.mondomaine.com zimbraMtaSmtpSaslPasswordMaps lmdb:/opt/zimbra/conf/relay_password
## Configuration de postfix pour qu'il utilise l'authentification SSL
[root@monzimbra]# zmprov ms monzimbra.mondomaine.com zimbraMtaSmtpSaslAuthEnable yes
## Configuration de postfix pour qu'il n'utilise pas le canonical name du relais (problème de login/mdp sinon)
[root@monzimbra]# zmproc ms monzimbra.mondomaine.com zimbraMtaSmtpCnameOverridesServername no
## Configuration de TLS
[root@monzimbra]# zmprov ms monzimbra.mondomaine.com zimbraMtaSmtpTlsSecurityLevel may</pre>
<p>C'est terminé, tous les domaines attachés au serveur passeront
dorénavant vers ce relais SMTP.</p>
Galera Mariadb: Load balancing et Failover HAproxy2016-06-21T21:47:00+02:002016-06-21T21:47:00+02:00Aldevartag:blog.devarieux.net,2016-06-21:/2016/06/galera-load-balancing-failover-haproxy.html<p>Après avoir mis en place le <a href="https://blog.devarieux.net/2016/06/monter-cluster-galera-mariadb.html">cluster Galera
Mariadb</a>,
nous avons besoin d'un point d'accès au cluster. Ce point d'accès peut
être un proxy mysql ou tout autre serveur HA.</p>
<p>Nous allons configurer HAproxy avec l'option leastconn pour qu'il envoie
les paquets vers la machine ayant le moins de connexions …</p><p>Après avoir mis en place le <a href="https://blog.devarieux.net/2016/06/monter-cluster-galera-mariadb.html">cluster Galera
Mariadb</a>,
nous avons besoin d'un point d'accès au cluster. Ce point d'accès peut
être un proxy mysql ou tout autre serveur HA.</p>
<p>Nous allons configurer HAproxy avec l'option leastconn pour qu'il envoie
les paquets vers la machine ayant le moins de connexions (Load
Balancing) et nous allons mettre en place un check http pour qu'en cas
de problème sur un noeud, HAproxy ne lui envoie plus de paquets
(FailOver).</p>
<p>Pour cela, nous avons besoin du script clustercheck présent
ici <a class="m-link-wrap" href="https://github.com/olafz/percona-clustercheck">https://github.com/olafz/percona-clustercheck</a>. Ce script doit être
présent sur chaque noeud du cluster mariadb.</p>
<section id="preparation-des-noeuds-du-cluster">
<h2>Préparation des nœuds du cluster</h2>
<p>Toutes les opérations détaillées dans cette section doivent être
effectuées sur tous les nœuds du cluster mariadb.</p>
<p>On commence par récupérer le script clustercheck, puis on créé un
utilisateur mysql pour l’exécution du script et on place le script au
bon endroit</p>
<pre>wget https://raw.githubusercontent.com/olafz/percona-clustercheck/master/clustercheck
mysql> GRANT PROCESS ON *.* TO 'clustercheckuser'@'localhost' IDENTIFIED BY 'clustercheckpassword!'
chmod +x clustercheck
mv clustercheck /usr/bin</pre>
<p>L'étape suivante consiste à créer un service xinetd dont la tâche sera
de lancer le script clustercheck à la demande.</p>
<p>Création du fichier <code>/etc/xinetd.d/mariadbcheck</code>:</p>
<pre># default: on
# description: mariadbcheck
service mariadbcheck
{
disable = no
flags = REUSE
socket_type = stream
port = 9200
wait = no
user = nobody
server = /usr/bin/clustercheck clustercheckuser clustercheckpassword!
log_on_failure += USERID
only_from = 0.0.0.0/0
per_source = UNLIMITED }</pre>
<p>Dans le champ only_from, vous pouvez mettre l'adresse ip d'HAproxy si
vous le souhaitez (avec un /32 à la fin).</p>
<p>Pour avoir un service propre et bien configuré, on l'ajoute aussi dans
<code>/etc/services</code> en commentant les anciens services utilisant le port
9200 (service wap, a priori votre serveur ne devrait pas en avoir besoin
:) )</p>
<pre>mariadbcheck 9200/tcp # mariadbcheck
#wap-wsp 9200/tcp # WAP connectionless session service
#wap-wsp 9200/udp # WAP connectionless session service</pre>
<p>On redémarre xinetd et on devrait avoir le port 9200 en écoute.</p>
<p>Pour vérifier que ça fonctionne, lancez la commande <code>clustercheck</code>.
Elle doit renvoyer du text contenant <code>HTTP/1.1 200 OK</code> qui sera le
retour attendu par HAproxy pour s'assurer que le noeud du cluster est
atteignable.</p>
</section>
<section id="configuration-d-haproxy">
<h2>Configuration d'HAproxy</h2>
<p>La plus gros du boulot est fait. Reste à définir le cluster dans
HAproxy.</p>
<p>Ceci se fait dans le fichier de conf en y ajoutant à la fin :</p>
<pre>listen galera-mariadb 0.0.0.0:3306
balance leastconn
option httpchk
mode tcp
server mariadb01 ip.de.mariadb.01:3306 check port 9200 inter 5000 fastinter 2000 rise 2 fall 2
server mariadb02 ip.de.mariadb.02:3306 check port 9200 inter 5000 fastinter 2000 rise 2 fall 2
server mariadb03 ip.de.mariadb.03:3306 check port 9200 inter 5000 fastinter 2000 rise 2 fall 2</pre>
<p>Après avoir redémarré HAproxy, le cluster doit être joignable et on doit
pouvoir prouver le load balancing :</p>
<pre>[root@haproxy]# mysql -uroot -p -h127.0.0.1 -e "show variables like 'wsrep_node_name' ;"
+-----------------+---------------+
| Variable_name | VALUE |
+-----------------+---------------+
| wsrep_node_name | mariadb01 |
+-----------------+---------------+</pre>
<pre>[root@haproxy]# mysql -uroot -p -h127.0.0.1 -e "show variables like 'wsrep_node_name' ;"
+-----------------+---------------+
| Variable_name | VALUE |
+-----------------+---------------+
| wsrep_node_name | mariadb02 |
+-----------------+---------------+</pre>
<pre>[root@haproxy]# mysql -uroot -p -h127.0.0.1 -e "show variables like 'wsrep_node_name' ;"
+-----------------+---------------+
| Variable_name | VALUE |
+-----------------+---------------+
| wsrep_node_name | mariadb03 |
+-----------------+---------------+</pre>
</section>
Pas à pas - monter un cluster Galera Mariadb2016-06-20T22:40:00+02:002016-06-20T22:40:00+02:00Aldevartag:blog.devarieux.net,2016-06-20:/2016/06/monter-cluster-galera-mariadb.html<p>Lorsque je me suis mis dans l'idée de monter un cluster Galera Mariadb
pour remplacer notre cluster Mysql, je pensais trouver facilement de la
documentation en ligne. On trouve en effet beaucoup d'articles de blogs
expliquant comment créer son cluster Galera malheureusement cette techno
évolue vite et les articles sont …</p><p>Lorsque je me suis mis dans l'idée de monter un cluster Galera Mariadb
pour remplacer notre cluster Mysql, je pensais trouver facilement de la
documentation en ligne. On trouve en effet beaucoup d'articles de blogs
expliquant comment créer son cluster Galera malheureusement cette techno
évolue vite et les articles sont rarement à jour.</p>
<p>La documentation qu'on peut trouver sur le site de mariadb est également
assez succinct et c'est en compilant des articles depuis plusieurs
sources que j'ai pu monter ce cluster.</p>
<p>Galera est une technologie de clusterisation de base de données bien
plus efficace que ce qu'on peut faire actuellement avec mysql. Un
cluster classique mysql fonctionne en mode actif/passif et si le nœud
actif tombe, il est nécessaire de faire une opération manuelle pour
passer un des nœud passif en actif. De plus, si un nœud reste éteint
durant une période prolongée, il ne peut plus rattraper son retard sur
le nœud primaire et sort du cluster. Galera règle ces problèmes avec un
cluster de nœuds actifs/actifs. Chaque nœud est capable de recevoir des
écritures et Galera s'occupe de synchroniser tout ça.</p>
<p>Pour réaliser le cluster, j'ai utilisé 4 serveurs Centos 7 : 3 nœuds
mariadb (il faut un chiffre impair pour respecter le quorum) et un
serveur haproxy en frontal en mode répartition de charge (leastconn) qui
fait office de passerelle d'accès. Les machines s'appellent
respectivement mariadb01, mariadb02, mariadb03 et mariadb-proxy.</p>
<p>Cet article s'attache à la mise en oeuvre du cluster en lui même. Un
second article détaillera <a href="https://blog.devarieux.net/2016/06/galera-load-balancing-failover-haproxy.html">le déploiement
d'haproxy</a>.</p>
<section id="configuration-du-noeud-mariadb01">
<h2>Configuration du nœud mariadb01</h2>
<p>On commence par récupérer le repo mariadb pour CentOS
ici <a class="m-link-wrap" href="https://downloads.mariadb.org/mariadb/repositories/">https://downloads.mariadb.org/mariadb/repositories/</a> ce qui devrait
vous donner quelque chose comme ça:</p>
<pre class="code"># Put this file in /etc/yum.repos.d/
# MariaDB 10.1 CentOS repository list - created 2016-06-20 19:31 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1</pre>
<p>On peut ensuite installer les paquets nécessaires</p>
<p>
<code>yum -y install MariaDB-server MariaDB-client galera rsync xinetd</code><br />
<p>
On édite ensuite le fichier de configuration de galera<br />
<code>vim /etc/my.cnf.d/server.conf</code><br />
Et dans la zone du fichier dédiée à galera:<br />
</p>
</p>
<pre>[galera]
# Mandatory settings
wsrep_on=ON
wsrep_provider='/lib64/galera/libgalera_smm.so'
wsrep_cluster_address='gcomm://'
wsrep_cluster_name='galera'
wsrep_node_name='mariadb01'
wsrep_sst_method=rsync
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0</pre>
<p>On ne donne aucune adresse pour le moment au cluster. On laisse la
valeur par défaut gcomm://. On reviendra sur cette partie plus tard.</p>
<p>Avant de démarrer le premier nœud du cluster, on lance la sécurisation
de l'instance mariadb avec la commande mysql_secure_installation.</p>
<p>Une fois cette étape effectuée, on peut démarrer le cluster. Cette
commande ne doit être lancée qu'une seule fois et seulement sur le
premier noeud configuré.</p>
<pre>galera_new_cluster</pre>
<p>On se connecte ensuite sur l'instance mysql pour vérifier que le cluster
est bien opérationnel:</p>
<pre>[root@mariadb01 ~]# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 18705
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW GLOBAL STATUS WHERE Variable_name IN ('wsrep_ready', 'wsrep_cluster_size', 'wsrep_cluster_status', 'wsrep_connected');
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| wsrep_cluster_size | 1 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------+---------+
4 rows in set (0.01 sec)</pre>
<p>Et voilà notre cluster Galera composée de 1 nœud pour le moment :)</p>
</section>
<section id="configuration-de-mariadb02-et-mariadb03">
<h2>Configuration de mariadb02 et mariadb03</h2>
<p>On reprend les mêmes étapes que pour mariadb01 en adaptant le fichier de
configuration. On n'oublie pas de lancer mysql_secure_installation.</p>
<p>Le fichier de conf de mariadb02 :</p>
<pre>[galera]
# Mandatory settings
wsrep_on=ON
wsrep_provider='/lib64/galera/libgalera_smm.so'
wsrep_cluster_address='gcomm://mariadb01,mariadb02'
wsrep_cluster_name='galera'
wsrep_node_name='mariadb02'
wsrep_sst_method=rsync
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0</pre>
<p>On peut lancer le service mariadb de façon classique et vérifier que le
cluster est opérationnel :</p>
<pre>[root@mariadb02 ~]# systemctl start mariadb
[root@mariadb02 ~]# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 18905
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW GLOBAL STATUS WHERE Variable_name IN ('wsrep_ready', 'wsrep_cluster_size', 'wsrep_cluster_status', 'wsrep_connected');
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| wsrep_cluster_size | 2 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------+---------+
4 rows in set (0.01 sec)</pre>
<p>On a bien 2 nœuds dans notre cluster, passons à mariadb03</p>
<p>Le fichier de conf de mariadb03 :</p>
<pre>[galera]
# Mandatory settings
wsrep_on=ON
wsrep_provider='/lib64/galera/libgalera_smm.so'
wsrep_cluster_address='gcomm://mariadb01,mariadb02,mariadb03'
wsrep_cluster_name='galera'
wsrep_node_name='mariadb03'
wsrep_sst_method=rsync
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0</pre>
<p>Idem, on lance le service et on vérifie que tout est ok:</p>
<pre>[root@mariadb02 ~]# systemctl start mariadb
[root@mariadb02 ~]# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 18905
Server version: 10.1.14-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW GLOBAL STATUS WHERE Variable_name IN ('wsrep_ready', 'wsrep_cluster_size', 'wsrep_cluster_status', 'wsrep_connected');
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| wsrep_cluster_size | 3 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------+---------+
4 rows in set (0.01 sec)</pre>
<p>Trois nœuds dans le cluster, c'est bon!</p>
</section>
<section id="configuration-finale">
<h2>Configuration finale</h2>
<p>On corrige maintenant les adresses de cluster sur les serveurs mariadb01
et mariadb02 en y mettant la même valeur que dans le fichier de conf de
mariadb03</p>
<pre>wsrep_cluster_address='gcomm://mariadb01,mariadb02,mariadb03'</pre>
<p>Puis on redémarrer les services</p>
<pre>[root@mariadb02 ~]# systemctl restart mariadb</pre>
<pre>[root@mariadb01 ~]# systemctl restart mariadb</pre>
<p>C'est terminé.</p>
<p>A ce stade, vous devez pouvoir vous connecter sur n'importe quel noeud,
créer une base, elle sera dupliquée dans la foulée sur les autres nœuds.</p>
</section>
Pydio - migration, upgrade, package [EN]2016-05-27T23:02:00+02:002016-05-27T23:02:00+02:00Aldevartag:blog.devarieux.net,2016-05-27:/2016/05/pydio-migration-upgrade-package-en.html<p>Cet article est également disponible <a href="http://blog.devarieux.net/2016/05/pydio-migration-upgrade-package-fr/">en
français</a>.</p>
<p>This unclear title reveals an operation i've just done to make 3 moves
in one. Pydio 6.0.7 was running on a CentOS 6 server, installed via the
tar.gz archive.</p>
<p>The primary goal was to upgrade Pydio to 6.4. Unfortunately …</p><p>Cet article est également disponible <a href="http://blog.devarieux.net/2016/05/pydio-migration-upgrade-package-fr/">en
français</a>.</p>
<p>This unclear title reveals an operation i've just done to make 3 moves
in one. Pydio 6.0.7 was running on a CentOS 6 server, installed via the
tar.gz archive.</p>
<p>The primary goal was to upgrade Pydio to 6.4. Unfortunately, there was
dependcies problems with php. Pydio 6.4 needs php 5.4 and CentOS only
brings 5.3 (you can install php 5.4 via other repos but I didn't want
this). The first was to create a new Centos7 VM, then install Pydio on
it using yum and the Pydio repo and finally import the old config in the
brand new Pydio.</p>
<p>Installing Pydio through the package manager allows you to update it
easily and it also ease the automation for an autmatic deployement.
Also, the plugin management is facilitated.</p>
<p>These are the steps I'll describe here.</p>
<p>Install mariadb and httpd</p>
<pre class="code sh">yum install -y mariadb mariadb-server
systemctl start mariadb.service
systemctl <span class="nb">enable</span> mariadb.service
mysql_secure_installation
yum install httpd
systemctl <span class="nb">enable</span> httpd.service
systemctl start httpd.service</pre>
<p>Installing Pydio dependancies :</p>
<pre class="code">yum -y install php php-gd php-ldap php-pear php-xml php-xmlrpc php-mbstring curl php-mcrypt* php-mysql</pre>
<p>Installing Pydio repositories</p>
<pre class="code">wget https://download.pydio.com/pub/linux/centos/7/pydio-release-1-1.el7.centos.noarch.rpm</pre>
<p>If you own a licence (free up to 10 users), you can also have the
enterprise repo.</p>
<pre class="code">wget https://API_KEY:API_SECRET@download.pydio.com/auth/linux/centos/7/x86_64/pydio-enterprise-release-1-1.el7.centos.noarch.rpm</pre>
<p>With API_KEY and API_SECRET in your dashboard on pydio.com, licence
tab</p>
<pre class="code">rpm -ivh pydio-release-1-1.el7.centos.noarch.rpm
rpm -ivh pydio-enterprise-release-1-1.el7.centos.noarch.rpm</pre>
<p>Edit the repo file to add your API_KEY and API_SECRET</p>
<pre class="code">vim /etc/yum.repos.d/pydio-enterprise.repo</pre>
<p>InstallPydio</p>
<pre class="code">yum update
yum install pydio-enterprise</pre>
<p>I use to modify the default vhost file /etc/httpd/conf.d/pydio.conf</p>
<pre class="code apache"><span class="nt"><VirtualHost</span><span class="w"> </span><s>nom.du.vhost:80</s><span class="nt">></span><span class="w">
</span><span class="nb">Alias</span><span class="w"> </span>/<span class="w"> </span><span class="sx">/usr/share/pydio/</span><span class="w">
</span><span class="nb">Alias</span><span class="w"> </span><span class="sx">/pydio_public</span><span class="w"> </span><span class="sx">/var/lib/pydio/public/</span><span class="w">
</span><span class="nt"><Directory</span><span class="w"> </span><s>/usr/share/pydio/</s><span class="nt">></span><span class="w">
</span><span class="nb">Options</span><span class="w"> </span>FollowSymLinks<span class="w">
</span><span class="nb">AllowOverride</span><span class="w"> </span>Limit<span class="w"> </span>FileInfo<span class="w">
</span><span class="nb">Require</span><span class="w"> </span><span class="k">all</span><span class="w"> </span>granted<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>error_reporting<span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>upload_max_filesize<span class="w"> </span><span class="m">100</span>M<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>post_max_size<span class="w"> </span><span class="m">100</span>M<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>output_buffering<span class="w"> </span><span class="k">Off</span><span class="w">
</span><span class="nt"></Directory></span><span class="w">
</span><span class="nt"><Directory</span><span class="w"> </span><s>/var/lib/pydio/public/</s><span class="nt">></span><span class="w">
</span><span class="nb">AllowOverride</span><span class="w"> </span>Limit<span class="w"> </span>FileInfo<span class="w">
</span><span class="nb">Require</span><span class="w"> </span><span class="k">all</span><span class="w"> </span>granted<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>error_reporting<span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="nt"></Directory></span><span class="w">
</span><span class="nt"></VirtualHost></span></pre>
<p>Customize the charset in /etc/pydio/bootstrap_conf.php</p>
<pre class="code">define("AJXP_LOCALE", "fr_FR.UTF-8");</pre>
<p>Create the database:</p>
<pre class="code">mysql -u root -p
create database pydio;
create user pydio@localhost identified by 'mypassword';
grant all privileges on pydio.* to pydio@localhost identified by 'mypassword';
use mysql
update mysql.users set Super_Priv='Y' where user like pydio;</pre>
<p>The last command gives the Super Privileges to the pydio user for it to
be able to create triggers.</p>
<p>Install the Pydio plugins;</p>
<pre class="code">yum install pydio-plugin*</pre>
<p>The last step is to import your old pydio database in your brand new one</p>
<pre class="code">mysql -u pydio -p pydio < mondumppydio.sql</pre>
<p>Finally, you can go to the pydio page and go through the First Run
Wizard. Once done, you should be able to connect with your account and
find all your files.</p>
Pydio : migration, upgrade, package [FR]2016-05-27T23:02:00+02:002016-05-27T23:02:00+02:00Aldevartag:blog.devarieux.net,2016-05-27:/2016/05/pydio-migration-upgrade-package-fr.html<p>The article is also available <a href="http://blog.devarieux.net/2016/05/pydio-migration-upgrade-package-en/">in
english</a>.</p>
<p>Sous ce titre peu clair se cache une opération de que je viens de mener
afin d'opérer 3 opérations sur une instance pydio. Pour mettre les
choses dans leur contexte, Pydio était installé via l'archive tar.gz,
sur un serveur CentOS 6 et …</p><p>The article is also available <a href="http://blog.devarieux.net/2016/05/pydio-migration-upgrade-package-en/">in
english</a>.</p>
<p>Sous ce titre peu clair se cache une opération de que je viens de mener
afin d'opérer 3 opérations sur une instance pydio. Pour mettre les
choses dans leur contexte, Pydio était installé via l'archive tar.gz,
sur un serveur CentOS 6 et la version utilisée était la 6.0.7.</p>
<p>L'objectif initial est de mettre à jour Pydio en version 6.4.
Malheureusement, la version de php nécessaire n'est pas présente dans
Centos 6 (sauf via des dépôts externe que je ne souhaitais pas
utiliser). La première étape est donc de monter une nouvelle VM Centos7
puis d'installer Pydio avec yum via le dépôt Pydio et d'importer
l'ancienne configuration dans cette nouvelle instance.</p>
<p>Installer Pydio via le gestionnaire de paquet permet de plus facilement
le mettre à jour et facilite également l'automation pour un déploiement
automatique de Pydio ainsi que la gestion des plugins.</p>
<p>Ce sont ces étapes que je vais détailler ici.</p>
<p>Installation de mariadb et httpd</p>
<pre class="code sh">yum install -y mariadb mariadb-server
systemctl start mariadb.service
systemctl <span class="nb">enable</span> mariadb.service
mysql_secure_installation
yum install httpd
systemctl <span class="nb">enable</span> httpd.service
systemctl start httpd.service</pre>
<p>Installation des dépendances pour Pydio :</p>
<pre class="code">yum -y install php php-gd php-ldap php-pear php-xml php-xmlrpc php-mbstring curl php-mcrypt* php-mysql</pre>
<p>Installation des dépots Pydio</p>
<pre class="code">wget https://download.pydio.com/pub/linux/centos/7/pydio-release-1-1.el7.centos.noarch.rpm</pre>
<p>Si vous avez une licence pydio (gratuit jusqu'à 10 utilisateurs), vous
devez aussi récupérer le dépot enterprise</p>
<pre class="code">wget https://API_KEY:API_SECRET@download.pydio.com/auth/linux/centos/7/x86_64/pydio-enterprise-release-1-1.el7.centos.noarch.rpm</pre>
<p>Avec API_KEY et API_SECRET dans votre dashboard sur pydio.com, onglet
licence</p>
<pre class="code">rpm -ivh pydio-release-1-1.el7.centos.noarch.rpm
rpm -ivh pydio-enterprise-release-1-1.el7.centos.noarch.rpm</pre>
<p>Edition du dépot pour ajouter API_KEY et API_SECRET</p>
<pre class="code">vim /etc/yum.repos.d/pydio-enterprise.repo</pre>
<p>Installation de pydio</p>
<pre class="code">yum update
yum install pydio-enterprise</pre>
<p>Modification du vhost par defaut :</p>
<pre class="code apache"><span class="nt"><VirtualHost</span><span class="w"> </span><s>nom.du.vhost:80</s><span class="nt">></span><span class="w">
</span><span class="nb">Alias</span><span class="w"> </span>/<span class="w"> </span><span class="sx">/usr/share/pydio/</span><span class="w">
</span><span class="nb">Alias</span><span class="w"> </span><span class="sx">/pydio_public</span><span class="w"> </span><span class="sx">/var/lib/pydio/public/</span><span class="w">
</span><span class="nt"><Directory</span><span class="w"> </span><s>/usr/share/pydio/</s><span class="nt">></span><span class="w">
</span><span class="nb">Options</span><span class="w"> </span>FollowSymLinks<span class="w">
</span><span class="nb">AllowOverride</span><span class="w"> </span>Limit<span class="w"> </span>FileInfo<span class="w">
</span><span class="nb">Require</span><span class="w"> </span><span class="k">all</span><span class="w"> </span>granted<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>error_reporting<span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>upload_max_filesize<span class="w"> </span><span class="m">100</span>M<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>post_max_size<span class="w"> </span><span class="m">100</span>M<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>output_buffering<span class="w"> </span><span class="k">Off</span><span class="w">
</span><span class="nt"></Directory></span><span class="w">
</span><span class="nt"><Directory</span><span class="w"> </span><s>/var/lib/pydio/public/</s><span class="nt">></span><span class="w">
</span><span class="nb">AllowOverride</span><span class="w"> </span>Limit<span class="w"> </span>FileInfo<span class="w">
</span><span class="nb">Require</span><span class="w"> </span><span class="k">all</span><span class="w"> </span>granted<span class="w">
</span><span class="nb">php_value</span><span class="w"> </span>error_reporting<span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="nt"></Directory></span><span class="w">
</span><span class="nt"></VirtualHost></span></pre>
<p>Modification du charset dans /etc/pydio/bootstrap_conf.php</p>
<pre class="code">define("AJXP_LOCALE", "fr_FR.UTF-8");</pre>
<p>Création de la base de données:</p>
<pre class="code">mysql -u root -p
create database pydio;
create user pydio@localhost identified by 'mypassword';
grant all privileges on pydio.* to pydio@localhost identified by 'mypassword';
update mysql.users set Super_Priv='Y' where user like pydio;</pre>
<p>La dernière commande sert à donner les super privilège à l'utilisateur
pydio afin qu'il puisse créer des triggers.</p>
<p>Vient ensuite l'installation des plugins pydio:</p>
<pre class="code">yum install pydio-plugin*</pre>
<p>On termine par l'import de la base de données</p>
<pre class="code">mysql -u pydio -p pydio < mondumppydio.sql</pre>
<p>Enfin, on lance l'interface de pydio et on passe via le wizard pour la
première configuration. Une fois terminé, on doit pouvoir se connecter
avec son compte habituel et retrouver tous ses fichiers.</p>
Nutanix Template for Zabbix2016-03-31T17:35:00+02:002016-03-31T17:35:00+02:00Aldevartag:blog.devarieux.net,2016-03-31:/2016/03/nutanix-template-for-zabbix.html<p>Cet article est également disponible <a href="http://blog.devarieux.net/2016/03/template_nutanix_pour_zabbix/">en
français</a></p>
<p>For the needs of our infrastructure, I built a Nutanix Template for the
monitoring plateforme Zabbix. This template automatically discover
containers, CVMs, hard drives, hypervisors and virtual machines.</p>
<p>Once the items are discovered, some metrics, graphs and triggers are
deployed</p>
<p>To be able …</p><p>Cet article est également disponible <a href="http://blog.devarieux.net/2016/03/template_nutanix_pour_zabbix/">en
français</a></p>
<p>For the needs of our infrastructure, I built a Nutanix Template for the
monitoring plateforme Zabbix. This template automatically discover
containers, CVMs, hard drives, hypervisors and virtual machines.</p>
<p>Once the items are discovered, some metrics, graphs and triggers are
deployed</p>
<p>To be able to use this template, the prism's SNMP server needs to be
configured, the Nutanix MIB needs to be integrated in the zabbix server
and some macros needs to be set at the host level in Zabbix. We will go
through these few steps in the next part of this post.</p>
<p>The template is configured to use SNMPv3 in authPriv mode, using SHA
auth and AES privacy.</p>
<section id="prism-central">
<h2>Prism Central</h2>
<p>The prism configuration is quite simple, using the SNMP configuration
interface</p>
<p><img alt="2016-03-18 09_52_19-Nutanix Web Console" class="m-image" src="images/2016-03-18-09_52_19-Nutanix-Web-Console.png" /></p>
<p>Make sure at least one Transport is configured in UDP, on the port of
your choice (161 by default)</p>
<p><img alt="2016-03-18 09_52_56-Nutanix Web Console" class="m-image" src="images/2016/03/2016-03-18-09_52_56-Nutanix-Web-Console.png" /></p>
<p>Then, go in the 'Users' tab and add a new user for Zabbix.</p>
<p><img alt="2016-03-18 09_53_41-Nutanix Web Console" class="m-image" src="images/2016-03-18-09_53_41-Nutanix-Web-Console.png" /></p>
<p>While you are here, you can download the MIB, we will need it later.</p>
<p>Clic Save. The prim configuration is done.</p>
</section>
<section id="nutanix-mib">
<h2>Nutanix MIB</h2>
<p>One you have downloaded the Nutanix MIB, we need to upload it on the
Zabbix server. On CentOS, it is located in /usr/share/snmp/mibs</p>
<pre># ls /usr/share/snmp/mibs/NUTANIX*
/usr/share/snmp/mibs/NUTANIX-MIB</pre>
<p>Restart Zabbix so it can use this new MIB</p>
<pre># systemctl restart zabbix-server</pre>
<p>You can test the MIB and the prism configuration using the snmpwalk
command line tool. In the example, we are listing all the Nutanix
containers.</p>
<pre>snmpwalk -v 3 -a SHA -A YOURSHAPASSWORD -u zabbix -x AES -X YOURAESPASSWORD IP.OF.PRISM.CENTRAL -l AuthPriv citContainerName
NUTANIX-MIB::citContainerName.1 = STRING: container00.
NUTANIX-MIB::citContainerName.2 = STRING: containerA.
NUTANIX-MIB::citContainerName.3 = STRING: containerB.
NUTANIX-MIB::citContainerName.4 = STRING: containerC.
NUTANIX-MIB::citContainerName.5 = STRING: RESERVED_SPACE.
NUTANIX-MIB::citContainerName.6 = STRING: containerD.</pre>
<p>The server configuration is done, we can now configure Zabbix itself.</p>
</section>
<section id="zabbix">
<h2>Zabbix</h2>
<p>If it's not already done, create a new host for prism central in Zabbix.
The host needs 3 macros for the Nutanix Template to work on it.</p>
<p>Those 3 macros are</p>
<ul>
<li>{$NTX_SNMP_USER} : the SNMP user</li>
<li>{$NTX_SNMP_AUTH} : the SHA password</li>
<li>{$NTX_SNMP_PRIV} : the AES password</li>
</ul>
<p>Then, import this
<a href="http://blog.devarieux.net/wp-content/uploads/2016/03/Template_SNMP_Nutanix_Cluster.xml">Template</a>
in Zabbix and apply it on your prism central host.</p>
<p>By default, the VM discovery is disabled because I couldn't find a good
way to create hosts from the LLD process.</p>
<p>If you have a big Nutanix cluster and Zabbix shows a timeout error while
parsing the SNMP OIDs, you can increase this timeout in the Zabbix
configuration file</p>
<pre>Timeout=10</pre>
<p>Known bugs :</p>
<ul>
<li>Until NOS 4.6, LLD can't discover all hypervisors. This behavior is
the same when using snmpwalk. I guess this is a Nutanix problem.
Everything works fine in NOS 4.6</li>
<li>The number of found VMs is limited to 250. I guess this is a
limitation on the Nutanix side.</li>
</ul>
</section>
Template Nutanix pour Zabbix2016-03-31T17:32:00+02:002016-03-31T17:32:00+02:00Aldevartag:blog.devarieux.net,2016-03-31:/2016/03/template_nutanix_pour_zabbix.html<p>This post is also available in english</p>
<p>Afin de superviser correctement notre cluster Nutanix sans passer trop
de temps à configurer les objets à surveiller, j'ai construit un
template Nutanix pour l'outil de monitoring Zabbix. Ce template s'occupe
de découvrir automatiquement les containers, les CVM, les disques durs,
les hyperviseurs …</p><p>This post is also available in english</p>
<p>Afin de superviser correctement notre cluster Nutanix sans passer trop
de temps à configurer les objets à surveiller, j'ai construit un
template Nutanix pour l'outil de monitoring Zabbix. Ce template s'occupe
de découvrir automatiquement les containers, les CVM, les disques durs,
les hyperviseurs ainsi que les machines virtuelles.</p>
<p>Une fois les objets découverts, un certains nombre de relevés de
métriques, de graphs et de triggers sont mis en place.</p>
<p>Pour utiliser ce template correctement, il est nécessaire de paramétrer
le serveur snmp de prism central, de récupérer la MIB de Nutanix pour
l'intégrer dans le serveur Zabbix et de configurer quelques macro au
niveau de l'hôte prism dans Zabbix. Nous allons tout de suite détailler
ces quelques étapes.</p>
<p>Le template est paramétré pour utiliser SNMPv3 en mode authPriv avec
Auth SHA et Privacy AES.</p>
<section id="prism-central">
<h2>Prism Central</h2>
<p>La configuration de prism se fait de façon assez simple via l'interface
de paramétrage SNMP.</p>
<p><img alt="2016-03-18 09_52_19-Nutanix Web Console" class="m-image" src="https://blog.devarieux.net/images/2016-03-18-09_52_19-Nutanix-Web-Console.png" /></p>
<p>Assurez-vous que le transport soit bien configuré en UDP, sur le port de
votre choix (161 par défaut)</p>
<p><img alt="2016-03-18 09_52_56-Nutanix Web Console" class="m-image" src="https://blog.devarieux.net/images/2016-03-18-09_52_56-Nutanix-Web-Console.png" /></p>
<p>Se rendre ensuite dans l'onglet Users et ajouter un nouvel utilisateur
pour que zabbix puisse se connecter</p>
<p><img alt="2016-03-18 09_53_41-Nutanix Web Console" class="m-image" src="https://blog.devarieux.net/images/2016-03-18-09_53_41-Nutanix-Web-Console.png" /></p>
<p>Profitez-en pour télécharger la MIB via le bouton Download MIB, nous
allons en avoir besoin.</p>
<p>Cliquez sur Save. La configuration de prism est terminée</p>
</section>
<section id="mib-nutanix">
<h2>MIB Nutanix</h2>
<p>Une fois la MIB Nutanix récupérée, il faut la placer sur le serveur
Zabbix. Sur un serveur CentOS, il faut placer le fichier dans
/usr/share/snmp/mibs</p>
<pre># ls /usr/share/snmp/mibs/NUTANIX*
/usr/share/snmp/mibs/NUTANIX-MIB</pre>
<p>Afin que Zabbix prenne ce nouveau fichier en considération, il est
nécessaire de redémarrer le service</p>
<pre># systemctl restart zabbix-server</pre>
<p>Pour tester le bon fonctionnement de la MIB et de la configuration de
prism, utilisons la commande snmpwalk qui va, dans cet exemple, lister
les noms des containers Nutanix.</p>
<pre>snmpwalk -v 3 -a SHA -A VOTREMOTDEPASSESHA -u zabbix -x AES -X VOTREMOTDEPASSEAES IP.DE.PRISM.CENTRAL -l AuthPriv citContainerName
NUTANIX-MIB::citContainerName.1 = STRING: container00.
NUTANIX-MIB::citContainerName.2 = STRING: containerA.
NUTANIX-MIB::citContainerName.3 = STRING: containerB.
NUTANIX-MIB::citContainerName.4 = STRING: containerC.
NUTANIX-MIB::citContainerName.5 = STRING: RESERVED_SPACE.
NUTANIX-MIB::citContainerName.6 = STRING: containerD.</pre>
<p>La configuration du serveur est terminée. On peut passer à la
configuration de Zabbix.</p>
</section>
<section id="zabbix">
<h2>Zabbix</h2>
<p>Si ce n'est pas déjà fait, créez un nouvel hôte pour prism central dans
Zabbix. Cet hôte à besoin de 3 macros pour que le template Nutanix
fonctionne. Ces 3 macros sont l'utilisateurs SNMP, le mot de passe SHA
et le mot de passe AES.</p>
<p>Ces macros sont :</p>
<ul>
<li>{$NTX_SNMP_USER}</li>
<li>{$NTX_SNMP_AUTH}</li>
<li>{$NTX_SNMP_PRIV}</li>
</ul>
<p><img alt="2016-03-18 11_06_42-Zabbix Appliance_ Configuration of hosts" class="m-image" src="https://blog.devarieux.net/images/2016-03-18-11_06_42-Zabbix-Appliance-Configuration-of-hosts.png" /></p>
<p>Importez ensuite ce
<a href="http://blog.devarieux.net/wp-content/uploads/2016/03/Template_SNMP_Nutanix_Cluster.xml">Template</a>
dans Zabbix et appliquez le sur votre hôte Prism Central.</p>
<p>Par défaut, la découverte des VM est désactivée car il n'est pas
possible de créer proprement des hôtes depuis ce processus LLD.</p>
<p>Si vous avez un cluster Nutanix volumineux et que Zabbix ne peux
remonter les informations à cause d'une erreur de timeout, pensez à
augmenter ce timeout dans la configuration de Zabbix</p>
<pre>Timeout=10</pre>
<p>Les bugs rencontrés actuellement sont les suivants :</p>
<ul>
<li>Jusqu'à la version 4.6 de NOS, le Discovery n'arrive pas à remonter
tous les hyperviseurs. Le comportement est le même avec snmpwalk. Il
semble que ce soit un problème du coté de Nutanix. Le problème est
corrigé en 4.6.</li>
<li>Le nombre de VM remontées est limité à 250. Sans doute une limitation
coté Nutanix également.</li>
</ul>
</section>
Migration OpenLDAP 2.2 vers OpenLDAP 2.42015-10-30T23:24:00+01:002015-10-30T23:24:00+01:00Aldevartag:blog.devarieux.net,2015-10-30:/2015/10/migration-openldap-2-2-vers-openldap-2-4.html<p>Parfois, certains serveurs sont là depuis tellement longtemps qu'on n'y
prête même plus attention. Et pourtant, il arrive qu'ils fassent tourner
des applications assez sensible, parfois même critique.</p>
<p>C'est le cas de ce serveur OpenLDAP qui tourne sur une RedHat 5, sans
licence (donc sans yum) et dont la version …</p><p>Parfois, certains serveurs sont là depuis tellement longtemps qu'on n'y
prête même plus attention. Et pourtant, il arrive qu'ils fassent tourner
des applications assez sensible, parfois même critique.</p>
<p>C'est le cas de ce serveur OpenLDAP qui tourne sur une RedHat 5, sans
licence (donc sans yum) et dont la version 2.2 d'OpenLDAP installée a
été compilée dans /usr/local. Typiquement le genre de serveur dont
personne ne veut s'occuper parce qu'il est difficile à maintenir et il
est également difficile de s'en débarrasser car il faut pouvoir sortir
les applications qui y tournent.</p>
<p>Avec un collègue nous nous sommes donc attelé à cette tâche, non sans
peine. Il n'était à priori pas difficile de sortir un annuaire OpenLDAP
2.2 vers un nouvel annuaire OpenLDAP 2.2 mais l’intérêt de cette
manipulation était assez limité. Nous avons donc décidé de migrer vers
la version 2.4 d'OpenLDAP proposée dans les dépôts de CentOS 7. Nous
souhaitions également profiter de cette migration pour passer d'une
configuration fichier (slapd.conf) à une configuration en base (olc, en
gros OpenLDAP stock sa configuration dans une base LDAP). Voici la
méthode employée pour réussir cette opération :</p>
<p>La première étape est de récupérer les informations dont nous avons
besoin sur l'ancien serveur. Nous avons besoin de son fichier de
configuration (slapd.conf, que nous allons renommer vieuxslapd.conf) et
du contenu de la base. Pour cela nous allons utiliser l'outil
<code>slapcat</code> qui va générer un fichier <code>ldif</code>. Ces 2 fichiers seront à
transférer sur le nouveau serveur. Si vous utilisez des schémas
spécifique, il faudra également les récupérer.</p>
<pre class="code">[aldevar@vieuxserveur]# slapcat -f /chemin/vers/vieuwslapd.conf -l /tmp/vieuxslap.ldif</pre>
<p>Sur notre nouvelle machine CentOS 7, à jour, on installe
openldap-servers et openldap-clients</p>
<pre>[aldevar@serveur]# yum -y install openldap-servers openldap-clients</pre>
<p>Configuration des logs d'OpenLDAP</p>
<pre>[aldevar@serveur]# echo "local4.* /var/log/slapd.log" > /etc/rsyslog.d/slapd.conf
[aldevar@serveur]# systemctl restart rsyslog.service</pre>
<p>Dans notre cas, il était nécessaire de nettoyer l'ancien fichier de
configuration.
| Pour vérifier si que le fichier de conf est valide, on utilise
<code>slaptest</code></p>
<pre>[aldevar@serveur]# slaptest -f vieuxslapd.conf</pre>
<p>Celui ci nous retourne des erreurs que nous corrigeons.</p>
<pre>[aldevar@serveur]# sed -i -e "s/attr=/attrs=/g" vieuxslapd.conf
[aldevar@serveur]# sed -i -e "/pidfile/d" /root/vieuxslapd.conf
[aldevar@serveur]# sed -i -e "/argsfile/d" /root/vieuxslapd.conf
[aldevar@serveur]# sed -i -e "s;directory /var/ldap/annuaireldap;directory /var/lib/ldap;" /root/vieuxslapd.conf</pre>
<p>Nous utilisons le schéma de samba, pour le récupérer nous installons
samba</p>
<pre>[aldevar@serveur]# yum -y install samba</pre>
<p>On copie les fichiers schéma récupérés sur l'ancien serveur dans le bon
répertoire :</p>
<pre>[aldevar@serveur]# cp *.schema /etc/openldap/schema/
[aldevar@serveur]# chown ldap. /etc/openldap/schema/*</pre>
<p>Maintenant, nous allons corriger une incompatibilité sur laquelle nous
avons bloqué un bon moment. OpenLDAP ajoute pour chaque entrée un
attribut <code>entryUUID</code> qu'il provisionne automatiquement. Entre la
version 2.2 et notre version 2.4, la format de la valeur
d'<code>entryUUID</code> a changé. Il est passé d'une suite de caractères
aléatoire à 4 série de caractères hexadécimaux séparés par des <code>-</code>.
Tant que nous n'avions pas trouver de solution à cette incompatibilité,
aucune entrée de ne pouvait être ajoutée dans notre nouvelle base. C'est
d’ailleurs la raison pour laquelle nous ne pouvions pas mettre en place
de synchronisation entre les 2 instances.</p>
<p>La solution, radicale et rapide est de supprimer les entrées
<code>entryUUID</code></p>
<pre>[aldevar@serveur]# sed -i -e "/entryUUID/d" vieuxslap.ldif</pre>
<p>Une fois ces étapes effectuée, nous devrions être prêt pour tester
l'import des données. Pour cela, nous utilisons l'outil <code>slapadd</code> qui
à l'avantage de pouvoir travailler sans daemon ldap actif. En lui
fournissant le fichier de configuration il est capable d'écrire
directement dans les fichiers de la base. Dans un premier temps, nous le
lançons avec l'option <code>-u</code> afin de le lancer en mode <code>dry-run</code>.</p>
<pre>[aldevar@serveur]# slapadd -f vieuxslapd.conf -c -u -o schema-check=yes -l vieuxslap.ldif</pre>
<p>Si cette commande ne sort pas d'erreurs, on peut la faire en réelle.</p>
<pre>[aldevar@serveur]# slapadd -f vieuxslapd.conf -c -o schema-check=yes -l vieuxslap.ldif</pre>
<p>A partir de là, on dispose d'une base ldap fonctionnelle et si on lance
la daemon slapd en lui fournissant le fichier de configuration, tout
devrait fonctionner.</p>
<pre>[aldevar@serveur]# slapd -u ldap -f vieuxslapd.conf</pre>
<p>Mais, comme je l'ai dit plus haut, la bonne pratique est plutôt de
stocker la configuration en base olc. Cette base se trouve dans
<code>/etc/openldap/slapd.d</code> et contient déjà de quoi faire fonctionner un
slapd basique mais vide. L'utilitaire <code>slaptest</code> que nous avons
utilisé pour vérifier le fichier de configuration est également utilisé
pour faire cette migration. En lui fournissant d'un coté le fichier de
configuration et de l'autre le dossier de destination, il va transformer
le contenu du fichier en instructions ldif.</p>
<p>Avant tout, on supprime le contenu actuel du répertoire.</p>
<pre>[aldevar@serveur]# rm -Rf /etc/openldap/slapd.d/*</pre>
<p>On lance la migration de la configuration</p>
<pre>[aldevar@serveur]# slaptest -f vieuxslapd.conf -F /etc/openldap/slapd.d/</pre>
<p>0n corrige les droits pour que le daemon puisse travailler</p>
<pre>[aldevar@serveur]# chown -R ldap. /etc/openldap/slapd.d/</pre>
<p>Enfin, on importe le fichier <code>DB_CONFIG</code> afin d'avoir des performances
normales sur la base</p>
<pre>[aldevar@serveur]# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
[aldevar@serveur]# chown ldap. /var/lib/ldap/DB_CONFIG</pre>
<p>Pour finir, on peut démarrer le daemon</p>
<pre>[aldevar@serveur]# systemctl start slapd
[aldevar@serveur]# systemctl enable slapd</pre>
Debian abandonne la Linux Standard Base2015-10-20T21:56:00+02:002015-10-20T21:56:00+02:00Aldevartag:blog.devarieux.net,2015-10-20:/2015/10/debian-abandonne-la-linux-standard-base.html<p><a href="https://lwn.net/Articles/658809/">LWN a annoncé</a> il y a déjà
quelques jours que la communauté Debian abandonnait le support de la
<a href="http://refspecs.linuxfoundation.org/lsb.shtml">Linux Standard Base</a>
(LSB). La LSB tente de se définir comme un standard de compatibilité des
différentes distributions. En suivant ces règles, chaque binaire devrait
simplement fonctionner sur chaque distribution, que ce …</p><p><a href="https://lwn.net/Articles/658809/">LWN a annoncé</a> il y a déjà
quelques jours que la communauté Debian abandonnait le support de la
<a href="http://refspecs.linuxfoundation.org/lsb.shtml">Linux Standard Base</a>
(LSB). La LSB tente de se définir comme un standard de compatibilité des
différentes distributions. En suivant ces règles, chaque binaire devrait
simplement fonctionner sur chaque distribution, que ce soit Debian, RHEL
ou SLES.</p>
<p>Difficile d'en vouloir aux mainteneurs Debian. La LSB est très vaste et
<a href="https://www.linuxbase.org/lsb-cert/productdir.php?by_lsb">très peu
d'applications</a>ont
reçu la certification LSB. Ajoutez à cela que le gestionnaire de paquet
RPM est celui qui a été choisi et vous avez un standard dont les specs
vont à l'encontre de ce que propose Debian.</p>
<p>Le fait que Debian stoppe les efforts pour rester compatible avec LSB ne
signifie pas forcement qu'elle va devenir incompatible avec les autres
distributions. Debian prévoie de rester compatible avec le standard de
hiérarchie des systèmes de fichiers (<a href="http://www.linuxfoundation.org/collaborate/workgroups/lsb/fhs">Filesystem Hierarchy
Standard</a>),
un des éléments de LSB qui défini où doivent se trouver certains
fichiers et répertoires. C'est en effet un des standard majeur pour
conserver un semblant de compatibilité entre distributions.</p>
<p>Sur le court terme, cela ressemble à un non événement. A plus long
terme, on peut se demander ce qu'il va advenir de l'écosystème Linux.
Créer une distribution et la maintenir est déjà une tâche
particulièrement difficile.Imaginez alors ce que cela doit être de
coordonner des standards a travers plusieurs distributions ...</p>
<p>Parmi les distributions majeures, nous avons typiquement 2 camps:
Debian/Ubuntu et Fedora/RHEL. Ces 2 camps ont réussi à ne pas trop
s'éloigner l'un de l'autre et on peut penser que systemd avait commencé
ce processus de coordination. Les normes sont importantes, mais
seulement dans la mesure où elles sont respectées. Jusqu'ici GNU/Linux a
évité le problème <a href="https://xkcd.com/927/">des normes concurrentes</a>.</p>
<p>Cela va-t-il rester le cas?</p>
Scripter, programmer2015-09-25T07:14:00+02:002015-09-25T07:14:00+02:00Aldevartag:blog.devarieux.net,2015-09-25:/2015/09/scripter-programmer.html<p>Il y a quelques mois, <a href="https://twitter.com/_Desmoden">Jon Hudson</a>,
ingénieur réseau chez Brocade, a présenté un discours très intéressant
au <a href="http://techfieldday.com/event/nfd9">Network Field Day 9</a> sur le
sujet de la programmabilité en réseau.</p>
<p>Durant la conversation (qui vaut vraiment le coup d'être vu), une
question de John Herbert de
<a href="http://movingpackets.net/">MovingPackets.net</a> a été …</p><p>Il y a quelques mois, <a href="https://twitter.com/_Desmoden">Jon Hudson</a>,
ingénieur réseau chez Brocade, a présenté un discours très intéressant
au <a href="http://techfieldday.com/event/nfd9">Network Field Day 9</a> sur le
sujet de la programmabilité en réseau.</p>
<p>Durant la conversation (qui vaut vraiment le coup d'être vu), une
question de John Herbert de
<a href="http://movingpackets.net/">MovingPackets.net</a> a été posée : "<em>Les
ingénieurs réseaux deviendront-ils des programmeurs?</em>". La réponse de
Jon Hudson a suscité les applaudissements de l'audience :</p>
<blockquote>
<p>"Le problème que j'ai avec cette affirmation est que la majorité des
ingénieurs réseaux que je connais, moi y compris, savent comment
coder. Nous avons fait des études dans ce domaine et nous avons
choisi de ne pas le faire." – Jon Hudson</p>
<p>“The trouble I have with that statement is, most network engineers I
know, like myself, we know how to code. We went to school for it,
and we chose not to.” – Jon Hudson</p>
</blockquote>
<p>Il ne faut pas oublier en effet qu'il y a une différence fondamentale
entre scripter, écrire des outils d'administration et programmer.</p>
<p>Le script, c'est le petit programme qu'on écrit à l'école pour
s’entraîner. <em>"Calculer les années bissextile pour les 300 prochaines
années"</em>, ou <em>"Parcourir les lignes de ce fichier et effectuer X
traitements sur cette ligne"</em>. C'est fun, souvent pratique, mentalement
stimulant et facile à réutiliser. Il résout un problème spécifique et
peu facilement être dupliqué ou modifié pour résoudre un autre problème.
Par contre la plupart de ces scripts sont fragiles, peu efficaces et
souvent non sécurisés.</p>
<p>Je ne suis pas du tout développeur mais du peu que je sache, écrire un
programme, pour moi, ça ressemble à: <em>"La fonction recevra en entrée un
pointeur vers un vecteur contenant une valeur qui doit être validée par
rapport au contenu du dictionnaire. Chaque exception durant l’exécution
de la routine doit être gérée. La fonction doit retourner un pointeur à
la fonction appelante qui va référencer un nouveau vecteur contenant la
valeur calculée de l'espace de nom de la fonction appelée. Documenter le
code en détail et démontrer que le code rédigé s’exécute en utilisant le
moins de demande d'allocation mémoire."</em></p>
<p>Ce que je viens d'écrire est sans doute un ramassis de n'importe quoi
mais c'est environ a ce niveau là que je décroche de la programmation et
que mon intérêt pour cette compétence se réduit à peau de chagrin. Il me
semble que le scripting et la programmation sont 2 choses bien
différentes que certaines personnes ont tendance à mélanger.</p>
<p>Ainsi, quand on nous assène qu'en tant que sysadmin ou ingé / technicien
réseau on DOIT savoir coder, je suis plutôt d'accord, surtout à l'heure
du Software Define Network, Software Define Storage ou plus globalement
du Software Define Datacenter et de l'hyperconvergence des
infrastructures. On pourra toujours tout faire à la main, que ce soit en
ligne de commande ou via une GUI, mais quand on travail dans un système
distribué possédant des APIs, il est bien plus facile d'utiliser un
script (qui a dit Python?) ou des outils comme Puppet/Ansible/Salt.
Attention cependant à la sémantique. Coder (écrire du code) ce n'est pas
la même chose que programmer (écrire un programme).</p>
<p>Il est important, quand on travail dans l'IT, de savoir scripter. Il y a
plein de tâches répétitives, ennuyeuses qu'on souhaite automatiser au
maximum. Il y aussi plein d'autres tâches plus rapide à faire à la main
et parfois difficile à automatiser. Pour résumer, construisez votre
script quand celui ci vous permet de faire votre tâche plus vite, mieux
et moins cher tout en évitant que le code soit instaurer comme nouvelle
religion de l'IT. Si vous avez besoin d'une scie, utilisez une scie. Si
vous avez besoin d'une scie sauteuse pour mieux scier, construisez votre
scie sauteuse mais faite attention de ne pas devenir un constructeur de
scie sauteuse qui a oublié comment scier.</p>
GNS3 - Créer son premier Lab2015-08-26T10:03:00+02:002015-08-26T10:03:00+02:00Aldevartag:blog.devarieux.net,2015-08-26:/2015/08/gns3-creer-son-premier-lab.html<section id="premier-lancement">
<h2>Premier Lancement</h2>
<p>Après avoir installé GNS3 et ses différents modules dans <a href="https://blog.devarieux.net/2015/08/prise-en-main-de-gns3-pour-la-simulation-reseau.html">un précédent
article</a>,
nous allons maintenant voir comment créer un Lab et faire un petit
exercice simple de configuration de routes statiques. La première chose
est d'ajouter un nouveau routeur dans la configuration de GNS3. Ici, ce
sera un …</p></section><section id="premier-lancement">
<h2>Premier Lancement</h2>
<p>Après avoir installé GNS3 et ses différents modules dans <a href="https://blog.devarieux.net/2015/08/prise-en-main-de-gns3-pour-la-simulation-reseau.html">un précédent
article</a>,
nous allons maintenant voir comment créer un Lab et faire un petit
exercice simple de configuration de routes statiques. La première chose
est d'ajouter un nouveau routeur dans la configuration de GNS3. Ici, ce
sera un c2691, qui est un vieux routeur possédant 4 emplacements. Si
vous me demandez gentiment, je peux peut-être vous fournir l'image IOS
pour ce modèle.</p>
<p>Au premier lancement de GNS3, il vous est proposé de créer un projet, ce
que nous allons faire tout de suite en enregistrant ce projet sous le
nom FirstLab.</p>
<div class="m-image">
<a href="/images/2015-08-25-21_47_47-Prise-en-main-de-GNS3-pour-la-simulation-réseau-À-La-Benne-Nightly.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_47_47-Prise-en-main-de-GNS3-pour-la-simulation-réseau-À-La-Benne-Nightly.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_48_59-New-project.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_48_59-New-project.png" /></a>
</div>
<p>Une fois le projet créé, on va ajouter un routeur dans la configuration de GNS3.
Pour cela, on se rend dans Edit > Preferences.</p>
<div class="m-image">
<a href="/images/2015-08-25-21_51_11-Preferences.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_51_11-Preferences.png" /></a>
</div>
<p>Je vous laisse parcourir les options afin que vous puissiez comprendre un peu mieux le logiciel. Si vous avez des VM VirtualBox, GNS3 les trouvera et vous les listera dans le menu VirtualBox.</p>
<div class="m-image">
<a href="/images/2015-08-25-22_00_01-Preferences.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_00_01-Preferences.png" /></a>
</div>
</section>
<section id="ajout-d-un-routeur">
<h2>Ajout d'un routeur</h2>
<p>Pour ajouter un routeur Cisco, on se rend dans Dynamips > IOS Router et
on clique sur New. Il suffit ensuite de suivre les indications et de
fournir l'image IOS du routeur qu'on souhaite voir apparaître.</p>
<div class="m-image">
<a href="/images/2015-08-25-21_55_51-Preferences.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_55_51-Preferences.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_56_47-New-IOS-router-template.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_56_47-New-IOS-router-template.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_57_08-New-IOS-router-c2691-jk9s-mz.123-17.image_.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_57_08-New-IOS-router-c2691-jk9s-mz.123-17.image_.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_57_22-New-IOS-router-c2691-jk9s-mz.123-17.image_.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_57_22-New-IOS-router-c2691-jk9s-mz.123-17.image_.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_58_01-New-IOS-router-c2691-jk9s-mz.123-17.image_.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_58_01-New-IOS-router-c2691-jk9s-mz.123-17.image_.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-25-21_59_26-New-IOS-router-c2691-jk9s-mz.123-17.image_.png|"><img src="https://blog.devarieux.net/images/2015-08-25-21_59_26-New-IOS-router-c2691-jk9s-mz.123-17.image_.png" /></a>
</div>
<p>Pour la valeur de Idle-PC, ne recopiez pas bêtement ce qui est écrit dans cette fenêtre. Ce chiffre correspond seulement à ma machine. Cliquez sur le bouton Idle-Pc finder et GNS3 trouvera la valeur de lui même. Cela peut prendre un peu de temps à calculer.</p>
<div class="m-image">
<a href="/images/2015-08-25-21_59_40-Preferences.png"><img src="https://blog.devarieux.net/images/2015-08-25-21_59_40-Preferences.png" /></a>
</div>
<p>Voilà, nous avons notrevrouteur c2691. On peut maintenant fermer la fenêtre de configuration et commencer notre projet.</p>
</section>
<section id="le-lab">
<h2>Le Lab</h2>
<p>Nous allons mettre en place un Lab très basique de routage statique
entre 2 routeurs. Un premier routeur situé à Rennes aura une interface
Loopback ayant pour IP 2.2.2.2/24, et un second routeur à Paris aura une
interface Loopback ayant 1.1.1.1/24 pour IP.</p>
<p>Sur chacun de ces 2 routeurs, nous allons ajouter une carte ayant 4
ports séries. Nous utiliserons 2 de ces ports. Le port Serial1/0 de
Rennes sera branché au port Serial1/0 de Paris et le port Serial1/1 de
Rennes sera branché sur le port Serial1/1 de Paris.</p>
<p>Les configurations IP seront les suivantes :</p>
<ul>
<li>Rennes Serial1/0 : 192.168.1.1/24</li>
<li>Rennes Serial1/1 : 192.168.2.1/24</li>
<li>Paris Serial1/0 : 192.168.1.2/24</li>
<li>Paris Serial1/1 : 192.168.2.2/24</li>
</ul>
<p>Et pour rappel, les interfaces Loopback</p>
<ul>
<li>Rennes Loopback0 : 2.2.2.2/24</li>
<li>Paris Loopback0 : 1.1.1.1/24</li>
</ul>
<p>Une fois tout cela mis en place, le but sera de réussir à pinger l'IP
1.1.1.1 depuis Rennes et pinger l'IP 2.2.2.2 depuis Paris en mettant en
place des routes statiques.</p>
<p>Pour la mise en place du Lab, suivez le guide...</p>
<p>Cliquez sur <em>Browse Routers</em> dans la colonne de gauche puis glissez 2
fois le routeur c2691 dans le projet. Sur le routeur R1, faites un
clique droit : <em>Configure</em></p>
<div class="m-image">
<a href="/images/2015-08-25-22_02_55-FirstLab.gns3_-—-GNS3.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_02_55-FirstLab.gns3_-—-GNS3.png" /></a>
</div>
<p>Renommez le en <strong>Rennes</strong> et dans l'onglet <em>slot</em>, ajoutez lui une carte NM-4T dans le
Slot 1. Faites de même pour le routeur R2 en le renommant <strong>Paris</strong>.</p>
<div class="m-image">
<a href="/images/2015-08-25-22_05_43-Node-configurator.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_05_43-Node-configurator.png" /></a>
</div>
<p>Une fois de retour sur le
projet, cliquez sur '<em>Add a Link'</em> dans la colonne de gauche et créer 2
liens séries en cliquant dans un premier temps sur <em>Rennes > Serial 1/0</em>
puis <em>Paris > Serial 1/0</em> pour le premier lien et <em>Rennes > Serial 1/1</em>
puis <em>Paris > Serial 1/1</em> pour le second lien.</p>
<div class="m-image">
<a href="/images/2015-08-25-22_07_19-FirstLab.gns3_-—-GNS3.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_07_19-FirstLab.gns3_-—-GNS3.png" /></a>
</div>
<p>Vous devriez avoir quelque chose qui ressemble à ça :</p>
<div class="m-image">
<a href="/images/2015-08-25-22_11_04-FirstLab.gns3_-—-GNS3.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_11_04-FirstLab.gns3_-—-GNS3.png" /></a>
</div>
<p>J'ai moi même ajouté les
notes sur les réseaux grâce aux notes que l'on peut insérer dans le
projet.</p>
<p>Une fois que c'est terminé, cliquez sur le Play vert qui se trouve en
haut de l'interface afin de démarrer les routeurs.</p>
<p>Nous allons enfin pouvoir ouvrir notre première console Cisco. Pour
cela, clique droit sur un routeur > <em>Console</em></p>
<div class="m-image">
<a href="/images/2015-08-25-22_19_50-FirstLab.gns3-—-GNS3.png"><img src="https://blog.devarieux.net/images/2015-08-25-22_19_50-FirstLab.gns3-—-GNS3.png" /></a>
</div>
<p>Pour préparer le lab, voici les
commandes à taper dans la console de Rennes :</p>
<p>IOS supporte la tabulation et les raccourcis. Par exemple, pour taper
<code>configure terminal</code>, je peux taper <code>conf<tab> t<tab></code> ou tout
simplement <code>conf t</code></p>
<pre>Rennes#enable //active le mode privilège
Rennes#conf t //configure terminal
Rennes(config)#int loopback0 //configurer l'interface Loopback0
Rennes(config-ig)#ip add 2.2.2.2 255.255.255.0
Rennes(config-if)#no shut //monter l'interface (état up)
Rennes(config-if)#exit
Rennes(config)#int Serial1/0
Rennes(config-if)#ip add 192.168.1.1 255.255.255.0
Rennes(config-if)#no shut
Rennes(config-if)#exit
Rennes(config)#int Serial1/1
Rennes(config-if)#ip add 192.168.2.1 255.255.255.0
Rennes(config-if)#no shut
Rennes(config-if)#exit
Rennes(config)#</pre>
<p>Même manipulation sur le routeur de Paris :</p>
<pre>Paris#enable
Paris#conf t
Paris(config)#int loopback0
Paris(config-ig)#ip add 1.1.1.1 255.255.255.0
Paris(config-if)#no shut
Paris(config-if)#exit
Paris(config)#int Serial1/0
Paris(config-if)#ip add 192.168.1.2 255.255.255.0
Paris(config-if)#no shut
Paris(config-if)#exit
Paris(config)#int Serial1/1
Paris(config-if)#ip add 192.168.2.2 255.255.255.0
Paris(config-if)#no shut
Paris(config-if)#exit
Paris(config)#</pre>
<p>Afin de voir l'état de vos interfaces, vous pouvez taper la commande
suivantes : <code>do show ip int brief</code></p>
<pre>Rennes(config)#do show ip int brief
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 unassigned YES unset administratively down down
FastEthernet0/1 unassigned YES unset administratively down down
Serial1/0 192.168.1.1 YES manual up up
Serial1/1 192.168.2.1 YES manual up up
Serial1/2 unassigned YES unset administratively down down
Serial1/3 unassigned YES unset administratively down down
Loopback0 2.2.2.2 YES manual up up</pre>
<p>Arriver ici, le but est de pinger l'interface Loopback de Rennes depuis
Paris en passant par le réseau 192.168.1.0 et l'interface Loopback de
Paris depuis Rennes en passant par le réseau 192.168.2.0.</p>
<p>Pour arriver à cet objectif, nous allons dire au routeur de Paris que
pour rejoindre le réseau 2.2.2.0/24 il doit passer par l'interface de
Rennes 192.168.1.1 qu'il connait car il est directement branché dessus.</p>
<p>De la même manière, nous allons dire au routeur de Rennes qu'il soit
passer par l'interface 192.168.2.2 de Paris pour joindre le réseau
1.1.1.0/24.</p>
<p>Voici donc les commandes à taper en console</p>
<pre>Paris(config)#ip route 2.2.2.0 255.255.255.0 192.168.1.1
Paris(config)#do ping 2.2.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 2.2.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 112/243/288 ms
Paris(config)#</pre>
<p>Le ping fonctionne!!</p>
<p>Depuis Rennes</p>
<pre>Rennes(config)#ip route 1.1.1.0 255.255.255.0 192.168.2.2
Rennes(config)#do ping 1.1.1.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 1.1.1.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 128/136/148 ms
Rennes(config)#do show ip route //pour voir les routes statiques
Codes: C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route
Gateway of last resort is not set
1.0.0.0/24 is subnetted, 1 subnets
S 1.1.1.0 [1/0] via 192.168.2.2
2.0.0.0/24 is subnetted, 1 subnets
C 2.2.2.0 is directly connected, Loopback0
C 192.168.1.0/24 is directly connected, Serial1/0
C 192.168.2.0/24 is directly connected, Serial1/1</pre>
<p>Voilà pour la prise en main de GNS3 et la configuration basique de 2
routeurs. Vous n'avez plus qu'à créer vos propres labs, ajouter des VM
et tenter de les faire communiquer par exemple.</p>
<p>Je vous proposerais peut être moi même de nouveaux labs d'ici quelques
temps</p>
</section>
Firefox comme navigateur par défaut de SailfishOS2015-08-24T09:17:00+02:002015-08-24T09:17:00+02:00Aldevartag:blog.devarieux.net,2015-08-24:/2015/08/firefox-comme-navigateur-par-defaut-de-sailfishos.html<p>Jolla et son SailfishOS sont vraiment de beaux outils mais il faut
avouer qu'ils ont quand même un problème majeur, c'est la piètre qualité
des navigateurs intégrés et surtout du navigateur par défaut.</p>
<p>Malheureusement, l'interface ne propose actuellement aucune option pour
modifier ce comportement. Ainsi, lorsqu'on clique sur un lien …</p><p>Jolla et son SailfishOS sont vraiment de beaux outils mais il faut
avouer qu'ils ont quand même un problème majeur, c'est la piètre qualité
des navigateurs intégrés et surtout du navigateur par défaut.</p>
<p>Malheureusement, l'interface ne propose actuellement aucune option pour
modifier ce comportement. Ainsi, lorsqu'on clique sur un lien dans une
autre application c'est forcement ce navigateur tout moisi qui s'ouvre
et qui met 3 heures à charger la page. Heureusement, avec quelques
bidouille, il est possible de paramétrer Firefox comme navigateur par
défaut, c'est d'ailleurs ce que je viens de faire :)</p>
<p>Si vous avez déjà Firefox d'installé, vous pouvez directement vous
rendre au paragraphe 'Paramétrage d'ADB'.</p>
<section id="installation-d-aptoide">
<h2>Installation d'Aptoide</h2>
<p>La première étape est d'installer le market Aptoide si ce n'est pas déjà
fait. Pour cela, il faut se rendre dans la Boutique Jolla, puis dans
'Place de marché' tout en bas et installer le market Aptoide Appstore</p>
</section>
<section id="installation-de-firefox">
<h2>Installation de Firefox</h2>
<p>L'installation de Firefox se fait via Aptoide, il faut donc ouvrir
l'application nouvellement installée et dans la zone de recherche, taper
Firefox. Il faut ensuite trouver l'application <strong>Firefox Browser for
Android</strong> et l'installer.</p>
</section>
<section id="parametrage-d-adb">
<h2>Paramétrage d'ADB</h2>
<p>C'est partie pour le bricolage. Il faut d'abord <a href="http://blog.devarieux.net/2015/03/se-connecter-en-ssh-a-son-jolla/">se connecter en
SSH</a>
à l'appareil afin d'y modifier le comportement d'Alien. Pour cela, il
faut éditer le fichier /opt/alien/system/build.prop et ajouter à la fin
:</p>
<pre>persist.service.adb.enable=1
service.adb.tcp.port=5555</pre>
<p>Une fois cette modification faite, on relance Alien Dalvik</p>
<pre>[root@Jolla ~]# systemctl restart aliendalvik.service</pre>
<p>Maintenant, un process adb doit apparaitre</p>
<pre>[root@Jolla ~]# ps aux | grep adb
shell 5162 0.0 0.0 6532 92 ? Ssl 23:04 0:00 /system/root/sbin/adbd
root 5592 0.0 0.0 3984 288 pts/0 Sl 23:06 0:00 adb fork-server server
root 7330 0.0 0.0 2256 544 pts/0 S+ 23:57 0:00 grep adb</pre>
<pre>[root@Jolla ~]# lsof -p 5162 | grep android_adb
adbd 5162 shell 10u CHR 10,25 0t0 1437 /opt/alien/dev/android_adb</pre>
<p>Une fois que tout ça est ok, on lance en root :</p>
<pre>[root@localhost bin]# /opt/alien/system/bin/adb kill-server
[root@localhost bin]# /opt/alien/system/bin/adb devices
* daemon not running. starting it now on port 5038 *
* daemon started successfully *
List of devices attached
emulator-5554 device
[root@localhost bin]#</pre>
</section>
<section id="parametrage-de-sailfishos">
<h2>Paramétrage de SailfishOS</h2>
<p>La système est maintenant prêt à accueillir nos modifications. Toujours
dans la connexion SSH, se rendre dans /usr/share/applications, faire une
copie de sauvegarde du fichier open-url.desktop et le modifier pour
qu'il ne prenne plus en charge les types MIME http et https</p>
<pre>cd /usr/share/applications
cp -a open-url.desktop open-url.desktop.ori
vi open-url.desktop</pre>
<p>Une fois dans le fichier, on supprime la ligne</p>
<pre class="code">MimeType=text/html;x-maemo-urischeme/http;x-maemo-urischeme/https;</pre>
<p>Le fichier doit maintenant ressembler à cela</p>
<pre>[root@Jolla applications]# cat open-url.desktop
[Desktop Entry]
Type=Application
Name=Browser
NotShowIn=X-MeeGo;
X-MeeGo-Logical-Id=sailfish-browser-ap-name
X-MeeGo-Translation-Catalog=sailfish-browser
X-Maemo-Service=org.sailfishos.browser
X-Maemo-Method=org.sailfishos.browser.openUrl</pre>
<p>Créer ensuite le fichier firefox-as-default.desktop et y mettre ce
contenu</p>
<pre>[Desktop Entry]
Type=Application
Name=Browser
NotShowIn=X-MeeGo;
X-MeeGo-Logical-Id=sailfish-browser-ap-name
X-MeeGo-Translation-Catalog=sailfish-browser
X-Maemo-Service=org.sailfishos.browser
X-Maemo-Method=org.sailfishos.browser.openUrl
[root@Jolla applications]# cat firefox-as-default.desktop
[Desktop Entry]
Exec=/opt/alien/system/bin/adb -e shell am start -a android.intent.action.VIEW -n org.mozilla.firefox/.App -d ' %U'
Name=Firefox HTTP handler (opener)
Type=Application
MimeType=text/html;x-maemo-urischeme/http;x-maemo-urischeme/https;
X-Nemo-Application-Type=no-invoker
X-Nemo-Single-Instance=no
X-apkd-apkfile=/data/app/org.mozilla.firefox.apk
NoDisplay=true</pre>
<p>Afin de prendre ces modifications en compte, on met à jour le cache des
types MIME</p>
<pre>[root@Jolla applications]# update-desktop-database</pre>
<p>Le fichier mimeinfo.cache devrait maintenant contenir 2 lignes de ce
type</p>
<pre>x-maemo-urischeme/http=firefox-as-default.desktop;
x-maemo-urischeme/https=firefox-as-default.desktop;</pre>
<p>Dorénavant, lorsqu'un lien sera cliqué dans une application (message,
twitter...) celui s'ouvrir avec Firefox.</p>
</section>
Vmware Client Integration Plugin HS dans Firefox2015-08-23T14:00:00+02:002015-08-23T14:00:00+02:00Aldevartag:blog.devarieux.net,2015-08-23:/2015/08/vmware-client-integration-plugin-hs-dans-firefox.html<p>Depuis quelques semaines, le plugin d'intégration client VMware ne
fonctionne plus dans Firefox. La case "Utiliser les identifiants
Windows" est grisée et d'après l'interface de vCenter, le plugin n'est
pas installé sur votre machine.</p>
<p>Ce problème est apparu avec Firefox 39 et concerne toutes les nouvelles
versions de Firefox depuis …</p><p>Depuis quelques semaines, le plugin d'intégration client VMware ne
fonctionne plus dans Firefox. La case "Utiliser les identifiants
Windows" est grisée et d'après l'interface de vCenter, le plugin n'est
pas installé sur votre machine.</p>
<p>Ce problème est apparu avec Firefox 39 et concerne toutes les nouvelles
versions de Firefox depuis. Cela a plusieurs conséquences.</p>
<ul>
<li>Impossible d'ouvrir les consoles des VM (la console HTML5, VMRC
fonctionne quant à lui)</li>
<li>Impossible de déposer un fichier depuis son PC vers un Datastore via
le navigateur HTML5</li>
<li>Impossible de déployer un template OVF depuis son PC via l'option de
déploiement de fichier OVF local.</li>
</ul>
<p>Pour corriger ce problème, il faut désactiver les options
security.ssl3.dhe de Firefox.</p>
<p>Pour cela, se rendre dans <a class="m-link-wrap" href="about:config">about:config</a>, rechercher security.ssl3.dhe.
Vous devriez vous retrouver avec 2 entrées :</p>
<ul>
<li>security.ssl3.dhe_rsa_aes_128_sha</li>
<li>security.ssl3.dhe_rsa_aes_256_sha</li>
</ul>
<p>Faire un clique droit sur chacune de ses entrées et cliquer sur
<strong>Inverser</strong> (Toggle).</p>
<p>Il ne reste plus qu'à rafraîchir la page vcenter.</p>
<p>Source <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2125623">Vmware KB
2125623</a></p>
Comprendre la prédiction de noms des interfaces réseau de systemd2015-08-22T23:58:00+02:002015-08-22T23:58:00+02:00Aldevartag:blog.devarieux.net,2015-08-22:/2015/08/comprendre-la-prediction-de-noms-des-interfaces-reseau-de-systemd.html<p><em>Cet article est une traduction d'`un article
original <https://major.io/2015/08/21/understanding-systemds-predictable-network-device-names/>`__
de Major Hayden, publié `sur son blog <https://major.io/>`__ le 21 Aout
2015. Article traduit avec son aimable autorisation.</em></p>
<p>J'ai un peu parlé des nom des interfaces réseau de systemd dans …</p><p><em>Cet article est une traduction d'`un article
original <https://major.io/2015/08/21/understanding-systemds-predictable-network-device-names/>`__
de Major Hayden, publié `sur son blog <https://major.io/>`__ le 21 Aout
2015. Article traduit avec son aimable autorisation.</em></p>
<p>J'ai un peu parlé des nom des interfaces réseau de systemd dans un de
mes premiers post sur <a href="https://major.io/2015/08/21/using-systemd-networkd-with-bonding-on-rackspaces-onmetal-servers/">systemd-networkd et le
bonding</a>.
J'avais alors eu quelques questions sur la manière dont systemd
détermine le nom final des interfaces réseau. La prédictibilité de ces
noms m'a <a href="https://major.io/2014/08/06/unexpected-predictable-network-naming-systemd/">pris de court l'été
dernier</a>
quand je n'ai pas pu comprendre comment ces noms étaient construits.
| Observons donc ce processus</p>
<section id="que-contient-le-nom">
<h2>Que contient le nom?</h2>
<p>Dans l'article sur le bonding avec systemd-networkd, j'avais utilisé une
carte réseau Intel dual port montée sur un port hotplug</p>
<pre># udevadm info -e | grep -A 9 ^P.*eth0
P: /devices/pci0000:00/0000:00:03.2/0000:08:00.0/net/eth0
E: DEVPATH=/devices/pci0000:00/0000:00:03.2/0000:08:00.0/net/eth0
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet OCP Server Adapter X520-2)
E: ID_MODEL_ID=0x10fb
E: ID_NET_DRIVER=ixgbe
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME_MAC=enxa0369f2cec90
E: ID_NET_NAME_PATH=enp8s0f0
E: ID_NET_NAME_SLOT=ens9f0</pre>
<p>Dans ce dump de la base de donnée udev, on voit que l'interface réseau
possède plusieurs noms</p>
<ul>
<li>ID_NET_NAME_MAC=enxa0369f2cec90</li>
<li>ID_NET_NAME_PATH=enp8s0f0</li>
<li>ID_NET_NAME_SLOT=ens9f0</li>
</ul>
<p>D'où viennent ces noms? Nous pouvons nous plonger dans la code source de
systemd pour comprendre l'origine de ces noms et lequel est sélectionné
au final.</p>
</section>
<section id="descendre-dans-le-terrier-de-udev">
<h2>Descendre dans le terrier de udev</h2>
<p>Voici un extrait du fichier
<a href="https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c">src/udev/udev-builtin-net_id.c</a>:</p>
<pre class="code c"><span class="cm">/*
* Predictable network interface device names based on:
* - firmware/bios-provided index numbers for on-board devices
* - firmware-provided pci-express hotplug slot index number
* - physical/geographical location of the hardware
* - the interface's MAC address
*
* http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
*
* Two character prefixes based on the type of interface:
* en -- ethernet
* sl -- serial line IP (slip)
* wl -- wlan
* ww -- wwan
*
* Type of names:
* b<number> -- BCMA bus core number
* ccw<name> -- CCW bus group name
* o<index>[d<dev_port>] -- on-board device index number
* s<slot>[f<function>][d<dev_port>] -- hotplug slot index number
* x<MAC> -- MAC address
* [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>]
* -- PCI geographical location
* [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
* -- USB port number chain</span></pre>
<p>Voici donc la manière dont sont nommées nos interfaces. Les cartes
Ethernet commenceront toujours par <em>en</em>, elles peuvent ensuite être
suivie d'un <em>p</em> (pour port PCI), un <em>s</em> (pour port PCI-E), un <em>o</em> (pour
carte interne (onboard)). En descendant un peu dans le fichier, on
trouve des exemples à partir de la ligne 56.</p>
</section>
<section id="de-vrais-exemples">
<h2>De vrais exemples</h2>
<p>Nous avons vu plus haut le nommage des interfaces PCI-E sur un serveur
OnMetal de chez Rackspace. Elles étaient nommées <em>ens9f0</em> et <em>ens9f1</em>.
Cela signifie qu'elles sont sur un port PCI-E qui se trouve être le port
numéro 9. Les indexes sont à 0 et 1 (pour les 2 ports Ethernet sur
l'Intel 82599ES).</p>
<section id="firewall-linux-avec-une-carte-pci-dual-port">
<h3>Firewall Linux avec une carte PCI dual-port.</h3>
<p>Voici un exemple avec mon firewall Linux personnel. C'est un Dell
Optiplex 3020 avec une carte Intel I350-T2(dual-port):</p>
<pre># udevadm info -e | grep -A 10 ^P.*enp1s0f1
P: /devices/pci0000:00/0000:00:01.0/0000:01:00.1/net/enp1s0f1
E: DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/net/enp1s0f1
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2)
E: ID_MODEL_ID=0x1521
E: ID_NET_DRIVER=igb
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME=enp1s0f1
E: ID_NET_NAME_MAC=enxa0369f6e5227
E: ID_NET_NAME_PATH=enp1s0f1
E: ID_OUI_FROM_DATABASE=Intel Corporate</pre>
<p>L'affichage de lspci:</p>
<pre># lspci -s 01:00
01:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
01:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)</pre>
<p>Cette carte est branchée sur le premier bus PCI (enp1), slot 0 (s0).
Comme c'est une carte dual-port, elle possède 2 indexes (f0 et f1). Cela
fait donc apparaître 2 noms prédictibles : <em>enp1s0f1</em> et <em>enp1s0f0</em>.</p>
</section>
<section id="serveur-1u-avec-4-ports-ethernet">
<h3>Serveur 1U avec 4 ports Ethernet.</h3>
<p>Prenons un autre exemple. Voici un serveur SuperMicro X9SCA 1U avec 4
cartes Ethernet PCI internes.</p>
<pre># udevadm info -e | grep -A 10 ^P.*enp2s0
P: /devices/pci0000:00/0000:00:1c.4/0000:02:00.0/net/enp2s0
E: DEVPATH=/devices/pci0000:00/0000:00:1c.4/0000:02:00.0/net/enp2s0
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection
E: ID_MODEL_ID=0x10d3
E: ID_NET_DRIVER=e1000e
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME=enp2s0
E: ID_NET_NAME_MAC=enx00259025963a
E: ID_NET_NAME_PATH=enp2s0
E: ID_OUI_FROM_DATABASE=Super Micro Computer, Inc.</pre>
<p>Voici les 4 cartes dans lspci</p>
<pre># for i in `seq 2 5`; do lspci -s 0${i}:; done
02:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
03:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
04:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
05:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection</pre>
<p>C'est assez intéressant car elles ne sont pas toutes sur le même bus
PCI. Elles se situent sur les bus 2 à 5 du slot 0. Il n'y a donc pas de
numéro d'index dans ce cas. Elles sont donc nommées de <em>enp2s0</em> à
<em>enp5s0</em>. Ce ne sont pas de vraies cartes internes, elles sont donc
nommées en fonction de leur localisation.</p>
</section>
<section id="serveur-de-stockage-avec-carte-ethernet-interne">
<h3>Serveur de stockage avec carte ethernet interne</h3>
<p>Voici un exemple de serveur avec une vrai carte ethernet interne
(onboard):</p>
<pre>$ udevadm info -e | grep -A 11 ^P.*eno1
P: /devices/pci0000:00/0000:00:19.0/net/eno1
E: DEVPATH=/devices/pci0000:00/0000:00:19.0/net/eno1
E: ID_BUS=pci
E: ID_MODEL_FROM_DATABASE=Ethernet Connection I217-V
E: ID_MODEL_ID=0x153b
E: ID_NET_DRIVER=e1000e
E: ID_NET_LABEL_ONBOARD=en Onboard LAN
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME_MAC=enxe03f49b159c0
E: ID_NET_NAME_ONBOARD=eno1
E: ID_NET_NAME_PATH=enp0s25
E: ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.</pre>
<p>L'affichage de lspci</p>
<pre>$ lspci -s 00:19.0
00:19.0 Ethernet controller: Intel Corporation Ethernet Connection I217-V (rev 05)</pre>
<p>Cette carte a un nouveau type de nom dans udev :
ID_NET_NAME_ONBOARD. Le code de udev pour systemd a une prise en
charge spécifique des cartes internes car elles se situent en général
sur le bus principal. Le nommage peut devenir assez laid car le 19
devrait être converti en hexadécimal dans le nom.
| Si systemd ne prenait pas en charge cette carte différemment, elle
aurait du être nommée <em>enp0s13</em> (car 19 devient 13 en hexa). Cela peut
mener à des confusions.</p>
</section>
</section>
<section id="choix-du-nom-finale">
<h2>Choix du nom finale</h2>
<p>Comme nous l'avons vu plus haut, udev contient une grande liste de nom
dans sa base. Cependant, il ne peut y avoir qu'un seul nom dans l'OS.
| Retournons dans le code. Cette fois, jetons un oeil a
<a href="https://github.com/systemd/systemd/blob/master/src/udev/net/link-config.c#L403">src/udev/net/link-config.c</a>
à partir de la ligne 403:</p>
<pre class="code c"><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">ctx</span><span class="o">-></span><span class="n">enable_name_policy</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">config</span><span class="o">-></span><span class="n">name_policy</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="n">NamePolicy</span><span class="w"> </span><span class="o">*</span><span class="n">policy</span><span class="p">;</span><span class="w">
</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">policy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">config</span><span class="o">-></span><span class="n">name_policy</span><span class="p">;</span><span class="w">
</span><span class="o">!</span><span class="n">new_name</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">*</span><span class="n">policy</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">_NAMEPOLICY_INVALID</span><span class="p">;</span><span class="w"> </span><span class="n">policy</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">policy</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_KERNEL</span><span class="p">:</span><span class="w">
</span><span class="n">respect_predictable</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_DATABASE</span><span class="p">:</span><span class="w">
</span><span class="n">new_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">udev_device_get_property_value</span><span class="p">(</span><span class="n">device</span><span class="p">,</span><span class="w"> </span><s>"ID_NET_NAME_FROM_DATABASE"</s><span class="p">);</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_ONBOARD</span><span class="p">:</span><span class="w">
</span><span class="n">new_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">udev_device_get_property_value</span><span class="p">(</span><span class="n">device</span><span class="p">,</span><span class="w"> </span><s>"ID_NET_NAME_ONBOARD"</s><span class="p">);</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_SLOT</span><span class="p">:</span><span class="w">
</span><span class="n">new_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">udev_device_get_property_value</span><span class="p">(</span><span class="n">device</span><span class="p">,</span><span class="w"> </span><s>"ID_NET_NAME_SLOT"</s><span class="p">);</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_PATH</span><span class="p">:</span><span class="w">
</span><span class="n">new_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">udev_device_get_property_value</span><span class="p">(</span><span class="n">device</span><span class="p">,</span><span class="w"> </span><s>"ID_NET_NAME_PATH"</s><span class="p">);</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="no">NAMEPOLICY_MAC</span><span class="p">:</span><span class="w">
</span><span class="n">new_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">udev_device_get_property_value</span><span class="p">(</span><span class="n">device</span><span class="p">,</span><span class="w"> </span><s>"ID_NET_NAME_MAC"</s><span class="p">);</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="k">default</span><span class="o">:</span><span class="w">
</span><span class="k">break</span><span class="p">;</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span></pre>
<p>Si on regarde le case dans son ensemble, on voit que la première
correspondance est conservée et donne le nom à l'interface. En partant
du haut vers le bas, udev prend le premier de cette liste:</p>
<ul>
<li>ID_NET_NAME_FROM_DATABASE</li>
<li>ID_NET_NAME_ONBOARD</li>
<li>ID_NET_NAME_SLOT</li>
<li>ID_NET_NAME_PATH</li>
<li>ID_NET_NAME_MAC</li>
</ul>
<p>Si on retourne sur le serveur OnMetal en haut de l'article, on peut
suivre cette logique. La base udev contient:</p>
<pre>E: ID_NET_NAME_MAC=enxa0369f2cec90
E: ID_NET_NAME_PATH=enp8s0f0
E: ID_NET_NAME_SLOT=ens9f0</pre>
<p>Le daemon udev commencerait par ID_NET_NAME_FROM_DATABASE, mais
cela n'existe pas pour cette carte. Il passe ensuite à
ID_NET_NAME_ONBOARD, qui n'est pas présent. Vient ensuite
ID_NET_NAME_SLOT, voilà la correspondance! L'entrée
ID_NET_NAME_SLOT contient <em>ens9f0</em>, qui est donc le nom final de
l'interface réseau.
| Cette boucle gère aussi quelques cas spéciaux. La première est de
vérifier si udev n'est pas configuré pour ne pas utiliser les noms
prédictible. Nous l'avions vu dans le post sur le<a href="https://major.io/2015/08/21/using-systemd-networkd-with-bonding-on-rackspaces-onmetal-servers/">bonding avec
systemd-networkd</a>
quand la configuration du bootloader contenait net.ifnames=0. Si cette
commande noyau est présente, les noms prédictibles ne sont pas utilisés.
| Un autre cas spécial est ID_NET_NAME_FROM_DATABASE. Ces ports
viennent de la <a href="https://github.com/systemd/systemd/blob/master/hwdb/20-net-ifname.hwdb">base de donnée matériel interne de
udev</a>.
Ce fichier ne contient pour le moment qu'une seule entrée et c'est pour
une carte réseau particulière iDRAC de DELL.</p>
</section>
<section id="confondu-par-l-hexa">
<h2>Confondu par l'hexa</h2>
<p>Si les numéros des ports PCI ne semblent pas se suivre, lisez mon
<a href="https://major.io/2014/08/06/unexpected-predictable-network-naming-systemd/">post de l'été
dernier</a>.
J'avais eu affaire à un serveur Dell particulier avec une carte Intel
dual-port sur le bus PCI 42. Le nom de l'interface était <em>enp66s0f0</em> et
j'en étais resté perplexe.
| Le nom <em>enp66s0f0</em> semble signifier que nous avons une carte sur le
bus PCI 66, slot 0, avec de multiple fonction d'index. Cependant,
systemd fait une conversion des numéros de slot PCI en hexa. La décimal
42 devient donc 66 en hexa.
| La plupart des serveurs n'auront pas cette complexité mais il est
important de se souvenir de la conversion en hexa.</p>
</section>
<section id="feedback">
<h2>Feedback</h2>
<p>Ces articles sur systemd sont ils intéressant? Je suis un grand fan de
systemd et j'adore écrire à son sujet.</p>
</section>
Ajouter Duckduckgo comme moteur de recherche dans SailfishOS2015-08-20T22:10:00+02:002015-08-20T22:10:00+02:00Aldevartag:blog.devarieux.net,2015-08-20:/2015/08/ajouter-duckduckgo-comme-moteur-de-recherche-dans-sailfishos.html<p>Par défaut, le navigateur de SailfishOS propose Bing, Yahoo ou Google
comme moteur de recherche et il n'y a pas d'interface pour ajouter de
nouveaux moteurs de recherche.</p>
<p>Je vous propose ici une méthode pour ajouter un nouveau moteur de
recherche dans cette liste. Ici ce sera
<a href="https://duckduckgo.com/">Duckduckgo</a></p>
<p>La manipulation …</p><p>Par défaut, le navigateur de SailfishOS propose Bing, Yahoo ou Google
comme moteur de recherche et il n'y a pas d'interface pour ajouter de
nouveaux moteurs de recherche.</p>
<p>Je vous propose ici une méthode pour ajouter un nouveau moteur de
recherche dans cette liste. Ici ce sera
<a href="https://duckduckgo.com/">Duckduckgo</a></p>
<p>La manipulation consiste à ajouter un fichier de description du moteur
de recherche dans le répertoire adéquat.</p>
<p>La première étape est d'activer le mode développeur et de se connecter
en SSH à son Jolla. Si vous ne savez pas comment vous y prendre, vous
pouvez <a href="http://blog.devarieux.net/2015/03/se-connecter-en-ssh-a-son-jolla/">suivre ce
tuto</a></p>
<p>Une fois connecté en SSH, se connecter en root :</p>
<pre>[nemo@Jolla ~]$ devel-su</pre>
<p>Se rendre dans /usr/lib/mozembedlite/chrome/embedlite/content/</p>
<pre>[root@Jolla nemo]# cd /usr/lib/mozembedlite/chrome/embedlite/content/</pre>
<p>Créer un fichier duckduckgo.xml</p>
<pre>[root@Jolla nemo]# vi duckduckgo.xml</pre>
<p>Coller le contenu de ce fichier :
<a href="http://blog.devarieux.net/wp-content/uploads/2015/08/duckduckgo.xml">duckduckgo.xml</a></p>
<p>Ou plus simplement</p>
<pre>[root@Jolla content]# curl http://blog.devarieux.net/wp-content/uploads/2015/08/duckduckgo.xml -o duckduckgo.xml</pre>
<p>Il ne reste plus qu'à fermer se rendre sur le téléphone, fermer
l'application 'Réglages', la relancer, se rendre dans 'Application' >
'Navigateur' et choisir le moteur de recherche Duckduckgo.</p>
<p>Enjoy!</p>
<div class="m-image">
<a href="/images/20150820220621.jpg"><img src="https://blog.devarieux.net/images/20150820220621-169x300.jpg" /></a>
</div>
Prise en main de GNS3 pour la simulation réseau2015-08-19T21:57:00+02:002015-08-19T21:57:00+02:00Aldevartag:blog.devarieux.net,2015-08-19:/2015/08/prise-en-main-de-gns3-pour-la-simulation-reseau.html<p>Comme moi, vous connaissez peut être l'utilitaire <a href="https://www.netacad.com/about-networking-academy/packet-tracer">Packet Tracer de
Cisco</a>
qui permet de simuler un réseau Cisco et d'y faire quelques exercices.
C'est un très bon outil pour les étudiants mais relativement peu
exploitable en entreprise car il ne simule que du Cisco et ne sais pas
simuler autre …</p><p>Comme moi, vous connaissez peut être l'utilitaire <a href="https://www.netacad.com/about-networking-academy/packet-tracer">Packet Tracer de
Cisco</a>
qui permet de simuler un réseau Cisco et d'y faire quelques exercices.
C'est un très bon outil pour les étudiants mais relativement peu
exploitable en entreprise car il ne simule que du Cisco et ne sais pas
simuler autre chose que des hôtes très basiques. Impossible d'y simuler
un serveur pfsense par exemple.</p>
<p>J'ai récemment fait la découverte de GNS3 qui est un logiciel assez
similaire mais vous vous en doutez bien plus complet et qui possède la
capacité de simuler un réseau de production. Vous pouvez créer des
projets avec switchs et routeurs mais également ajouter des VMs que vous
aurez pris le soin de créer avec VirtualBox ou Qemu. Wireshark est
intégré afin de capturer des paquets réseau comme on le souhaite.</p>
<p>GNS3 a vu le jour suite à l'apparition de Dynamips, un émulateur de l'OS
de Cisco : IOS (à ne pas confondre avec l'iOS d'Apple). Dynamips est un
outil qui se manipule en ligne de commande et qui demande un solide
bagage technique. GNS3 a alors été développé pour faciliter cette
configuration et apporter beaucoup d'autres fonctionnalités qui ne sont
pas présentes dans Dynamips comme par exemple le support de Cisco PIX et
ASA, ainsi que de Juniper avec JunOS.</p>
<p>Avant de commencer, il faut noter que la seule façon de simuler un vrai
environnement IOS est de posséder une image d'IOS. Dynamips et GNS3 ne
contiennent pas ces images pour d'évidents problèmes de droits, tout
comme VirtualBox ne vous propose pas d'image Windows. Il y a plusieurs
façon légales de se procurer ces images (par exemple si vous possédez un
switch ou un routeur Cisco) et d'autres moins légales (trouvable
facilement).</p>
<p>Pour récupérer la dernière version de GNS3 (v1.3.9 aujourd'hui), vous
devez vous inscrire <a href="http://www.gns3.com/">sur leur site</a> et
télécharger le paquet qu'il vous faut. L'appli est multiplateforme,
compatible Windows, Linux et Mac. L'installeur va installer pour vous
tous les outils nécessaire pour la virtualisation et la capture de
paquets.</p>
<div class="m-image">
<a href="/images/2015-08-17-23_30_55-GNS3-1.3.9-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_30_55-GNS3-1.3.9-Setup-300x233.png" /></a>
</div>
<p>Sous Windows, l'installation
est assez classique. Après avoir lancé l'installeur, la fenêtre de setup
apparaît, il suffit alors de suivre les indications jusqu'à arriver à
cette fenêtre :</p>
<div class="m-image">
<a href="/images/2015-08-17-23_33_08-GNS3-1.3.9-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_33_08-GNS3-1.3.9-Setup-300x233.png" /></a>
</div>
<p>Il est préférable de laisser tout cocher, ainsi si des logiciels ont besoin de mise à jour, elles seront faites. En cliquant sur Next, l'installeur va lancer
l'installation de winPcap.</p>
<div class="m-image">
<a href="/images/2015-08-17-23_33_29-WinPcap-4.1.3-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_33_29-WinPcap-4.1.3-Setup-300x233.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-17-23_33_42-WinPcap-4.1.3-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_33_42-WinPcap-4.1.3-Setup-300x233.png" /></a>
</div>
<p>On laisse cocher le lancement automatique du driver au démarrage.</p>
<p>Ensuite, l'installeur télécharge et installe Wireshark</p>
<div class="m-image">
<a href="/images/2015-08-17-23_33_59-GNS3-1.3.9-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_33_59-GNS3-1.3.9-Setup-300x233.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-17-23_34_14-Wireshark-1.12.4-64-bit-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_34_14-Wireshark-1.12.4-64-bit-Setup-300x233.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-17-23_34_39-Wireshark-1.12.4-64-bit-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_34_39-Wireshark-1.12.4-64-bit-Setup-300x233.png" /></a>
</div>
<p>WinPcap est déjà installé donc on décoche l'option</p>
<div class="m-image">
<a href="/images/2015-08-17-23_34_56-Wireshark-1.12.4-64-bit-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_34_56-Wireshark-1.12.4-64-bit-Setup-300x233.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-17-23_35_47-Wireshark-1.12.4-64-bit-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_35_47-Wireshark-1.12.4-64-bit-Setup-300x233.png" /></a>
</div>
<p>On décoche 'Run Wireshark',on ne va pas en avoir besoin tout de suite.</p>
<p>L'installation se poursuit avec cette fois SolarWinds Response Time
Viewer qui est une application d'analyse de capture Wireshark</p>
<div class="m-image">
<a href="/images/2015-08-17-23_37_13-SolarWinds-Registration.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_37_13-SolarWinds-Registration-300x168.png" /></a>
</div>
<p>Ici, vous pouvez mettre ce que vous voulez, l'adresse n'est pas vérifiée</p>
<div class="m-image">
<a href="/images/2015-08-17-23_38_54-SolarWinds-Response-Time-Viewer-for-Windows.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_38_54-SolarWinds-Response-Time-Viewer-for-Windows-300x213.png" /></a>
</div>
<p>L'application se lance automatiquement. Je vous invite à en
faire un tour rapide avant de la fermer</p>
<div class="m-image">
<a href="/images/2015-08-17-23_40_09-GNS3-1.3.9-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_40_09-GNS3-1.3.9-Setup-300x233.png" /></a>
</div>
<div class="m-image">
<a href="/images/2015-08-17-23_40_30-GNS3-1.3.9-Setup.png"><img src="https://blog.devarieux.net/images/2015-08-17-23_40_30-GNS3-1.3.9-Setup-300x233.png" /></a>
</div>
<p>SolarWinds vous propose une licence gratuite pour son
software. Je n'ai pas testé comment acquérir cette licence et je ne sais
pas sous quelle condition elle s'acquière.</p>
<p>Voilà pour la description et l'installation de GNS3. La prochaine fois,
on verra comment le configurer et y créer de nouveau routeur, switchs et
VM.</p>
Vmware tools, Centos 7 et customisation2015-08-14T22:39:00+02:002015-08-14T22:39:00+02:00Aldevartag:blog.devarieux.net,2015-08-14:/2015/08/vmware-tools-centos-7-et-customisation.html<p>Depuis quelques temps, lorsqu'on souhaite déployer les VMware tools dans
une VM Centos 7 / RedHat 7, le script d'installation hurle de ne pas
utiliser le script perl fournit mais de passer plutôt par les
open-vm-tools qu'on peut directement trouvé dans le gestionnaire de
paquet.</p>
<pre>yum install open-vm-tools</pre>
<p>C'est simple, rapide …</p><p>Depuis quelques temps, lorsqu'on souhaite déployer les VMware tools dans
une VM Centos 7 / RedHat 7, le script d'installation hurle de ne pas
utiliser le script perl fournit mais de passer plutôt par les
open-vm-tools qu'on peut directement trouvé dans le gestionnaire de
paquet.</p>
<pre>yum install open-vm-tools</pre>
<p>C'est simple, rapide, ça facilite les mise à jour des tools et c'est
conseillé par VMware directement, il y a même <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2073803">un
KB</a>
pour ça et <a href="https://github.com/vmware/open-vm-tools">un projet
GitHub</a>.</p>
<p>Pour rappel, l'insallation des vm-tools permet d'accéder à ces
fonctionnalité vSphere :</p>
<ul>
<li>Synchronisation de l'horloge de l'OS invité avec celle de la
plateforme de virtualisation</li>
<li>Permet à l'hyperviseur de procéder à des appels système afin par
exemple de demander à l'OS de s'arréter.</li>
<li>Support de vSphere High Availability (HA) grace à un système de
heartbeat.</li>
<li>Permet à l'hyperviseur de récolter des informations sur la
consommation des ressources CPU, RAM, réseau.</li>
</ul>
<p>Dans cette liste, il manque tout de même un outil important. Si vous
clonez ou si vous créez un template à partir d'une VM ayant les
open-vm-tools, vous serez dans l'incapacité de customiser la nouvelle VM
à sa création. Exit donc le changement du mot de passe root et surtout
la configuration réseau. Cette fonctionnalité est apportée par un plugin
pour open-vm-tools nommé DeployPkg.</p>
<p>La page <a href="http://partnerweb.vmware.com/GOSIG/RHEL_7.html">Red Hat Enterprise Linux 7 Guest Operating System Installation
Guide</a> mentionne bien
ce plugin mais il y manque certaines informations. La procédure complète
est mieux décrite dans la <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2075048">Knowledge Base de
VMware.</a>Celle
ci consiste a récupérer les clés public du dépots VMware, importer les
clés, créer le fichier de repo pour yum et procéder enfin à
l'installation.</p>
<p>Dans un premier temps, on récupère les clés ici
<a class="m-link-wrap" href="http://packages.vmware.com/tools/keys">http://packages.vmware.com/tools/keys</a> et on les place dans le répertoire
/tmp du serveur</p>
<p>On importe les clés avec rpm</p>
<pre>rpm --import /tmp/key1
rpm --import /tmp/key2</pre>
<p>Création du fichier <em>/etc/yum.repos.d/vmware-tools.repo</em> avec ce contenu
:</p>
<pre>[vmware-tools]
name = VMware Tools
baseurl = http://packages.vmware.com/packages/rhel7/x86_64/
enabled = 1
gpgcheck = 1</pre>
<p>Installation du paquet</p>
<pre>yum install open-vm-tools-deploypkg</pre>
<p>Installation de perl, nécessaire pour les scripts de customisation</p>
<pre>yum install perl</pre>
<p>On termine par le rechargement du service pour prendre en compte
l'installation du plugin</p>
<pre>systemctl restart vmtoolsd</pre>
<p>Vous pouvez maintenant transformer votre VM en template en toute
sérénité.</p>
Se connecter en SSH à son Jolla2015-03-03T23:19:00+01:002015-03-03T23:19:00+01:00Aldevartag:blog.devarieux.net,2015-03-03:/2015/03/se-connecter-en-ssh-a-son-jolla.html<p>Même s'il est possible d'utiliser directement une console sur l'appareil
grâce à FingerPrint quand on est en mode developpeur, il est quand même
plus simple d'utiliser son PC pour entrer quelques commandes où même
pour écrire des scripts. Voici donc comment activer la connexion SSH sur
son Jolla.</p>
<p>1- Activer …</p><p>Même s'il est possible d'utiliser directement une console sur l'appareil
grâce à FingerPrint quand on est en mode developpeur, il est quand même
plus simple d'utiliser son PC pour entrer quelques commandes où même
pour écrire des scripts. Voici donc comment activer la connexion SSH sur
son Jolla.</p>
<p>1- Activer le mode developpeur</p>
<div class="m-image">
<a href="/images/20150303211811.jpg"><img src="https://blog.devarieux.net/images/20150303211811-169x300.jpg" /></a>
</div>
<p>2- Activer la connexion distante et définir un mot de passe</p>
<div class="m-image">
<a href="/images/20150303211957.jpg"><img src="https://blog.devarieux.net/images/20150303211957-169x300.jpg" /></a>
</div>
<p>3- Se connecter depuis son PC avec l'utilisateur nemo. Pour passer en
root, taper simplement 'su' avec le même mot de passe.</p>
<div class="m-image">
<a href="/images/sshJolla.png"><img src="https://blog.devarieux.net/images/sshJolla.png" /></a>
</div>
Jolla victime de son succès2015-02-24T10:47:00+01:002015-02-24T10:47:00+01:00Aldevartag:blog.devarieux.net,2015-02-24:/2015/02/jolla-victime-de-son-succes.html<p>Comme je le disais dans le dernier <a href="https://blog.devarieux.net/2015/02/prise-en-main-du-smartphone-de-jolla.html">article sur le
Jolla</a>,
je devais recevoir avec mon colis 2 coques supplémentaires mais celles
ci étaient absentes.</p>
<p>J'ai donc envoyé un mail au support Jolla pour savoir ce qu'il en était.
Ils m'ont informé qu'ils ne pourraient pas honorer leur commande. Voici …</p><p>Comme je le disais dans le dernier <a href="https://blog.devarieux.net/2015/02/prise-en-main-du-smartphone-de-jolla.html">article sur le
Jolla</a>,
je devais recevoir avec mon colis 2 coques supplémentaires mais celles
ci étaient absentes.</p>
<p>J'ai donc envoyé un mail au support Jolla pour savoir ce qu'il en était.
Ils m'ont informé qu'ils ne pourraient pas honorer leur commande. Voici
leur réponse :</p>
<blockquote>
<p>Hi,</p>
<p>thank you for your message and for your recent order at the Jolla
Online Shop.</p>
<p>However, the bad news is that we were not able to dispatch the Lime
and Nadeshiko Pink The Other Half that your order contained. We were
unprepared for the level of interest that the Jolla Bundle received
and unfortunately we were not able to meet the demand in full.
Currently we can't estimate when the Lime and Nadeshiko Pink The
Other Half will be available again, and we don't want to keep you
waiting for your order any longer.</p>
<p>We are really sorry for letting you down. To make up for the absence
of Lime and Nadeshiko Pink The Other Half, we’re putting together an
exclusive Jolla branded merchandise pack for you. It will be shipped
to you in the coming days.</p>
<p>Even without the extra accessories, we sincerely hope that you will
love your new Jolla smartphone!</p>
<p>Have a great day!</p>
<p>
Sincerely,<br />
<p>
Jolla Customer Care<br />
</p>
</p>
</blockquote>
<p>Pour moi, la phrase clé est "<em>We were unprepared for the level of
interest that the Jolla Bundle received and unfortunately we were not
able to meet the demand in full".</em>C'est en fait une bonne nouvelle.
L'augmentation du parc de smartphone Jolla est une condition<em>sine qua
non</em> pour que le nombre d'application du store augmente ,ce qui décidera
plus de personne à l'acheter, ce qui augmentera le nombre d'application
etc.</p>
<p>Pour s'excuser de cette impossibilité d'honorer la commande, ils
m'annoncent également qu'ils sont en train de me préparer un <em>Jolla
branded merchandise pack</em>. En gros, des goodies. Pourquoi pas, y'a peut
être des trucs sympa et ça m'aidera à faire leur promo. Ceci me laisse
un tout petit peu sur ma faim tout de même. Je leur ai donc demandé s'il
leur était possible de me donner un code promo pour l'achat d'une <a href="/http://shop.jolla.com/eu_en/cat-the-other-half/the-other-half-aloe.html">coque
Aloe</a>.
Et voici leur réponse :</p>
<blockquote>
<p>Hi,</p>
<p>thank you for your message.</p>
<p>We will make sure to send you an Aloe Other Half.</p>
<p>Have a great day!</p>
<p>Sincerely,
Jolla Customer Care</p>
</blockquote>
<p>Je devrais donc recevoir une coque Aloe à la place.</p>
<p>La dessus, on peut dire que service consommateur de Jolla fait bien son
taf. C'est pas pour rien que l'adresse email du support est
<a href="mailto:'care@jolla">'care@jolla</a>....'</p>
Prise en main du smartphone de Jolla2015-02-21T00:29:00+01:002015-02-21T00:29:00+01:00Aldevartag:blog.devarieux.net,2015-02-21:/2015/02/prise-en-main-du-smartphone-de-jolla.html<p>Il est enfin arrivé, après plus de 2 semaines d'attente pour cause de
rupture de stock. Malheureusement le colis est incomplet puisqu'il
manque 2 des 3 'Other Half' (les coques arrières). J'ai envoyé un mail à
Jolla pour savoir où était ses 2 pièces manquantes.</p>
<p>Une fois cette légère déception …</p><p>Il est enfin arrivé, après plus de 2 semaines d'attente pour cause de
rupture de stock. Malheureusement le colis est incomplet puisqu'il
manque 2 des 3 'Other Half' (les coques arrières). J'ai envoyé un mail à
Jolla pour savoir où était ses 2 pièces manquantes.</p>
<p>Une fois cette légère déception passée, j'ai observé l'emballage d'un
peu plus prêt. La boite est sympa, sobre. Le logo Jolla est écrit en
argenté et entouré de lignes de code</p>
<p>Le contenu est très basique : le smartphone, la batterie, un câble
USB/micro USB et un bloc alim secteur sur lequel on peut branche le
câble USB. Pas de pair d'écouteur, on a juste le strict minimum. Notons
tout de même la présence de 2 stickers au nom de la firme.</p>
<p>Au premier démarrage, un tuto vous explique comment utiliser cet OS basé
sur la gestuelle. En effet, que ce soit pour fermer une appli, valider
ou annuler une action, retourner sur l'écran principal ou lire un SMS,
toutes ces actions se feront par un mouvement de haut en bas, ou de
gauche à droite ou inversement, sans oublier que si le geste commence en
dehors de la surface de l'écran, cela n'aura pas le même effet que s'il
prend son départ sur la surface d'affichage. C'est donc une nouvelle
façon d’appréhender son smartphone et je doit avouer que j'étais assez
enthousiaste en testant ces nouvelles fonctions. Cette façon de faire,
très différente d'Androïd, iOS ou Windows Phone est vraiment
rafraichissante, surtout après 5 années chez Androïd.</p>
<p>Lorsqu'un menu est disponible, une lumière vous indique que vous pouvez
tirer l'écran pour faire apparaitre ce menu. La sélection d'une entrée
du menu se fait en tirant plus ou moins.</p>
<p>Lorsqu'on ferme une application en swipant de droite à gauche (pour la
fermer réellement, c'est de haut en bas), celle ci se 'range' sur la
page principale et reste tourner en tache de fond. SailfishOS est
multitâche. Les applications qui ne sont pas fermées continues de se
mettre à jour et ne sont pas gelées comme cela peut être le cas sur les
autres plateforme. Vous pouvez avoir jusqu'à 9 applications en parallèle</p>
<p>Au premier démarrage, SailfishOS vous propose de connecter vos comptes
Google, Facebook et Twitter. Il regroupera ensuite toutes les
notifications au même endroit, que vous pourrez retrouver en swipant du
bas vers le haut. On peut ensuite facilement ajouter un compte email, un
compte xmpp (intégré sans appli à installer) et sont même présent les
connecteurs CalDAV et CardDAV que j'ai pu brancher sur mon instance
zimbra.</p>
<p>Mais que manque-t-il à ce smartphone en fait? Premièrement, le store
n'est pas très fourni. Il est cependant possible d'installer des
applications Android en installant quelques market. Je n'ai pas encore
testé cette fonctionnalité.</p>
<p>L'écran n'offre pas une très bonne définition, ainsi que la camera 8Mp.
Les photos sont de piètre qualité par rapport à ce dont on est habitué.
L'appareil photo à même tendance à prendre les photos après vous avoir
annoncé que la photo à été prise, ce qui peut avoir tendance à faire des
photos floues.</p>
<p>Ce n'est pas un foudre de guerre, si vous voulez jouer, passez votre
chemin. Par contre, l'OS est très fluide dans son utilisation.</p>
<p>Je suis sûr qu'il a plein d'autres défauts que je trouverai lors de son
utilisation quotidienne. Ceci dit, l'OS me semble simple à appréhender.
Le système lumineux indiquant les actions possibles est très bien pensé
et fait bien son boulot de guide.</p>
Jolla - Le Smartphone Linux2015-02-07T18:01:00+01:002015-02-07T18:01:00+01:00Aldevartag:blog.devarieux.net,2015-02-07:/2015/02/jolla-le-smartphone-linux.html<section id="flash-back">
<h2>Flash Back</h2>
<p>En Juin 2013, je me demandais comment j'allais <a href="https://blog.devarieux.net/2013/06/comment-vais-je-me-passer-des-services-de-google.html">me passer des services
de
Google</a>.</p>
<p>Depuis, pas mal de choses ont évolué. J'ai un serveur sur lequel je
stock mon agenda, mes contacts, mes emails avec Zimbra. J'utilise
<a href="http://pyd.io">Pydio</a> pour le cloud. Mon compte gmail est conservé
pour des …</p></section><section id="flash-back">
<h2>Flash Back</h2>
<p>En Juin 2013, je me demandais comment j'allais <a href="https://blog.devarieux.net/2013/06/comment-vais-je-me-passer-des-services-de-google.html">me passer des services
de
Google</a>.</p>
<p>Depuis, pas mal de choses ont évolué. J'ai un serveur sur lequel je
stock mon agenda, mes contacts, mes emails avec Zimbra. J'utilise
<a href="http://pyd.io">Pydio</a> pour le cloud. Mon compte gmail est conservé
pour des raisons historique, même si de moins en moins de personnes de
mon entourage l'utilise. Ce compte Google est également celui que
j'utilise sur mon smartphone Android.</p>
<p>En gros, Android est le dernier lien solide qui m'attache à Google. Ce
lien va bientôt sauter. Je viens en effet de commander le smartphone de
Jolla sous Sailfish OS. En gros, du full Linux, sans la sous couche Java
incluse dans Android.</p>
<p>L'entreprise Jolla qui fabrique les smartphones du même nom a été créée
par des anciens cadres et ingénieurs de chez Nokia et Sailfish OS
reprend les bases de MeeGo, l'OS du Nokia N9, basé sur Qt. Une couche de
compatibilité est ajoutée pour pouvoir faire fonctionner plus ou moins
bien les applis Android.</p>
</section>
<section id="comment-est-ce-que-je-me-suis-decide-a-faire-cet-achat">
<h2>Comment est ce que je me suis décidé à faire cet achat?</h2>
<p>Cela faisait un moment que je souhaitais changer mon Nexus 4. Il
fonctionne encore très bien, Madame en héritera. J'attendais avec
impatience la sortie du Nexus 6 mais la politique tarifaire sur ce
modèle m'a fait renoncer à cet achat. Il est hors de question que je
mette plus de 300/350€ dans un smartphone.</p>
<p>Et puis il y a 10 jours un amis m'a montré son Jolla, m'a expliqué le
fonctionnement, la gestion du multi tâches, comment on passe d'une appli
à l'autre etc.. Et enfin le prix : 250€. Alléchant... Le lendemain, je
me baladais sur le site de Jolla et étais à 2 doigts de faire chauffer
la CB quand je me suis dit que ce n'était peut être pas le moment de
faire ce genre de dépense. Le jeudi suivant, je tombe sur une nouvelle
offre : <a href="http://jollafr.org/code-promo-le-jolla-pour-200e-fosdem2015/">Code promo, le Jolla pour 200€ !
#FOSDEM2015</a>.
Et voilà comment je me suis retrouvé à commander la bête sur le <a href="http://shop.jolla.com/eu_en/">shop de
Jolla.</a></p>
</section>
<section id="et-maintenant">
<h2>Et Maintenant</h2>
<p>Alors évidemment, ne rêvons pas trop, tout ne sera pas rose. Je suppose
qu'il va y avoir des bugs, que je vais perdre en confort mais comme le
dit si bien l'ami qui m'a montré son Jolla la première fois, c'est aussi
un achat engagé.</p>
<div class="m-image">
<a href="/images/jolla-launch-2.jpg"><img src="https://blog.devarieux.net/images/jolla-launch-2-300x226.jpg" /></a>
</div>
<p>J'attends maintenant impatiemment de recevoir mon colis.</p>
</section>
Trop de requêtes ARP - Régler le timeout de la table ARP2015-01-21T20:18:00+01:002015-01-21T20:18:00+01:00Aldevartag:blog.devarieux.net,2015-01-21:/2015/01/trop-de-requetes-arp-regler-le-timeout-de-la-table-arp.html<p>Pour des besoins spécifiques, nous avons fait l'acquisition d'un serveur
chez SoYouStart.</p>
<p>Le serveur étant assez puissant, nous avons décidé d'y installer un
hyperviseur Proxmox qui hébergera des VM CentOS</p>
<p>Avant de mettre en place les applications dont j'ai besoin sur ce
serveur, je l'ai installé et laissé tourner quelques …</p><p>Pour des besoins spécifiques, nous avons fait l'acquisition d'un serveur
chez SoYouStart.</p>
<p>Le serveur étant assez puissant, nous avons décidé d'y installer un
hyperviseur Proxmox qui hébergera des VM CentOS</p>
<p>Avant de mettre en place les applications dont j'ai besoin sur ce
serveur, je l'ai installé et laissé tourner quelques temps pour
m'assurer de sa stabilité. Et le premier dimanche suivant l'installe,
voici le mail que je reçois, venant d'un bot de chez OVH et concernant
une des VM :</p>
<pre>Bonjour,
Nous avons constaté que votre serveur diffuse inutilement un nombre important de requêtes sur le
réseau via son IP failover XX.XX.XX.XX, ceci est dû à une mauvaise configuration de celle-ci.
Nous vous avons demandé dans un mail précédant de bien vouloir reconfigurer votre IP failover,
constatant que le problème persiste, nous nous permettons de réitérer cette demande.
Si le problème n'est pas résolu dans un délais de 24 heures, nous nous verrons dans l'obligation de
bloquer votre IP.
Dans ce cas, il vous sera possible de la débloquer dans votre manager une fois la reconfiguration
faite.
Ceci est le dernier avertissement avant le blocage de votre IP !
------- EXTRAIT DES REQUETES -------
Thu Jan 8 06:47:25 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:47:55 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:48:25 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:48:55 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:49:25 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:49:55 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
Thu Jan 8 06:50:25 2015 : arp who-has IP.DE.LA.GW tell XX.XX.XX.XX
------- FIN DE L'EXTRAIT -------</pre>
<p>Une requête toutes les 30 secondes, c'est en effet beaucoup.</p>
<p>J'ai longtemps cherché d'où pouvait venir le problème. J'ai commencer
par changer de modèle de carte réseau dans Proxmox (E1000, VirtIO,
Vmxnet3) sans succès. J'ai reconfiguré et rereconfiguré le réseau en
ajoutant ou retirant des options dans le fichier ifcfg-eth0, rien à
faire, toujours autant de requêtes ARP.</p>
<p>En faisant tout ça, je me rendais bien compte d'une aberration dans les
opérations que je mettais en œuvre : je travaillais sur du niveau 3 (IP)
alors que j'avais un problème qui se situait entre la couche 2 et la
couche 3 (ARP).</p>
<p>Après moult recherches, j'ai fini par trouver où étaient les fichiers
qui pourraient m'aider.</p>
<p>Voici les fichiers concernés, avec leurs valeurs par défaut.</p>
<pre>/proc/sys/net/ipv4/neigh/default/anycast_delay:100
/proc/sys/net/ipv4/neigh/default/app_solicit:0
/proc/sys/net/ipv4/neigh/default/base_reachable_time:30
/proc/sys/net/ipv4/neigh/default/base_reachable_time_ms:1200
/proc/sys/net/ipv4/neigh/default/delay_first_probe_time:5
/proc/sys/net/ipv4/neigh/default/gc_interval:30
/proc/sys/net/ipv4/neigh/default/gc_stale_time:60
/proc/sys/net/ipv4/neigh/default/gc_thresh1:128
/proc/sys/net/ipv4/neigh/default/gc_thresh2:512
/proc/sys/net/ipv4/neigh/default/gc_thresh3:1024
/proc/sys/net/ipv4/neigh/default/locktime:100
/proc/sys/net/ipv4/neigh/default/mcast_solicit:3
/proc/sys/net/ipv4/neigh/default/proxy_delay:80
/proc/sys/net/ipv4/neigh/default/proxy_qlen:64
/proc/sys/net/ipv4/neigh/default/retrans_time:100
/proc/sys/net/ipv4/neigh/default/ucast_solicit:3
/proc/sys/net/ipv4/neigh/default/unres_qlen:3</pre>
<p>Ici, les fichiers qui nous intéressent sont base_reachable_time (ou
base_reachable_time_ms) et gc_stale_time.</p>
<p>Le fichier gc_stale_time définit la fréquence à laquelle l'état
'stale' (obsolète) des entrées de la table ARP sera vérifié. Le défaut
est à 60 secondes. Le fichier base_reachable_time quant à lui définit
la durée durant laquelle une entrée de la table ARP est considérée
valide. La durée de validité de cette entrée sera un chiffre choisi au
hasard entre (base_reachable_time/2) et (3*base_reachable_time/2).
La valeur par défaut est de 30 secondes.</p>
<p>Un simple echo du chiffre souhaité dans le fichier suffit. CentOS permet
d'avoir ces valeurs en dure et persistante après un redémarrage (les
autres distributions aussi sans doute, mais je ne sais par quel moyen).</p>
<p>Pour CentOS donc, dans le fichier /etc/sysctl.conf, ajouter ces lignes :</p>
<pre>##### Pour limiter le nombre de requête ARP ##########
##### Equivalent a 30 minutes ###########
net.ipv4.neigh.default.base_reachable_time_ms = 1200000
net.ipv4.neigh.default.gc_stale_time = 3600</pre>
<p>Ces valeurs vont donner une durée de validité des entrées de la table
ARP entre 15 et 45 minutes.</p>
Playskool présente: Numéricable concurrence Netflix2014-09-16T11:02:00+02:002014-09-16T11:02:00+02:00Aldevartag:blog.devarieux.net,2014-09-16:/2014/09/numericable-concurrence-netflix.html<p>Sous ce titre un peu taquin se cache une grande frustration. Nous avons
tous plus ou moins l'habitude que nos différents fournisseurs tentent de
nous la mettre bien profond avec différents services inutiles et mal
conçus.</p>
<p>Hier, Lundi 15 Septembre, nous avons atteint, je crois, le zenith du
foutage de …</p><p>Sous ce titre un peu taquin se cache une grande frustration. Nous avons
tous plus ou moins l'habitude que nos différents fournisseurs tentent de
nous la mettre bien profond avec différents services inutiles et mal
conçus.</p>
<p>Hier, Lundi 15 Septembre, nous avons atteint, je crois, le zenith du
foutage de gueule, le paroxysme de la sodomie, les<a href="http://lesabyssales.fr/">profondeurs
abyssales</a> de mon trou du cul. Et j'ai beau
ajouté du beurre, ça passe toujours pas. Vous l'avez compris, je suis
colère, <a href="https://www.youtube.com/watch?v=n4IEaJo43tc">je suis violence parce que je suis
trahison</a>.</p>
<p>Bien... Maintenant que vous avez compris comment je me sens je vais vous
dire ce qui me met dans cet état. Hier donc, Numéricable a lancé son
service pour concurrencer Netflix : LaBox Series. <a href="http://blog.devarieux.net/wp-content/uploads/2014/09/CP_Numericable_LaBox-Series.pdf">Le communiqué de
presse</a> est
limpide : "Un accès SIMPLE et GRATUIT à 3000 épisodes de séries par mois
pour les abonnés LaBox Fibre". Parfait me dis-je, je suis abonné à LaBox
Fibre avec une offre Power, même si le catalogue n'est sans doute pas
encore énorme, ça semble être un bon début, surtout si <a href="http://www.zdnet.fr/actualites/netflix-en-france-ce-sera-sans-numericable-qui-riposte-avec-labox-series-39806307.htm">Numéricable
refuse de
développer</a>
une interface Netflix pour LaBox. Tout guilleret, je rentre donc chez
moi hier soir et je me lance dans l'exploration du service en question.</p>
<p>Je commence par regarder le catalogue. Mouais, beaucoup de manga assez
ancien, des séries moyennement intéressantes et surtout peu d'épisodes
par série. Vous ne trouverez pas de saison 1, sauf s'il n'y qu'une seule
saison et certaines saisons sont incomplètes. Je commence à ronger mon
frein mais je suis bonne pâte et je leur trouve quelques excuses : c'est
le premier jour de lancement, ça a été fait dans la précipitation pour
contrer Netflix, ça va s'étoffer.</p>
<p>Une fois que j'ai fait le tour du pauvre catalogue (Ha si, y'a chapi
chapo quand même), je lance l'épisode 1 de la saison 1 de <em>Äkta
människor</em>(la série suédoise sur la banalisation des androïdes (les
robots, pas les smartphones)) et là... STUPEUR ET TREMBLEMENT :</p>
<p><strong>ON ME DEMANDE DE PAYER!!!!</strong></p>
<p>Ho, pas grand chose, 1,40€ je crois de mémoire, pour pouvoir voir
l'épisode pendant 48h, en passant par ArteVOD. WHAT THE FUCK? C'est
marqué que c'est <strong>GRATUIT</strong> putain! Depuis quand payer à l'acte c'est
gratuit? Vous la sentez bien la sodomie là? Parce que moi j'ai encore
mal ce matin.</p>
<p>Si j'étais un peu mesquin, je dirais que ce service est une incitation
pour que les abonnés fibre migrent vers Bouygues qui s'appuie sur le
réseau numéricable et proposera Netflix sur sa box au mois de novembre.</p>
Accéder en webdav à son fichier Keepass2014-09-05T22:54:00+02:002014-09-05T22:54:00+02:00Aldevartag:blog.devarieux.net,2014-09-05:/2014/09/acceder-en-webdav-a-son-fichier-keepass.html<p>Keepass est un gestionnaire de mot de passe que j'utilise
personnellement et professionnellement. Il permet notamment de partager
un coffre fort entre plusieurs personne en offrant un support pour ftp
et http/webdav. Certains plugins ajoutent le support sftp et ftps.</p>
<p>Sur CentOS, apache est livré avec le module webdav …</p><p>Keepass est un gestionnaire de mot de passe que j'utilise
personnellement et professionnellement. Il permet notamment de partager
un coffre fort entre plusieurs personne en offrant un support pour ftp
et http/webdav. Certains plugins ajoutent le support sftp et ftps.</p>
<p>Sur CentOS, apache est livré avec le module webdav. Ce n'est pas
forcement le cas de toutes les distributions.</p>
<p>La configuration utilisée est la suivante :</p>
<ul>
<li>Un sous domaine créé pour contenir le fichier kdbx</li>
<li>une protection par mot de passe pour l'accès au fichier en lui même
(anciennement .htaccess)</li>
<li>L'autorisation d'accéder au sous domaine en webdav</li>
<li>Et enfin, un mot de passe <strong>ultra solide</strong> pour le fichier kdbx qui
peut contenir des données sensibles.</li>
</ul>
<p>Dans mon cas, j'ai utilisé un sous domaine du type keepass.domain.tld et
le fichier est stocké en local sur le serveur sous /var/www/keepass/</p>
<pre>root# mkdir /var/www/keepass
root# chown apache. /var/www/keepass
root# chmod 770 /var/www/keepass
root# vim /etc/httpd/conf.d/keepass.conf</pre>
<p>Pour ne pas que le mot de passe passe en clair sur le net, nous allons
forcer l'utilisation de https</p>
<pre><VirtualHost *:80>
ServerName keepass.domain.tld
ServerAdmin admin@domain.tld
Redirect permanent / https://keepass.domain.tld/
ErrorLog /var/log/httpd/keepass.err
CustomLog /var/log/httpd/keepass.log combined
DocumentRoot /var/www/keepass
</VirtualHost>
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca.key
ServerName keepass.domain.tld
ServerAdmin admin@domain.tld
ErrorLog /var/log/httpd/keepass.err
CustomLog /var/log/httpd/keepass.log combined
DocumentRoot /var/www/keepass
<Directory "/var/www/keepass">
DAV On
SSLRequireSSL
Options None
AuthType Basic
AuthName WebDAV
AuthUserFile /etc/httpd/conf/.htpasswd
<LimitExcept GET OPTIONS>
Order allow,deny
Allow from X.X.X.X #IP que vous autorisez, 'all' pour tout le monde
Require valid-user
</LimitExcept>
</Directory>
</VirtualHost></pre>
<p>Voici les étapes pour la création du fichier .htpasswd</p>
<pre>root# htpasswd -c /etc/httpd/conf/.htpasswd NomUtilisateur
root# /etc/init.d/httpd restart</pre>
<p>Il ne reste plus qu'à placer le fichier kdbx dans /var/www/keepass et
donner à apache les droits en écriture sur ce fichier.</p>
<p>Enfin, dans Keepass en ouvrant une url, le logiciel demande de fournir
l'URL et si besoin un couple login/mdp.</p>
<p>L'URL sera de type <a class="m-link-wrap" href="https://keepass.domain.tld/fichier.kdbx">https://keepass.domain.tld/fichier.kdbx</a> et le couple
login/mdp est celui créé lors de l’exécution de la commande htpasswd</p>
Bash : Script de sauvegarde2014-07-24T11:14:00+02:002014-07-24T11:14:00+02:00Aldevartag:blog.devarieux.net,2014-07-24:/2014/07/bash-script-de-sauvegarde.html<p>On ne le dira jamais assez : <strong>FAITES DES SAUVEGARDES!!!!!</strong>
Ayant un petit serveur dédié sous CentOS, j'ai évidemment appliqué
cet adage à moi même. Je vous présente donc un script duquel vous pouvez
librement vous inspirer afin de l'adapter à votre environnement.
Ce script place quelques répertoires et quelques exports …</p><p>On ne le dira jamais assez : <strong>FAITES DES SAUVEGARDES!!!!!</strong>
Ayant un petit serveur dédié sous CentOS, j'ai évidemment appliqué
cet adage à moi même. Je vous présente donc un script duquel vous pouvez
librement vous inspirer afin de l'adapter à votre environnement.
Ce script place quelques répertoires et quelques exports de base de
données dans un fichier tar.gz puis envoie ce fichier sur 2 serveurs FTP
(ceinture + bretelles) et enfin déplace l'archive dans un répertoire de
<a href="http://pyd.io">pydio</a> afin de pouvoir facilement récupérer le
fichier sur ma machine personnelle.</p>
<pre>#!/bin/bash
#Fichier de Backup créé par Alain Devarieux
# - créer un fichier tar.gz contenant plusieurs élements de l'arborescence
# - Envoie ce fichier tar.gz sur un serveur FTP dédié au backup
# - Dépose une copie du fichier tar.gz dans un repertoire local
# - Ceinture ET Bretelles : Envoie le fichier tar.gz sur un 2nd serveur FTP
logger -t backup "########## Debut de la sauvegarde ##########"
# Nom du fichier de Backup
backup_file="/sauv/backup-$(hostname)-$(date +%Y-%m-%d).tar.gz"
#Variable : Premier Serveur FTP de Backup
bckftp01="server01"
bckftp01_user="user01"
bckftp01_mdp="Enter password here"
#Variable : Second Serveur de Backup
bckftp02="server02"
bckftp02_user="user02"
bckftp02_mdp="Enter password here"
#Varibales : Dossier de destination du tar.gz en local
destdir="/var/www/html/pydio/data/files/"
#Liste des dossiers à sauvegarder
backup_list="/etc /var/www/html /sauv/sql /sauv/packagelist.txt"
#Le dossier a exclure
backup_exclude="/var/www/html/pydio/data"
#Liste des paquets installés
rpm -qa > /sauv/packagelist.txt
#Dump des bases SQL
#Base01
if ! mysqldump -u userbase01 -pPassword base01 > /sauv/sql/base01.sql; then
statusbase01="Warning : Erreur lors de l'export de la base Base01"
else
statusbase01="Succes de l'export de la base Base01"
fi
logger -t backup "$statusbase01"
#Base02
if ! mysqldump -u userbase02 -pPassword Base02 > /sauv/sql/base02.sql; then
statusbase02="Warning : Erreur lors de l'export de la base Base02"
else
statusbase02="Succes de l'export de la base Base02"
fi
logger -t backup "$statusbase02"
#Creation du tar
#On commence par enregistrer la seconde de debut
start=$(date '+%s')
if ! tar czf $backup_file --exclude=$backup_exclude $backup_list; then
statustar="echec de la commande tar" || exit 1
else
statustar="Succes creation fichier tar taille=$(stat -c%s $backup_file) duree=$((`date '+%s'` - $start))"
fi
#On log le resultat
logger -t backup "$statustar"
#Envoie vers le ftp01
if ! lftp $bckftp01_user:$bckftp01_mdp@$bckftp01 -e "put $backup_file; exit"; then
statusftp01="Echec de l'envoie FTP vers $bckftp01"
else
statusftp01="Succes de l'envoie FTP vers $bckftp01"
fi
#On log le resultat
logger -t backup "$statusftp01"
#Envoie vers le ftp02
if ! lftp $bckftp02_user:$bckftp02_mdp@$bckftp02 -e "put $backup_file; exit"; then
statusftp02="Echec de l'envoie FTP vers $bckftp02"
else
statusftp02="Succes de l'envoie FTP vers $bckftp02"
fi
#On log le resultat
logger -t backup "$statusftp02"
#Deplacer le fichier dans pydio
if ! mv $backup_file $destdir; then
statusmv="Warning : Echec du déplacement de $backup_file dans Pydio"
else
statusmv="Fichier $backup_file déplacé dans Pydio"
fi
logger -t backup "$statusmv"
logger -t backup "########## Fin de la sauvegarde ##########"
exit 0</pre>
<p>Le script est planifié pour être lancé tous les dimanche à 5h00.
J'ai écris un 2nd script qui m'envoie un email avec les logs de la
sauvegarde afin que je puisse surveillé que tout c'est bien passé</p>
<pre>#!/bin/bash
#Envoie d'un mail suite à l'execution du script de sauvegarde
datejour=$(LC_ALL="en_EN.UTF-8" date "+%b %d")
grep backup /var/log/messages |grep "$datejour" | mail -s "Backup du mois de $(date "+%B")" adresse@email.com adresse2@email.com</pre>
<p>Petite explication sur le LC_ALL="en_EN.UTF-8"
Lorsque je tape</p>
<pre>date "+%b"</pre>
<p>J'obtiens la version courte et francisée du mois. Par exemple, pour le
mois de juillet, je vais avoir comme retour <em>juil</em>. Hors syslog lui
écris dans le fichier <em>/var/log/messages</em> en anglais. Ce qui donne pour
le mois de juillet : <em>jul</em> pour <em>july.</em> Pour pouvoir réussir mon grep
dans mon fichier de log, j'ai besoin de que la commande <em>date</em> me
retourne les informations en anglais également. C'est ce qui explique le
positionnement de cette variable en amont.</p>
<p>Ce second script est également placé dans un cron et est lancé a 5h15
tous les dimanches.</p>
Résolutions de début d'année2013-12-28T18:22:00+01:002013-12-28T18:22:00+01:00Aldevartag:blog.devarieux.net,2013-12-28:/2013/12/resolution-de-debut-dannee.html<p>En ce début d'année 2014, voici mes projets informatiques personnels
dont j'aimerai terminer la mise en œuvre rapidement.
Le problème n'est pas de réunir les compétences mais tout simplement
de prendre le temps de m'y mettre sérieusement pour enfin les terminer
proprement.</p>
<p><strong>1 - Terminer ma migration des services Google</strong>
J'ai …</p><p>En ce début d'année 2014, voici mes projets informatiques personnels
dont j'aimerai terminer la mise en œuvre rapidement.
Le problème n'est pas de réunir les compétences mais tout simplement
de prendre le temps de m'y mettre sérieusement pour enfin les terminer
proprement.</p>
<p><strong>1 - Terminer ma migration des services Google</strong>
J'ai déjà avec succès migré mes contacts, mon agenda et le stockage
cloud avec une instance OwnCloud. Le problème majeur reste la migration
des emails.
En effet, malgré les efforts fournis par les différents hébergeurs de
solutions mutualisées, je n'arrive toujours pas à avoir des emails qui
ne partent pas dans les boites spams de mes contacts qui utilisent des
webmails gmail, outlook ou yahoo.
Sans solutions pérennes rapidement, je me verrai peu être dans
l'obligation d'investir dans un serveur dédié. Bien plus cher, mais au
moins je maîtriserai le serveur SMTP.</p>
<p><strong>2 - Mettre en place un serveur de musique à la maison</strong>
L'ampli, les enceintes, la platine vinyle sont en place. Il me reste
à ajouter une solution simple pour lire de la musique numérique.
Pour l'instant, lorsque je veux écouter des fichiers FLAC ou
découvrir de nouveaux morceaux sur soundcloud, je débranche les RCA sur
la box et les branche sur un câble Jack/RCA. Ça fonctionne bien, mais ça
fait trainer un câble dans le salon. J'aimerai donc, avec les 3 ou 4 PC
portables qui ne fonctionnent plus et qui sont stockés à l'arrache dans
le bureau, monter un vrai PC portable, le plus silencieux possible, avec
un petit serveur MPD.
Avec ça et un client Android MPD, je pourrais gérer mes playlists
directement depuis mon canapé.</p>
<p><strong>3 - Changer de distribution</strong>
Cela devrait être fait rapidement. Pour l'instant, c'est Ubuntu qui
tourne sur le laptop. Cela fait environ 4 mois et pour être honnête, je
n'aime pas du tout (remarquez l'effort surhumain que je fais pour ne pas
dire "<strong>*C'est vraiment de la merde cette grosse bouse!!!!!*</strong>"). Je
pense revenir rapidement sous Mageia qui est ma distribution <em>out of the
box</em> favorite. Surtout depuis qu'elle supporte la technologie Optimus.</p>
Veille Open Source pour les pros2013-12-18T18:48:00+01:002013-12-18T18:48:00+01:00Aldevartag:blog.devarieux.net,2013-12-18:/2013/12/veille-open-source-pour-les-pros.html<p>Cela fait quelques temps que je suis ce site, édité par
<a href="http://www.smile.fr/">smile</a> (dont je vous conseil les livres
blancs), et je n'en ai pas beaucoup parlé autour de moi. Ajouté
récemment dans les flux RSS, il me permet de suivre l'actualité des
solutions open source professionnelles facilement.</p>
<p>Ce site,
c'est …</p><p>Cela fait quelques temps que je suis ce site, édité par
<a href="http://www.smile.fr/">smile</a> (dont je vous conseil les livres
blancs), et je n'en ai pas beaucoup parlé autour de moi. Ajouté
récemment dans les flux RSS, il me permet de suivre l'actualité des
solutions open source professionnelles facilement.</p>
<p>Ce site,
c'est <a href="http://www.open-source-guide.com/">open-source-guide.com</a>,
disponible également en <a href="http://www.open-source-guide.com/en">version
anglaise</a>. Il m'a permis de
découvrir plusieurs solutions open source dont je ne connaissais pas
l'existence. Un système de double notation permet de se rendre
rapidement compte de la fiabilité des produits (note smile et note des
utilisateurs).</p>
Owncloud et fail2ban derrière un reverse proxy2013-12-05T18:32:00+01:002013-12-05T18:32:00+01:00Aldevartag:blog.devarieux.net,2013-12-05:/2013/12/owncloud-et-fail2ban-derriere-un-reverse-proxy.html<p>Dans le <a href="https://blog.devarieux.net/2013/11/mise-en-oeuvre-de-fail2ban-pour-owncloudldap.html">dernier
article</a>,
j'expliquais comment mettre en place fail2ban sur son serveur pour
protéger son instance Owncloud lorsqu'elle est connectée sur un serveur
Ldap.</p>
<p>En général, lorsqu'on utilise un serveur Ldap pour l'authentification,
c'est qu'on se trouve en entreprise et les choses ne sont pas alors pas
si simple …</p><p>Dans le <a href="https://blog.devarieux.net/2013/11/mise-en-oeuvre-de-fail2ban-pour-owncloudldap.html">dernier
article</a>,
j'expliquais comment mettre en place fail2ban sur son serveur pour
protéger son instance Owncloud lorsqu'elle est connectée sur un serveur
Ldap.</p>
<p>En général, lorsqu'on utilise un serveur Ldap pour l'authentification,
c'est qu'on se trouve en entreprise et les choses ne sont pas alors pas
si simple. Par exemple, dans mon cas, le serveur owncloud ne se trouve
pas directement en frontale sur le net mais est caché derrière un
reverse proxy.</p>
<p>Du coup, le serveur owncloud ne voit qu'une seule IP : celle du reverse
proxy. La mise en place de fail2ban sur ce serveur poserait alors un
gros problème car cela reviendrait à faire bannir l'IP du reverse proxy
et interdire tout accès à owncloud depuis l’extérieur. Dans cet article,
nous allons donc voir comment corriger ce problème à l'aide de syslog.</p>
<section id="sur-le-serveur-owncloud">
<h2>Sur le serveur Owncloud</h2>
<section id="modification-d-owncloud">
<h3>Modification d'owncloud</h3>
<section id="configuration-du-serveur-owncloud">
<h4>Configuration du serveur owncloud</h4>
<p>Afin d’assurer une cohérence dans l’écriture des logs, il faut que la
timezone soit correctement configurée sur le serveur.</p>
<pre>[root@owncloud]# tzselect</pre>
<p>Création du fichier qui recevra les écritures des logs des échecs de
connexions :</p>
<pre>[root@owncloud]# touch /var/log/owncloud-fail.log
[root@owncloud]# chmod 660 /var/log/owncloud-fail.log
[root@owncloud]# chown root.apache /var/log/owncloud-fail.log</pre>
</section>
<section id="modification-du-backend-d-owncloud">
<h4>Modification du backend d'owncloud</h4>
<p>Dans le fichier <em>/var/www/html/owncloud/lib/user/database.php</em>, ligne
1. Dans la fonction <strong>checkPassword</strong>, entre le else et le return
false, insérez le code suivant :</p>
<pre>$headers = apache_request_headers();
$real_client_ip = $headers["X-Forwarded-for"];
$IPClient=$_SERVER['REMOTE_ADDR'];
openlog("owncloud", LOG_PID, LOG_LOCAL0);
syslog(LOG_WARNING, "Password check failed for: " . "$IPClient" . " " . "$real_client_ip");
closelog();</pre>
<p>Dans le fichier <em>/var/www/html/owncloud/apps/user_ldap/user_ldap.php</em>,
ligne 75. Dans la fonction <strong>checkPassword</strong>, entre le
if(count($ldap_users) < 1) { et le return false; insérez le code
suivant :</p>
<pre>if($uid!="admin") {
$headers = apache_request_headers();
$real_client_ip = $headers["X-Forwarded-For"];
$IPClient=$_SERVER['REMOTE_ADDR'];
openlog("owncloud", LOG_PID, LOG_LOCAL0);
syslog(LOG_WARNING, "Password check failed for: " . "$IPClient" . " " . "$real_client_ip");
closelog();</pre>
<p>Puis, en dessous du return false, fermez l’instruction if en ajoutant un</p>
<p><code>}</code></p>
<p>Toujours dans le même fichier, ligne 97, juste après
<strong>if(!$this→areCredentialsValid($dn, $password)) {</strong> Et au-dessus du
<strong>return false;</strong> correspondant ajouter le code suivant :</p>
<pre>$headers = apache_request_headers();
$real_client_ip = $headers["X-Forwarded-For"];
$IPClient=$_SERVER['REMOTE_ADDR'];
openlog("owncloud", LOG_PID, LOG_LOCAL0);
syslog(LOG_WARNING, "Password check failed for: " . "$IPClient" . " " . "$real_client_ip");
closelog();</pre>
</section>
<section id="explication-du-code">
<h4>Explication du code</h4>
<pre>$headers = apache_request_headers()</pre>
<p>Récupère l’entête des requêtes http venant du reverse proxy sous forme
de tableau</p>
<pre>$real_client_ip = $headers[ "X-forwarded-For "] ;</pre>
<p>Récupère l’adresse IP réelle du client dans le tableau $headers</p>
<pre>$IPClient = $_SERVER[‘REMOTE_ADDR’] ;</pre>
<p>Récupère l’adresse IP du client. Si le client vient de l’extérieur du
SIB, cette IP sera celle du reverse proxy.</p>
<p>Openlog, Syslog et closelog sont les fonctions PHP pour écrire les
échecs de connexions en passant par syslog.</p>
</section>
</section>
<section id="configuration-de-rsyslog">
<h3>Configuration de rsyslog</h3>
<section id="log-locaux">
<h4>Log locaux</h4>
<p>Pour loguer les échecs de connexion venant d’owncloud, il faut dire à
rsyslog ce qu’il doit faire avec ces entrées. On crée pour cela un
fichier supplémentaire <em>/etc/rsyslog.d/owncloud.conf</em> contenant une
seule ligne :</p>
<pre>local0.* /var/log/owncloud-fail.log</pre>
<p>Ainsi, tous les messages reçus sur l’interface LOCAL0 de rsyslog seront
redirigé vers le fichier <em>/var/log/owncloud-fail.log</em></p>
</section>
<section id="log-distant">
<h4>Log distant</h4>
<p>Le serveur owncloud ne peut pas bannir lui-même les IP car il ne voit
que l’IP du reverse proxy pour toutes les connexions venant de
l’extérieur. Il faut donc remonter les logs des échecs de connexions
vers le reverse proxy qui bannira lui-même les IP. On crée pour cela un
nouveau fichier de configuration de rsyslog :
<em>/etc/rsyslog.d/fail2ban.conf</em>.</p>
<pre>local0.* @nomdevotrereverse.proxy:514</pre>
<p>Ceci a pour effet d’envoyer tous les messages reçu sur l’interface
LOCAL0 de rsyslog vers le service syslog du reverse proxy.</p>
</section>
</section>
<section id="prise-en-compte-des-modifications">
<h3>Prise en compte des modifications</h3>
<p>On redémarre le service rsyslog</p>
<pre>/etc/init.d/rsyslog restart</pre>
<p>Afin de voir si les modifications effectuées n’ont pas générée d’erreur
:</p>
<pre>grep rsyslog /var/log/messages</pre>
</section>
</section>
<section id="sur-le-reverse-proxy">
<h2>Sur le reverse proxy</h2>
<section id="configuration-de-syslog">
<h3>Configuration de syslog</h3>
<p>Par défaut, le service syslog n’écoute pas le réseau et ne peut donc pas
recevoir de logs distants. Pour corriger cela, on édite le fichier
<em>/etc/sysconfig/syslog</em>. Modification de la ligne SYSLOGD_OPTIONS en
ajoutant l’option –r</p>
<pre>SYSLOGD_OPTIONS="-r -m 0"</pre>
<p>Puis, on relance le service afin d’activer l’écoute réseau :</p>
<pre>/etc/init.d/syslog restart</pre>
</section>
<section id="configuration-de-fail2ban">
<h3>Configuration de fail2ban</h3>
<section id="installation">
<h4>Installation</h4>
<p>L’installation se fait simplement par le gestionnaire de paquet :</p>
<pre>yum install fail2ban</pre>
</section>
<section id="configuration-de-la-prison">
<h4>Configuration de la prison</h4>
<p>On édite pour cela le fichier <em>/etc/fail2ban/jail.conf</em> et on y ajoute
les lignes suivantes :</p>
<pre>[owncloud]
enabled = true
port = https
filter = owncloud
action = iptables[name=httpd,port=https,protocal=all]
logpath = /var/log/messages
maxretry = 5</pre>
<p>Toutes les autres prisons peuvent être positionnées sur enabled = false
puisque nous n’en avons pas besoin ici.</p>
</section>
<section id="creation-du-filtre">
<h4>Création du filtre</h4>
<p>Dans la configuration du jail, nous avons dit à fail2ban d’utiliser le
filtre owncloud, nous allons maintenant créer le filtre :</p>
<p>Création du fichier <em>/etc/fail2ban/filter.d/owncloud.conf</em></p>
<pre>[Definition]
failregex = Password check failed for: ip.du.reverse.proxy <HOST>
ignoreregex =</pre>
<p>Puisque nous ne souhaitons que bannir les IP externes, nous ne
récupérons que les lignes qui contiennent l’IP du reverse proxy ET l’IP
réelle du client. Le ligne ignoreregex n’est pas nécessaire mais il faut
tout de même qu’elle soit présente afin que fail2ban valide la
configuration.</p>
</section>
<section id="demarrage-du-service">
<h4>Démarrage du service</h4>
<p>On lance le service fail2ban :</p>
<pre>/etc/init.d/fail2ban start</pre>
<p>Si le lancement tombe en échec, c’est qu’il y a un problème de
configuration. Pour repérer ce problème, il faut lancer le daemon à la
main :</p>
<pre>fail2ban-server</pre>
<p>Puis on lance un reload du client qui va tester pour nous la
configuration</p>
<pre>fail2ban-client reload</pre>
<p>S’il y a une erreur, cette commande nous le dira.</p>
</section>
<section id="test-de-la-configuration">
<h4>Test de la configuration</h4>
<p>Afin de tester la valididité de la regex, fail2ban propose l’outil
fail2ban-regex. Créer pour cela quelques échecs de connexion et tester
avec la commande :</p>
<pre>fail2ban-regex /var/log/messages /etc/fail2ban/filter.d/owncloud.conf</pre>
<pre>Running tests
=============
Use regex file : /etc/fail2ban/filter.d/owncloud.conf
Use log file : /var/log/messages
Results
=======
Failregex
|- Regular expressions:
| [1] Password check failed for: ip.du.reverse.proxy <HOST>
|
`- Number of matches:
[1] 6 match(es)
Ignoreregex
|- Regular expressions:
|
`- Number of matches:
Summary
=======
Addresses found:
[1]
X.X.X.X (Thu Dec 05 10:02:11 2013)
X.X.X.X (Thu Dec 05 10:05:24 2013)
X.X.X.X (Thu Dec 05 10:05:34 2013)
X.X.X.X (Thu Dec 05 10:05:42 2013)
X.X.X.X (Thu Dec 05 10:05:47 2013)
X.X.X.X (Thu Dec 05 10:05:53 2013)
Date template hits:
18154 hit(s): MONTH Day Hour:Minute:Second
Success, the total number of match is 6
However, look at the above section 'Running tests' which could contain important info</pre>
</section>
</section>
</section>
Mise en oeuvre de Fail2Ban pour Owncloud/Ldap2013-11-27T20:30:00+01:002013-11-27T20:30:00+01:00Aldevartag:blog.devarieux.net,2013-11-27:/2013/11/mise-en-oeuvre-de-fail2ban-pour-owncloudldap.html<p>Si vous stockez des données personnelles ou à caractères sensibles sur
votre serveur owncloud, vous souhaitez sans doute que les malandrins
s'aventurant à tester vos couples <em>Login / Mot de passe</em> par brutforce
soient éjectés de votre serveur après un certains nombre de tentatives
infructueuses.</p>
<p>Fail2Ban fera le travail pour vous …</p><p>Si vous stockez des données personnelles ou à caractères sensibles sur
votre serveur owncloud, vous souhaitez sans doute que les malandrins
s'aventurant à tester vos couples <em>Login / Mot de passe</em> par brutforce
soient éjectés de votre serveur après un certains nombre de tentatives
infructueuses.</p>
<p>Fail2Ban fera le travail pour vous, mais pour cela, il a besoin que les
échecs de connexions soient logués, ce qu'Owncloud ne fait
malheureusement pas. Il faut donc, avant de mettre en oeuvre Fail2Ban,
procéder à quelques modifications dans le code d'Owncloud.</p>
<p>Vous trouverez beaucoup d'article vous expliquant comment faire cela
avec une connexion classique via la base de donnée d'Owncloud, par
exemple
<a href="http://www.dataparadis.net/osp/gnu-linux-server/cloud-server/owncloud-and-fail2ban-update/">ici</a>.
Dans cet article, nous verrons plutôt comment régler le problème
lorsqu'on utilise une authentification via un serveur Ldap.</p>
<section id="preparer-le-terrain">
<h2>Préparer le terrain</h2>
<p>Afin d'assurer une cohérence dans l'écriture des logs, il faut que la
timezone soit correctement configurée sur le serveur. Vous pouvez faire
cela à l'aide de la commande :</p>
<pre>[root@server1]# tzselect</pre>
<p>On va ensuite, créer le fichier qui servira à loguer les échecs de
connexions</p>
<pre>[root@server1]# touch /var/log/owncloud-fail.log
[root@server1]# chmod 660 /var/log/owncloud-fail.log
[root@server1]# chown root.apache /var/log/owncloud-fail.log</pre>
</section>
<section id="modification-du-backend-d-owncloud">
<h2>Modification du backend d'Owncloud</h2>
<p>Dans le fichier lib/user/database.php, ligne 202. Dans la fonction
checkPassword, entre le <strong>else</strong> et le <strong>return false</strong>, insérez le code
suivant :</p>
<pre>$today = new DateTime();
date_timezone_set($today, timezone_open('Europe/Paris'));
$IPClient=$_SERVER['REMOTE_ADDR'];
$logAuth=fopen('/var/log/owncloud-fail.log', 'a+');
fputs($logAuth, date_format($today, 'Y/m/d H:i:s') . " Password check failed for: \t" . $IPClient . "\n");
fclose($logAuth);</pre>
<p>Dans le fichier apps/user_ldap/user_ldap.php, ligne 75. Dans la
fonction checkPassword, entre le <strong>if(count($ldap_users) < 1)
{</strong> et le <strong>return false;</strong> insérez le code suivant :</p>
<pre>if($uid!="admin") {
date_default_timezone_set('Europe/Paris');
$today = date("Y/m/d H:i:s");
$IPClient=$_SERVER['REMOTE_ADDR'];
$logAuth=fopen('/var/log/owncloud-fail.log', 'a+');
fputs($logAuth, $today . " Password check failed for: \t" . $IPClient . "\n");
fclose($logAuth);</pre>
<p>Puis, en dessous du return false, fermez l'instruction if en ajoutant un</p>
<pre>}</pre>
<p><strong>Explication du code :</strong></p>
<p>Il y a un utilisateur qui est inscrit en base de donnée et qui n'est pas
dans le ldap, c'est l'admin d'owncloud. Afin ne ne pas loguer une
connexion de l'utilisateur 'admin' en tant qu'erreur de connexion, il
est nécessaire de vérifier que que c'est pas cet utilisateur qui se
connecte. D'où le <strong>if($uid!="admin"){}</strong>. Veillez à modifier cette
valeur suivant la votre.</p>
<p>La variable <strong>$ldap_users</strong> est un tableau contenant la liste des
utilisateurs qui correspondent à la valeur saisie dans le login. Si
cette table est vide, alors il y aura un échec de connexion logué.</p>
<p>Le dernier ajout à faire se trouve un petit peu plus bas dans ce
fichier, ligne 97, juste en dessous
de <strong>if(!$this->areCredentialsValid($dn, $password)) {</strong> et au dessus
de <strong>return false;</strong>ajoutez le code suivant :</p>
<pre>date_default_timezone_set('Europe/Paris');
$today = date("Y/m/d H:i:s");
$IPClient=$_SERVER['REMOTE_ADDR'];
$logAuth=fopen('/var/log/owncloud-fail.log', 'a+');
fputs($logAuth, $today . " Password check failed for: \t" . $IPClient . "\n");
fclose($logAuth);</pre>
</section>
<section id="configuration-de-fail2ban">
<h2>Configuration de Fail2Ban</h2>
<p>Dans votre fichier /etc/fail2ban/jail.conf (ou équivalent suivant votre
distribution) :</p>
<pre>[Owncloud]
enabled = true
port = http,https
filter = owncloud
logpath = /var/log/owncloud-fail.log
maxretry = 5</pre>
<p>Et enfin, le fichier de filtre /etc/fail2ban/filter.d/owncloud.conf</p>
<pre># /etc/fail2ban/filter.d/owncloud.conf
#
# Fail2Ban configuration file
# Owncloud
#
[Definition]
# Option: failregex
failregex = <HOST>$</pre>
<p>Relancez fail2ban et le tour est joué.</p>
</section>
Remboursement de licence Windows 8 sur portable ASUS - Episode 22013-10-19T17:51:00+02:002013-10-19T17:51:00+02:00Aldevartag:blog.devarieux.net,2013-10-19:/2013/10/remboursement-de-licence-windows-8-sur-portable-asus-episode-2.html<section id="la-vertu-de-la-patience">
<h2>La vertu de la patience</h2>
<p>Suite et fin de ce <a href="http://blog.devarieux.net/2013/07/remboursement-de-licence-windows-8-sur-portable-asus/">premier
article</a>
sur la procédure de remboursement de licence Windows de mon nouveau
portable. Il m'a fallu patienter quelques temps avant de devoir les
relancer pour savoir où en était la procédure.</p>
<p>J'avais en effet envoyé mon dossier complet par …</p></section><section id="la-vertu-de-la-patience">
<h2>La vertu de la patience</h2>
<p>Suite et fin de ce <a href="http://blog.devarieux.net/2013/07/remboursement-de-licence-windows-8-sur-portable-asus/">premier
article</a>
sur la procédure de remboursement de licence Windows de mon nouveau
portable. Il m'a fallu patienter quelques temps avant de devoir les
relancer pour savoir où en était la procédure.</p>
<p>J'avais en effet envoyé mon dossier complet par email le 26 Juillet. Le
28 Août, n'ayant toujours aucune nouvelles, je leur ai envoyé ce mail de
relance :</p>
<blockquote>
Bonjour,
Je me permets de revenir vers vous concernant cette demande de
remboursement.
Je vous ai envoyé les documents il y a un petit peu plus d'un mois
et je n'ai pas reçu de nouvelle de votre part.
Pouvez-vous me dire quel est le délai généralement constaté dans le
traitement de ces dossiers?
Cordialement,</blockquote>
<p>Et le jour même, je recevais cette réponse de leur part :</p>
<blockquote>
<p>Bonjour monsieur,</p>
<p>Je vous remercie.</p>
<p>Je vous joins maintenant en pièce jointe, le formulaire pré rempli
que vous devrez vérifier, dater puis signer et me le retourner en
retour de ce mail s’il vous plaît.</p>
<p>En vous souhaitant une bonne journée,</p>
</blockquote>
<p>Le jour même, je leur renvoyais le document, toujours par email,
rempli et signé.
Le 17 Septembre, mon dossier montait enfin en compta.</p>
<blockquote>
<p>Bonjour monsieur,</p>
<p>Je vous remercie.</p>
<p>Je remonte votre document au centre de comptabilité.</p>
<p>En vous souhaitant une bonne journée,</p>
</blockquote>
<p>Et le 10 Octobre, j'ai enfin reçu mon virement de 42€.</p>
</section>
<section id="bilan-de-l-operation">
<h2>Bilan de l'opération</h2>
<p>D'après cette petite expérience, le remboursement de licence Windows
chez Asus ce fait plutôt facilement. Pas besoin de renvoyer le PC. Il
faut juste leur écrire assez rapidement (au max 3 semaines après
l'achat) et être assez patient.</p>
<p>J'ai lancé la procédure le 16 Juillet et reçu le virement le 10 Octobre.
Il a donc fallu environ 3 mois pour aller au bout de l'opération.</p>
<p><img alt="asus-ACF-COA" class="m-image" src="/images/asus-ACF-COA-300x92.png" /></p>
<p>Je me suis tout de même heurté à un petit problème lors du premier
démarrage de la machine. Je souhaitais démarrer sur l'OS Windows afin
pouvoir refuser le CLU. Il est impossible de refuser le CLU. Vous ne
pouvez que l'accepter. La seul solution a été de rebooter le PC (hard
reboot via le bouton Power).</p>
<p>Il ne faut surtout pas démarrer sur la partition Windows. Ceci risque
d'activer la licence de l'OS, son remboursement devenant alors
impossible.</p>
</section>
Remboursement de licence Windows 8 sur portable ASUS - Episode 12013-07-25T19:14:00+02:002013-07-25T19:14:00+02:00Aldevartag:blog.devarieux.net,2013-07-25:/2013/07/remboursement-de-licence-windows-8-sur-portable-asus.html<p>Il y a 10 jours, j'ai fait l'acquisition d'un nouvel ultra-book. Un Asus
Zenbook UX32VD-R4020H pour être précis. Une belle bête, avec un core i5
@ 1.70Ghz, 4go de RAM, technologie Optimus (un chipset Intel HD intégré
au processeur et une carte graphique Nvidia 620M quand la machine a
besoin …</p><p>Il y a 10 jours, j'ai fait l'acquisition d'un nouvel ultra-book. Un Asus
Zenbook UX32VD-R4020H pour être précis. Une belle bête, avec un core i5
@ 1.70Ghz, 4go de RAM, technologie Optimus (un chipset Intel HD intégré
au processeur et une carte graphique Nvidia 620M quand la machine a
besoin d'un peu plus de puissance graphique), un SSD de 24Go pour
installer l'OS et un disque dur de 500GO pour la data. Le tout avec un
écran 13.3" 1080p.</p>
<p>Évidemment, la machine est livrée avec un Windows 8 préinstallée. J'ai
donc entrepris de me faire rembourser l'OS OEM par Asus.</p>
<p>Pour cela, il y a une adresse email de contact qui est
<a href="mailto:acf_coa@asus.com">acf_coa@asus.com</a>. Voici le mail que je leur ai envoyé le Mardi 16
Juillet :</p>
<blockquote>
<p>Bonjour,</p>
<p>Je viens de faire l'acquisition d'un Ultrabook Asus Zenbook
UX32VD-R4020H.
Je suis très content de cet achat, cependant, je ne souhaite pas
conserver le système d'exploitation Windows 8 qui ne me convient
pas.</p>
<p>Je n'ai pas encore démarré la machine. Pourriez-vous me donner la
procédure afin d'obtenir le remboursement de la licence Windows 8.</p>
<p>Vous trouverez la facture d'achat en PJ de cet email.</p>
<p>Cordialement,</p>
</blockquote>
<p>Le Jeudi 25 Juillet, je recevais une réponse d'Asus avec la procédure à
suivre et les documents à fournir pour me faire rembourser.</p>
<blockquote>
<p>Bonjour cher client,</p>
<p>Vous avez sollicité nos services pour demander le remboursement de
la licence OEM Windows 8 liée à votre produit.</p>
<p>Dans un premier temps je vais vous demander de me fournir tous les
éléments ci-dessous afin de pouvoir constituer votre dossier et
pré-remplir un formulaire qui vous sera ensuite renvoyé pour
signature.</p>
<p>Merci donc de me fournir par retour de mail :</p>
<p>- Nom et prénom du propriétaire de la machine.</p>
<p>- N° de téléphone.</p>
<p>- Adresse e-Mail.</p>
<p>- Adresse postale complète.</p>
<p>- N° de série du produit ASUS (visible sur la carte de
garantie et/ou sous votre machine, sur un autocollant).</p>
<p>- Copie de la facture d’achat.</p>
<p>- Une copie de la page 1 de votre « carte de garantie ASUS
» (fournie avec tous produit ASUS).</p>
<p>o Cette page contient une étiquette avec un code barre et le n° de
série du produit.</p>
<p>o Cette page est également à remplir par le propriétaire du
produit.</p>
<p>- Facultatif : une photo de l’étiquette du produit avec le
numéro de série visible (située sous le produit ou sur le chargeur
du produit) Ces éléments me permettront entre autres d’identifier la
clé de licence Windows 8 liée à votre appareil.</p>
<p>Une fois ces éléments en ma possession je vous ferais donc parvenir
votre « formulaire de demande de remboursement de la licence
Microsoft » préalablement rempli qu’il vous faudra confirmer, dater
et signer à la main puis me renvoyer par mail ou par courrier postal
(adresse de nos locaux sur les documents joints). Ce premier
document contient : conditions générales, détails de procédures,
formulaire et engagements contractuels.</p>
<p>Nous tenons cependant à vous signaler que ce document a pour but de
couvrir tous les cas de figure et que de fait, il est possible que
certaines étapes de procédure ou certaines mentions ne soient pas
pertinentes sur votre dossier (exple : le point 2.e des conditions
générales ne concerne pas la plupart de nos dossiers puisque le n°
de RMA est rempli par nos services)</p>
<p>Je joins a ce courrier le second formulaire, « procédure de paiement
», qui doit impérativement être rempli informatiquement et
signé/daté à la main. En effet ces documents administratifs sont
traités en partie automatiquement et ne peuvent l’être si l’écriture
est manuelle, en revanche pour des raisons légales la signature du
client doit être manuelle.</p>
<p>Ce formulaire permettra de procéder au remboursement par virement
une fois la procédure dûment remplie et validée par les 2 partis.</p>
<p>Afin de pouvoir vous assurer un traitement fluide et les meilleurs
délais, nous vous invitons à répondre à nos e-mails au plus vite,
merci également de prendre note que nos services n’effectuerons pas
de relance systématique en cas d’absence de réponse et ne pourront
être tenus responsables en cas d’échec de la procédure pour des
raisons de délais ne pouvant nous être incombés.</p>
<p>Je reste toutefois à votre disposition pour toute autre information
complémentaire.</p>
<p>En vous souhaitant une bonne journée.</p>
</blockquote>
<p>La procédure de remboursement semble donc relativement simple. En tout
cas, c'est bien partie.</p>
<p>En plus de ça, le document à remplir, dans lequel il faut mettre son RIB
(code IBAN et BIC) est fourni au format ODT. Un bon point encore pour
Asus.</p>
<p>Je vous tiendrai au courant de l'avancement de la procédure via ce blog.</p>
HP Proliant Support Pack sur RHEL 52013-07-23T18:07:00+02:002013-07-23T18:07:00+02:00Aldevartag:blog.devarieux.net,2013-07-23:/2013/07/hp-proliant-support-pack-sur-rhel-5.html<p>Dans le cadre de mon travail, je suis en train d'installer et de
configurer un serveur HP System Insight Manager (SIM). Une sorte de
Nagios amélioré pour serveur HP, avec anticipation des pannes matériel.</p>
<p>Ce serveur SIM nous a permis par exemple de détecter qu'une pile de
cache RAID était …</p><p>Dans le cadre de mon travail, je suis en train d'installer et de
configurer un serveur HP System Insight Manager (SIM). Une sorte de
Nagios amélioré pour serveur HP, avec anticipation des pannes matériel.</p>
<p>Ce serveur SIM nous a permis par exemple de détecter qu'une pile de
cache RAID était en train de lâcher et nous avons donc pu remplacer
cette pile avant que le problème intervienne (pas de cache RAID = temps
d'accès en écriture tout moisi et ça le fait moyen sur un serveur de
sauvegarde).</p>
<p>Pour que le serveur HPSIM accède aux serveurs qu'il surveille, il faut
installer un agent. Cet agent, c'est HP Proliant Support Pack. Une suite
d'utilitaires et de pilotes pour serveur HP Proliant.</p>
<p>J'ai donc téléchargé l'iso <a href="http://h18004.www1.hp.com/products/servers/service_packs/en/index.html">sur le site
d'HP. </a>Celle
ci contient les utilitaires pour tous les OS supportés (Windows, RedHat,
HP-UX). Une fois l'iso transférée sur le serveur, je la monte :</p>
<pre>mkdir /media/iso
mount -o loop /tmp/fichier.iso /media/iso</pre>
<p>Ensuite, c'est l'utilitaire HPSUM qui va s'occuper d'installer les
différents modules et utilitaires.</p>
<pre>cd /media/iso/hp/swpackages/
./hpsum</pre>
<p>Cette commande utilise un serveur X.
| Pour info, la doc complète : <a href="http://bizsupport1.austin.hp.com/bc/docs/support/SupportManual/c03114114/c03114114.pdf">Guide de l'Utilisateur, HP Smart Update
Manager</a></p>
<p>En suivant les étapes une à une, les packages sont tous compilés et
installés.</p>
<section id="aie">
<h2>Aïe</h2>
<p>Malheureusement, parfois, tout ne tourne pas rond et dans mon cas,
certains paquets n'ont pas pu être compilés. Les logs montrent un obscur
message de problème de dépendance avec ksym.</p>
<p>Pour résoudre ce problème et terminer l'installation des paquets, voici
la procédure ;</p>
<p>Installation des sources :</p>
<pre>cd /media/iso/hp/swpackages/
rpm -ivh <paquet>.src.rpm
rpmbuild -bb /usr/src/redhat/SPECS/<paquet>.spec
rpm -ivh --nodeps /usr/src/redhat/RPMS/<arch>/<paquet>.rpm</pre>
<p>On vérifie que le module a bien été installé :</p>
<dl>
<dt>::</dt>
<dd>modinfo <nomdumondule></dd>
</dl>
<p>On charge le module :</p>
<dl>
<dt>::</dt>
<dd>modprobe <nomdumodule></dd>
</dl>
<p>Ce qui donne, avec le paquet qla4xxx qui me concernait :</p>
<pre>rpm -ivh hp-qla4xxx-<version>.src.rpm
rpmbuild -bb /usr/src/redhat/SPECS/hp-qla4xxx.spec
rpm -ivh --nodeps /usr/src/redhat/RPMS/x86_64/kmod-hp-qla4xxx-<version>-x86_64.rpm
modprobe qla4xxx</pre>
</section>
<section id="explication">
<h2>Explication</h2>
<p>Les RPM utilisent les dépendances de KMP (Kernel Module Packaging) pour
s'assurer que les binaires RPM puissent être installés. Red Hat
maintient une liste blanche de <em>kernel symbols</em> (ksym donc) que les
RPM utilisent. Certains de ses symboles peuvent être dans le kernel mais
pas dans la liste blanche. Le résultat est que certains RPM, qui y font
référence, ne peuvent pas être installés.</p>
<p>L'utilisateur doit donc utiliser l'option "--nodeps" lors de
l'installation des binaires.</p>
<p>La paquet qla4xxx utilisent les symboles suivant sur RHEL 5 qui ne sont
pas dans la liste blanche ;</p>
<p>ksym(kobject_uevent_env) ksym(iscsi2_session_chkready)
ksym(pci_get_domain_bus_and_slot)</p>
</section>
Comment vais-je me passer des services de Google?2013-06-26T21:31:00+02:002013-06-26T21:31:00+02:00Aldevartag:blog.devarieux.net,2013-06-26:/2013/06/comment-vais-je-me-passer-des-services-de-google.html<p>Ça faisait quand même un moment qu'on s'en doutait, Snowden nous l'a
confirmé. Tous les plus grands services en ligne américains mettent
quasi à disposition les données qu'ils possèdent sur leurs utilisateurs
aux services gouvernementaux des USA. Cela pose plusieurs problèmes.
Certains sont d'ordre individuel, d'autres d'ordre politique,
économique, diplomatique …</p><p>Ça faisait quand même un moment qu'on s'en doutait, Snowden nous l'a
confirmé. Tous les plus grands services en ligne américains mettent
quasi à disposition les données qu'ils possèdent sur leurs utilisateurs
aux services gouvernementaux des USA. Cela pose plusieurs problèmes.
Certains sont d'ordre individuel, d'autres d'ordre politique,
économique, diplomatique voir même en exagérant un peu, pose un problème
de civilisation.</p>
<p>Individuellement, je ne suis pas vraiment d'accord à ce que des gens,
auxquels je n'ai pas donné accès à mes données, puissent les consulter
sans mon avis. Je n'ai rien à cacher, mais ce n'est pas non plus une
raison pour que je partage mon agenda avec n'importe qui et qu'il puisse
voir la date, l'heure et le lieu de mon RDV avec mon proctologue.</p>
<p>Et même si je n'ai rien à cacher, je n'ai pas non plus envie qu'en cas
de problème avec les autorités mes communications et
agissements électroniques puissent être utilisé contre moi. J'utilise
actuellement les services suivant chez Google, très pratique parce
qu'ils sont synchronisé avec mon smartphone Android : Gmail, Google+,
Agenda, Drive, Maps. Autant dire que ma vie est stockée sur les serveurs
de Google, quelque part dans les nuages.</p>
<p>Le récent scandale PRISM m'a fait mettre le nez dans ma propre merde.
Grand défenseur des LL, je me suis laissé happer par la facilité
d'utilisation des services de Google. D'un autre coté, je ne veux pas
non plus disparaître des radars sur Internet pour la simple et bonne
raison que je veux contrôler mon identité en ligne. Je ne veux pas que
ce soit les autres qui décident des liens qui ressortiront sur Google
lorsqu'on y tape mon nom. Pour cela, il faut que je contrôle ma présence
en ligne. Le blog est donc là pour ça.</p>
<p>Économiquement, j'imagine que les grandes entreprises françaises ainsi
que certaines plus petites mais innovantes et qui utilisent activement
les services de Google, Yahoo ou même le cloud d'Amazon pour les
entreprises doivent être en train de serrer les fesses. Il devient
facile pour la NSA et la CIA de faire de l'espionnage à
grande échelle et à peu de frais (théorie du complot powered).</p>
<p>La question qui se pose maintenant, c'est de savoir comment sortir de
tous ces services. Tant qu'on n'entre pas dans les prisons dorées de
Google ou Apple, il est relativement aisé de trouver des solutions
alternatives. Par contre, une fois qu'on y a mis les 2 pieds, ça devient
plus compliqué d'en sortir parce qu'il est nécessaire de migrer toutes
les données correctement et surtout ne rien oublier.</p>
<p>Pour ma part, j'ai la chance d'avoir un bagage technique qui me permet
de savoir mettre en place et gérer un serveur. La solution passera donc
certainement par Owncloud pour tout ce qui concerne l'agenda, les
contacts, le stockage de photos. Pour les mails, ça se complique, j'en
ai déjà fait l’expérience. J'ai essayé d'envoyer quelques mails avec mon
ancien domaine (aldevar.fr). Ceux ci finissaient souvent dans la boite à
spam de mes destinataires. En plus de ça, même si j'arrive à régler ce
problème, la très grande majorité de mes contacts utilisent Gmail ainsi
que des smartphones Android. Donc, même si je décide de supprimer mes
données perso des serveurs de Google, le géant du web aura toujours mes
données grâce à mes amis qui synchronisent leurs contacts
et reçoivent mes emails.</p>
<p>Ouais, je sais, c'est ballot...</p>
Good Bye Bouygues Telecom2012-11-02T16:00:00+01:002012-11-02T16:00:00+01:00Aldevartag:blog.devarieux.net,2012-11-02:/2012/11/good-bye-bouygues-telecom.html<p>Cela faisait quelques temps que je souhaitais quitter Bouygues Telecom
pour la téléphonie. En fait, c'est surtout depuis l'arrivée de Free et
ses forfaits à 20€. J'étais toujours engagé chez eux jusqu'à Aout 2013,
il m'était donc difficile, financièrement parlant, de partir comme ça.</p>
<section id="demenagement-sur-les-dents">
<h2>Déménagement sur les dents</h2>
<p>J'avais en …</p></section><p>Cela faisait quelques temps que je souhaitais quitter Bouygues Telecom
pour la téléphonie. En fait, c'est surtout depuis l'arrivée de Free et
ses forfaits à 20€. J'étais toujours engagé chez eux jusqu'à Aout 2013,
il m'était donc difficile, financièrement parlant, de partir comme ça.</p>
<section id="demenagement-sur-les-dents">
<h2>Déménagement sur les dents</h2>
<p>J'avais en plus groupé mon forfait téléphone et Internet chez eux, avec
une offre BBox Fibre. Donc, lors de mon déménagement en Septembre 2012
et puisque leur offre Fibre fonctionnait plutôt bien dans l'ensemble,
j'ai procédé au déménagement de ma ligne Fibre à ma nouvelle adresse,
non sans les avoir appelés 3 fois avant afin de m'assurer que mon
nouveau logement était bien relié à la fibre. "Oui oui" m'a t'on dit à
plusieurs reprises.</p>
<p>Ainsi, le 24 Septembre, un technicien devait se présenter pour nous
raccorder. Le technicien n'est pas venu (classique). J'ai pris ma plus
grosse voix pour appeler le service client et demander des explications
: "Ha mais vous n'êtes pas relié à la fibre monsieur, le rendez-vous à
été annulé le 16 Septembre".</p>
<p>Ok, donc merci de m'avoir prévenu pour le rendez-vous annulé, ça fait
plaisir...! À la place de l'offre fibre, j'ai donc droit à une offre
imbattable de 4Mb/s à la place des 100Mb/s que j'avais avant. Et
attention, je ne paierais même pas plus cher, ils me le font
gracieusement au même prix... Ahem... Comment vous dire...? Je pense
plutôt que je vais résilier mon offre Internet Fibre et aller chez
Numéricable.</p>
</section>
<section id="choisir-un-nouveau-forfait-telephone">
<h2>Choisir un nouveau forfait téléphone</h2>
<p>Puisque je quittais l'offre Bbox, il me fallait choisir un forfait de
téléphonie. Je pensais pouvoir simplement revenir vers l'offre que j'ai
toujours eu, soit 2h d'appel + appels illimités le soir + sms illimité +
3G avec 2Go de fair use. Pour environ 35€ par mois avec smartphone
subventionné.</p>
<p>Malheureusement, ce type de forfait n'existe plus et j'avais le choix
entre une offre 'Tout illimité + 3Go de fair use à 42Mbps' à 60€ ou une
offre avec 'Tout illimité + 500Mo de fair use à 7.2Mbps'. Je consomme un
peu plus de 1.5Go de data par mois sur mon Nexus S, donc il me fallait
une offre avec au moins 3Go de data. Cela signifiait payer 60€ par mois,
juste pour le téléphone alors que c'est ce que je payais avant pour
Téléphone + Internet Fibre.</p>
<p>Il me restait un peu moins d'un an d'engagement. Je me suis donc dit que
c'était le bon moment pour partir à moindre frais.</p>
<p>J'ai choisi l'offre Eden 1h. Pas de data, pas de SMS, rien. Juste 1h
d'appel. De suite après avoir souscris à ce mini forfait, je me suis
rendu sur le site de B&You pour faire l'acquisition d'une nouvelle carte
SIM avec un forfait tout illimité à 20€. La somme que je dois à Bouygues
pour pouvoir partir est donc de (14€ x 10 mois)/3 = 35€. Somme remboursé
en 1 mois.</p>
</section>
<section id="et-maintenant">
<h2>Et maintenant?</h2>
<p>Bon, oui, je vais maintenant devoir acheter moi même mes smartphones.</p>
<p>Ici aussi, faisons un rapide calcul.</p>
<p>Avec le forfait à 60€ de chez Bouygues et smartphone subventionné,
j'aurais payé à l'année, smartphone non compris : <strong>60*12 = 720€</strong></p>
<p>Avec le forfait à 20€ de chez B&You et un smartphone à 349€ (par
exemple, le LG Nexus 4 16G), cela me fera à l'année : <strong>20*12 + 349 =
589€</strong> (En considérant que je change de smartphone une fois par an, ce
qui n'est pas le cas. (bon ok, je change tous les 18 mois...)).</p>
<p>J'économise donc environ <strong>130€</strong>, sans compter que chez Bouygues et son
forfait à 60€, il faut au minimum débourser 50 ou 80€ pour un smartphone
dernier cri subventionné.</p>
<p>Quand je pense qu'on s'est fait pigeonner (pour le dire poliment)
pendant toutes ses années...</p>
</section>
To bulle or not to bulle2012-05-22T19:39:00+02:002012-05-22T19:39:00+02:00Aldevartag:blog.devarieux.net,2012-05-22:/2012/05/to-bulle-or-not-to-bulle.html<p>On s'y attendait plus ou moins, les investisseurs n'ont pas vraiment
confiance, pour l'instant en tout cas, en Facebook et sa capacité à
générer des revenus. Le titre FB a eu du mal à se maintenir pour son
premier jour de cotation Vendredi 18 Mai puis a dévissé complètement le …</p><p>On s'y attendait plus ou moins, les investisseurs n'ont pas vraiment
confiance, pour l'instant en tout cas, en Facebook et sa capacité à
générer des revenus. Le titre FB a eu du mal à se maintenir pour son
premier jour de cotation Vendredi 18 Mai puis a dévissé complètement le
Lundi 21 en perdant plus de 11 % de sa valeur d'introduction. Cependant,
tout n'est pas aussi simple qu'il n'y paraît.</p>
<p>Les libristes crient victoire à coup de « Je vous l'avais bien dit »
mais la raison de la déroute du titre au NASDAQ n'est pas uniquement
liée à la confiance que peux générer la société de Paolo Alto. En effet,
la banque d'investissement Morgan Stanley, qui a géré en grande partie
l'introduction en bourse, a joué la gourmande en demandant une
introduction du prix du titre à 38USD, après un prix d'achat la veille à
34USD. Las ! Les acheteurs potentiels n'ont pas suivi, estimant ce prix
bien trop élevé par rapport à la valeur supposée de Facebook.</p>
<p>L'action s'est difficilement maintenue à 38USD Jeudi grâce aux
perfusions de Morgan Stanley, qui a racheté les titres en vente avant la
fin de clôture afin de maintenir artificiellement l'action au prix
d'introduction, pour la modique somme de 2 milliards de $. Bien sûr, la
banque ne pouvait conserver une telle stratégie éternellement et le
lendemain, c'était la déroute avec 11 % de perte, alors que les autres
valeurs technologique (Google et Apple notamment) se maintenaient ou
progressaient.</p>
<p>A l'origine de tout cela, la banque avait décidé d'augmenter le nombre
de titre en vente, fournissant à certains de ses investisseurs jusqu'à
40 % de titre en plus que ce qu'ils avaient demandé. La réaction ne
s'est donc pas faite attendre et ceux-ci ont rapidement remis en vente
les titres en trop, ce qui explique en grande partie un tel fiasco pour
l'action FB.</p>
<p>A l'heure où j'écris ces lignes, peu de temps avant la cloture du marché
US, le titre perd 2 % alors qu'il en perdait encore 4,5 % il y a moins
d'une heure. Cette remontée (ou cette limitation des pertes) est encore
sans doute due à des rachats d'urgence par les banques ayant gérées
cette introduction en bourse.</p>
<p>Comment alors essayer de comprendre ce que peut valoir l'entreprise
Facebook ? Pour l'instant cela est très compliqué car seulement basé sur
des spéculations pures. Nous avons l'habitude de voir en Facebook une
boite noire ne dévoilant que très peu de chiffre, notamment concernant
ses revenus. Mais tout cela va changer car cette introduction en bourse
oblige Facebook à publier ses résultats détaillés régulièrement. Nous
allons enfin savoir comment Facebook gagne son argent et surtout quelle
proportion de cet argent est gagné par la publicité ciblée. C'est
seulement à partir de ce moment que nous pourrons juger de la pérénité
de son modèle économique.</p>
<p>Seulement voilà, ceux qui lisent ces lignes savent en majorité de quoi
est fait l'internet. Les enseignes vont et viennent. Myspace, skyblog ne
sont déjà plus que de lointain souvenir. Facebook is so 2007. Valoriser
la société à hauteur de 100 milliards de $ (soit un chiffre astronomique
de 133$ par utilisateur comme le <a href="http://frederic.bezies.free.fr/blog/?p=7511">relève si bien frédéric
Bezies</a>)est un pari
risqué. Cela nous rappel les heures sombres de l'internet et la bulle du
début des années 2000. Plus que les 100 Millards de Facebook, le chiffre
qui pour moi représente le plus le risque d'une nouvelle bulle, c'est le
rachat, toujours par Facebook, décidemment dans tous les bons coups,
d'Instagram pour 1 Millards. Rappelons juste qu'Instagram génère 0€ de
chiffre (en dollars, ça fait 0 aussi, ainsi qu'en pesos ou en rouble).</p>
<p>Les trentenaires et les quarantenaires sont actuellement tous ou presque
sur Facebook. Leurs enfants devraient en toute logique fuir ce réseau à
moins que Zuckerberg trouve une solution miracle pour contourner cette
obsolescence programmée. Google a trouvé la solution en se diversifiant
à outrance et en proposant une multitude de services extrêmement
pratique. Facebook a un autre défi à relever, les plus grands étant de
se détacher de son image de réseau social et surtout de capitaliser sur
ces utilisateurs.</p>
<p>La pub sur intenet ne fonctionne pas. Ce n'est pas moi qui le dit.
Général Motor a en effet décidé de retirer ses publicités de Facebook à
cause d'un retour sur investissement trop faible. Pas étonnant. Les
utilisateurs ont pris l'habitude de contourner visuellement les
publicités, que ce soit avec ou sans filtre publicitaire. D'autant plus
que les pubs sont toujours affichées aux mêmes endroits. Quand on
fréquente un site 2 ou 3h par jour, on prend vite le reflex de ne pas
'voir' ces emplacements.</p>
<p>Les services gratuits ont donc du mal à trouver des modèles économiques
viables sur le long terme. Comme lors de la première bulle. Cette fois
ci, les investisseurs sont plus prudent. L'introduction en bourse de
Facebook a permis d'ouvrir les yeux sur le risque de cette nouvelle
bulle. Plutôt que d'investir des quantités astronomiques d'argent dans
des startups, celle-ci sont rachetées par les grands groupes que sont
Facebook, Google, Apple, Microsoft, IBM, Intel et compagnie afin
d'acquérir leurs technologies.</p>
<p>Le danger actuel se situe peut être plus dans les guerres stériles de
brevets, qui font perdre du temps, de l'argent et empêchent les petites
startups de se développer sur les idées novatrices. Ceci risque de
nécroser le developpement du net et ralentir son developpement. Cette
problématique mériterait un article dédié, nous en reparlerons donc dans
un prochain billet.</p>
Lettre ouverte à Google2011-08-11T10:22:00+02:002011-08-11T10:22:00+02:00Aldevartag:blog.devarieux.net,2011-08-11:/2011/08/lettre-ouverte-a-google.html<p>Cher Google,</p>
<p>Je me souviens encore de notre première rencontre il y a une douzaine
d’années.</p>
<p>Douze ans, dans l’informatique, c’est long. Sur Internet c’est même une
éternité! En douze ans, nous somme passé du 56kb au 100Mb (1700 fois
plus rapide!!), des pages persos avec …</p><p>Cher Google,</p>
<p>Je me souviens encore de notre première rencontre il y a une douzaine
d’années.</p>
<p>Douze ans, dans l’informatique, c’est long. Sur Internet c’est même une
éternité! En douze ans, nous somme passé du 56kb au 100Mb (1700 fois
plus rapide!!), des pages persos avec fond d’écran Matrix aux sites
‘régie publicitaire’, des frames et tableaux au CSS et HTML5 etc. Quels
sont les sites que j’utilisais en 1999 et que j’utilise encore
maintenant? Caramail? Multimania? Voilà? Ahem… Non en fait, à part toi,
il n’y en a pas.</p>
<p>A la rentrée scolaire 1999 donc, un professeur m’avait parlé de toi. Je
dois avouer que je suis de suite tombé amoureux de ton interface. Quelle
sobriété! Quelle efficacité! Un logo, une zone de saisie, un bouton.
Avec mon modem RTC c’était un vrai plaisir à utiliser. Et surtout, quand
je faisais une recherche, j’avais les réponses que j’attendais. Je me
demandais même comment d’autres pouvaient encore utiliser Lycos (qu’est
devenu ce beau labrador noir d’ailleurs?), Altavista, Yahoo et
compagnie. Enfin bref, j’étais comblé.</p>
<p>Aujourd’hui encore, je ne vois pas comment je pourrais me passer de ton
moteur de recherche. Il est devenu un réflexe, il est <a href="https://web.archive.org/web/20120418043655/http://www.slate.fr/story/41367/google-memoire">ma
mémoire</a>.</p>
<p>En 2004, tu m’as surpris en te diversifiant. Gmail est arrivé. J’ai
obtenu rapidement une invitation, j’étais content. Voilà donc 8 ans que
Gmail est ma messagerie principale. Pourtant, j’utilisais Hotmail qui me
convenait parfaitement… Enfin… sauf pour les spams, la lenteur de
l’interface et le fait que ce soit du Microsoft. J’avais déjà migré
depuis 2 ans sur GNU/Linux donc je n’étais pas mécontent de me
débarrasser définitivement de cette adresse email. Au niveau du tri du
spam, y’a pas à tortiller, tu étais vraiment le meilleur et de loin.</p>
<p>J’apprécie aussi le fait que tu n’ais jamais changé brutalement. Tes
interfaces ont évolué, petit à petit, discrètement, sans jamais être
révolutionnées et ainsi perdre les utilisateurs qui ont vite fait de ne
plus savoir où cliquer.</p>
<p>Dorénavant, mon smartphone est également propulsé grâce à toi. Tu
m’envoies mes mails instantanément, tu me géolocalises, tu me permets
d’accéder à certaines informations dont je n’avais auparavant accès
qu’en étant chez moi. Maintenant, dans le train, le temps passe plus
vite. Je blogue, je commente, je discutes, je lis les dernières news,
tout ça en me déplaçant. La fonction top moumoute étant quand même la
synchronisation des contacts entre mon téléphone et Gmail.</p>
<p>J’ai mis du temps à me mettre aux flux RSS. Si il y a bien une
technologie où je ne suis pas un<em>early adopter</em>, c’est celle là. J’ai
commencé par utiliser un client lourd (liferea), puis je me suis rendu
compte que ce n’était pas pratique du tout puisque quand je rentrais
chez moi le soir, je retrouvais dans mon application les mêmes articles
que j’avais déjà lu dans la journée. Je suis donc passé à… Google
Reader. C’est vrai qu’il y a moult solutions équivalentes que je n’ai
pas pris la peine de tester par flemmardise.</p>
<p>Le 1er Juillet j’obtenais mon invitation pour Google+. Enfin un réseau
social qui me convient! Bon… Diaspora* aurait pu faire l’affaire mais
les méthodes de développement employées et la lenteur de l’interface
m’ont fait abandonner le projet malgré l’engouement initial.
Contrairement à Facebook, j’ai enfin l’impression de maîtriser mon
identité numérique. Peu à peu, mes amis m’y rejoignent, l’activité qui y
règne est enthousiasmante et surtout la masse de boulets n’a pas encore
débarqué (ce qui arrivera bien un jour où l’autre).</p>
<p>Alors quoi? Je t’aurais écrit cette lettre juste pour lister les
services que tu me proposes et que j’utilise? Non bien sûr!</p>
<p>Mon cher Google, tu es devenu petit à petit mon interface d’accès au
web. Tu connais tout de moi, ce que je fais, où je vais, ce que j’aime,
ce que je découvre. Tu possèdes les clés de mon identité. Je sais
comment tu utilises ces données et pour l’instant, cela me convient. Je
te fais confiance pour à l’avenir ne pas utiliser ces données à des fins
moins glorieuses. Je te fais confiance pour reconnaître tes erreurs
quand tu en commettras, comme tu l’as déjà fait par le passé. Pour tout
cela, moi et tous les autres utilisateurs seront vigilant afin que le
pire ne se produise pas.</p>
Le web 2.0 est-il une idiocratie?2011-07-24T19:37:00+02:002011-07-24T19:37:00+02:00Aldevartag:blog.devarieux.net,2011-07-24:/2011/07/le-web-2-0-est-il-une-idiocratie.html<p>Comme moi, vous venez peut-être d'une génération qui a grandi en ligne
avant le boom des réseaux sociaux. Internet était alors une chambre
secrète que peu de personnes avaient visité. Nous trollions avant que ce
soit appelé 'troller' et nous le faisions plus pour l'exercice
intellectuel que pour se divertir …</p><p>Comme moi, vous venez peut-être d'une génération qui a grandi en ligne
avant le boom des réseaux sociaux. Internet était alors une chambre
secrète que peu de personnes avaient visité. Nous trollions avant que ce
soit appelé 'troller' et nous le faisions plus pour l'exercice
intellectuel que pour se divertir. Une de mes premières expériences
enrichissantes venant d'Internet était un logiciel qui permettait de
voir et d'envoyer des emails sur les newsgroups. L'activité qui y
régnait était très enrichissante et c'est sans doute cette expérience là
qui m'a poussé à me diriger vers l'informatique.</p>
<p>Je me rappelle les discussions enflammées sur les chatrooms. ASV les
gens? Évidemment, ce n'était qu'une question de temps avant que 'le
peuple' ne débarque en masse sur le réseau. En attendant, je me faisais
mes premiers 'amis internet'. Nous n'avions pas ou très peu d'ami IRL
avec qui discuter sur le net.</p>
<p>Pas mal de monde considère que Myspace représente la chute d'Internet et
ils n'ont pas tout à fait tort. Il faut avouer que Myspace était plutôt
sympa et permettait de rencontrer pas mal de musiciens. Ceux-ci
pouvaient recevoir des avis/critiques sur leurs musiques. Quand Myspace
a commencé à mourir, il n'y avait plus cette communauté centrale pour
les musiciens. Ce qui s'en approche le mieux aujourd'hui est sans doute
<a href="http://www.soundcloud.com/">Soundcloud</a>. Myspace a ouvert les vannes
de l'Internet à pas mal d'idiots. Difficile de nier qu'avec la création
de Myspace le QI général des internautes a subit une forte chute.</p>
<p>L'internet devenait une sorte de centre commercial fantaisiste, avec
pleins d'icônes dégueulasses et de lumières clignotantes. Avec la
création de Twitter, le web2 entamait sa création. Est arrivé Facebook
qui a définitivement tué Myspace et qui a introduit les apps. Mais
Facebook s'est vite transformé en la peur que nous avons tous de la
'conspiration Orwellienne'. Avec l'avènement de l'Iphone et d'Android,
Facebook est devenu une sorte de passage obligé vers le monde numérique.
Un peu comme AOL a pu l'être pendant un temps.</p>
<p>Il y a un espoir que Google+ mette fin à ce monopole de Facebook sur les
réseaux sociaux. Je ne pense pas que G+ fasse tant que ça de concurrence
à Twitter. Le réseau de microblogging a beaucoup participé à faire de
l'Internet une affaire populaire et je pense qu'il va encore vivre
longtemps. Peut-être que je me trompe et qu'Internet n'est pas devenu
une idiocratie comme cela semble être le cas avec Facebook. En tant que
personnes ayant utilisé Internet dans ses premiers jours, nous avons
grandi, mûri, et nous devons utiliser nos connaissances numériques pour
accompagner une nouvelle génération.</p>
RHEL 5.5 et chipset broadcom BCM57092010-06-28T19:36:00+02:002010-06-28T19:36:00+02:00Aldevartag:blog.devarieux.net,2010-06-28:/2010/06/rhel-5-5-et-chipset-broadcom-bcm5709.html<p>Nous avons récemment installé une nouvelle machine qui sert de serveur
principal pour notre nouveau système de sauvegarde. Lors des tests des
sauvegardes complètes du week end, le chipset réseau du serveur
s'écroulait lamentablement sous la charge du nombre de paquets qui
arrivaient. Même si le réseau semblait toujours fonctionnel …</p><p>Nous avons récemment installé une nouvelle machine qui sert de serveur
principal pour notre nouveau système de sauvegarde. Lors des tests des
sauvegardes complètes du week end, le chipset réseau du serveur
s'écroulait lamentablement sous la charge du nombre de paquets qui
arrivaient. Même si le réseau semblait toujours fonctionnel (service
réseau lancé, ifconfig ne signal rien d'anormal), la machine était
injoignable et ne répondait pas au ping. Dans certains cas, un
redémarrage du service réseau ne suffit pas à retrouver une
connectivité.</p>
<p>A l'heure où la sauvegarde s'arrêtait, voici ce qu'on pouvait trouver
dans /var/log/messages :</p>
<pre>server1 kernel: NETDEV WATCHDOG: eth0: transmit timed out
server1 kernel: bnx2: eth0 NIC Copper Link is Down</pre>
<p>La résolution du problème passe par une mise à jour du pilote. On trouve
le pilote pour ce chipset à cette page :
<a class="m-link-wrap" href="http://www.broadcom.com/support/ethernet_nic/netxtremeii.php">http://www.broadcom.com/support/ethernet_nic/netxtremeii.php</a> Après avoir
extrait l'archive, on installe les sources :</p>
<pre>rpm -ivh netxtreme2-<version>.src.rpm</pre>
<p>Installation de kernel-devel pour pouvoir compiler les sources du
pilotes :</p>
<pre>yum install kernel-devel</pre>
<p>Construction du paquet :</p>
<pre>cd /usr/src/redhat
rpm -bb SPECS/netxtreme2.spec</pre>
<p>Installation du paquet fraichement installé :</p>
<pre>rpm -ivh RPMS/<arch>/netxtreme2-<version>.<arch>.rpm</pre>
<p>déchargement de l'ancien module :</p>
<pre>rmmode bnx2</pre>
<p>Chargement du nouveau module :</p>
<pre>modprobe bnx2</pre>
<p>Suite à cette petite manipulation, plus de soucis de chipset réseau qui
ne répond plus. Problème résolu :D</p>
QRQVB : Protocole TCP2010-02-02T07:00:00+01:002010-02-02T07:00:00+01:00Aldevartag:blog.devarieux.net,2010-02-02:/2010/02/qrqvb-protocole-tcp.html<p>Nouvelle QRQVB et pas des moindres, le protocole TCP (Transmission
Control Protocol, Protocole de Contrôle de Transmission). Comme son
petit frère UDP, TCP se situe en couche 4 du <a href="https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=232">modèle
OSI</a>.</p>
<section id="caracteristique-de-tcp">
<h2>Caractéristique de TCP</h2>
<p>TCP est bien plus compliqué qu’UDP examiné au <a href="https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=493">chapitre
précédent</a>.
Il apporte en contrepartie des …</p></section><p>Nouvelle QRQVB et pas des moindres, le protocole TCP (Transmission
Control Protocol, Protocole de Contrôle de Transmission). Comme son
petit frère UDP, TCP se situe en couche 4 du <a href="https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=232">modèle
OSI</a>.</p>
<section id="caracteristique-de-tcp">
<h2>Caractéristique de TCP</h2>
<p>TCP est bien plus compliqué qu’UDP examiné au <a href="https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=493">chapitre
précédent</a>.
Il apporte en contrepartie des services beaucoup plus élaborés.</p>
<ul>
<li>TCP contient un mécanisme pour assurer <strong>le bon acheminement des
données</strong>. Cette possibilité est absolument indispensable dès lors
que les applications doivent transmettre de gros volumes de données
de façon fiable. Cette fonction est assurée par un mécanisme
d’acquittement (ou accusé de réception). Les paquets de données sont
acquittés de bout en bout et non de point à point. C’est à dire que
ce sont les machines sources et machines de destinations qui
s’occupent de cela et non les routeurs qui se situent entre les 2.</li>
<li>Le protocole TCP permet l’établissement d’un <strong>circuit virtuel</strong>
entre les 2 machines qui échangent de l’information (Voir a ce propos
le <a href="https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=528#comment-757">commentaire de
Guizmo.7</a>).
On dit aussi que TCP fonctionne en <strong>mode connecté</strong> (par opposition
à UDP qui est en mode non connecté). En pratique, l’une des 2 machine
doit effectuer un appel que l’autre doit accepter. S’en suit une
discutions afin d’établir certains paramètres de communication. Une
fois les préliminaires terminés, les protocoles informent les
applications respectives que la connexion est établie et que le
transfert peut débuter. Durant le transfert, le dialogue entre les
protocoles continue, pour vérifier le bon acheminement des données.</li>
<li>TCP a la capacité de <strong>mémoriser les données</strong>. Les paquets pouvant
prendre chacun un chemin différent pour arriver à destination, il
arrive que ceux ci n’arrivent pas dans le bon ordre. Grâce à cette
capacité de mémorisation, TCP garde les paquets un certains temps et
les reconstitue lorsqu’ils sont tous arrivés afin de présenter les
données à l’application.</li>
<li>TCP simule une connexion en <strong>« full duplex »</strong>. Pour chacune des 2
machines en connexion, l’opération qui consiste à lire des données
peut s’effectuer indépendamment de celle qui consiste à en écrire.</li>
</ul>
</section>
<section id="entete-tcp">
<h2>Entête TCP</h2>
<div class="m-image">
<a href="/images/enteteTCP1.png"><img src="https://blog.devarieux.net/images/enteteTCP1.png" /></a>
</div>
<p>L’entête TCP est codé sur 20 octets hors options.</p>
<ul>
<li>Port Source (16 bits): Port utilisé par l’application sur la machine
source.</li>
<li>Port Destination (16 bits): Port de destination.</li>
<li>Numéro d’ordre (32 bits): Correspond au numéro du paquet. Cette
valeur permet de situer à quel endroit du flux de données le paquet,
qui est arrivé, doit se situer par rapport aux autres paquets.</li>
<li>Numéro d’accusé de réception (32 bits): Acquittement pour les paquets
reçus. Cette valeur signale le prochain numéro de paquet attendu. Par
exemple, si il vaut 1500, cela signifie que tous les datagrammes
<1500 ont été reçus</li>
<li>Offset (4 bits): Le champ Offset est codé sur 4 bits et définit le
nombre de mots de 32 bits dans l’entête TCP. Ce champ indique donc où
les données commencent.</li>
<li>Réservé (6 bits): Champ inutilisé actuellement. Il était à l’origine
prévu pour l’avenir. On peut dire aujourd’hui que ce champ restera
vide.</li>
<li>Drapeaux (flags) (6×1 bit): Les drapeaux représentent des
informations supplémentaires :
URG: si ce drapeau est à 1 le paquet doit être traité de façon
urgente.
ACK: si ce drapeau est à 1 le paquet est un accusé de réception.
PSH (PUSH): si ce drapeau est à 1, le paquet fonctionne suivant la
méthode PUSH.
RST: si ce drapeau est à 1, la connexion est réinitialisée.
SYN: Le Flag TCP SYN indique une demande d’établissement de
connexion.
FIN: si ce drapeau est à 1 la connexion s’interrompt.</li>
<li>Fenêtre (16 bits): Champ permettant de connaître le nombre d’octets
que le récepteur souhaite recevoir sans envoyer d’accusé de
réception.</li>
<li>Somme de contrôle (Checksum ou CRC): La somme de contrôle est
réalisée en faisant la somme des champs de données de l’en-tête, afin
de pouvoir vérifier l’intégrité de l’en-tête</li>
<li>Pointeur d’urgence (16 bits): Indique le numéro d’ordre à partir
duquel l’information devient urgente.</li>
</ul>
</section>
<section id="etablissement-dune-connexion">
<h2>Établissement d’une connexion</h2>
<div class="m-image">
<a href="/images/ConnectionTCP.png"><img src="https://blog.devarieux.net/images/ConnectionTCP.png" /></a>
</div>
<p>Une ouverture de connexion TCP s’effectue en 3 temps.</p>
<p>L’émetteur du premier paquet doit avoir connaissance du couple
<strong>`IP <https://web.archive.org/web/20110919035256/http://blog.aldevar.fr/?p=293>`__
: Port</strong> de l’application de la machine réceptrice (par exemple, on
contact un serveur HTTP sur le port 80 qui lui est dédié). L’émetteur de
ce premier paquet est à l’origine de l’établissement du circuit virtuel.
C’est une attitude qualifiée de « <strong>cliente</strong>« .</p>
<p>Le récepteur du premier paquet accepte l’établissement de la connexion,
ce qui suppose qu’il était prêt à le faire avant que le client en prenne
l’initiative. C’est une attitude de « <strong>serveur</strong>« .</p>
<p>Le client envoie un segment comportant le drapeau SYN à 1. Le serveur
répond avec sa propre séquence (SYN = 1) mais il doit aussi acquitter le
paquet précédent, ce qu’il fait avec ACK. Le client répond alors avec un
acquittement de la séquence du serveur (ACK = 1).</p>
<p>Une fois achevée cette phase appelée « Three-way handshake », les 2
applications sont en mesure d’échanger des données.</p>
</section>
Rapport de stage sur la mise en place de Squid et Egroupware2010-01-06T15:05:00+01:002010-01-06T15:05:00+01:00Aldevartag:blog.devarieux.net,2010-01-06:/2010/01/rapport-de-stage-sur-la-mise-en-place-de-squid-et-egroupware.html<p>J’ai longuement hésité à mettre ce rapport de stage en ligne pour
plusieurs raisons. Tout d’abord, ce rapport n’est pas vraiment
représentatif du travail fournit. La majorité des solutions expliquées
m’ont demandées beaucoup de temps de recherche et d’arrachage de cheveux
(notamment pour la migration …</p><p>J’ai longuement hésité à mettre ce rapport de stage en ligne pour
plusieurs raisons. Tout d’abord, ce rapport n’est pas vraiment
représentatif du travail fournit. La majorité des solutions expliquées
m’ont demandées beaucoup de temps de recherche et d’arrachage de cheveux
(notamment pour la migration des comptes sous Lotus Notes). Ensuite, la
qualité rédactionnel est loin d’être au rendez-vous. On m’a beaucoup
reproché que ce rapport était trop technique et c’est plutôt vrai.
Enfin, ce document ne décrit pas vraiment l’installation de Squid et
d’Egroupware. Ces parties sont survolées et je m’attarde plus sur la
résolution des problèmes rencontrés (résoudre un conflit de schéma LDAP
quand on a jamais vu OpenLDAP de sa vie n’est pas chose aisée).</p>
<p>Un mois après la fin de la formation, je me décide tout de même à le
mettre en ligne. Je pense que ce rapport décrit plutôt bien ce que peut
être le métier de technicien réseau dans une administration ou une PME.
Le problème lors de la mise en place d’un nouveau service n’est pas
l’installation et la configuration de ce service mais la migration des
anciens services utilisés vers les nouveaux. Surtout lorsque l’ancien
service est un système propriétaire vieillissant (Je veux parler ici de
Lotus Notes 5).</p>
<p><a href="https://web.archive.org/web/20110722200015/http://www.squid-cache.org/">Squid</a>
est un proxy http très utilisé, dont j’ai pu découvrir une partie des
possibilités.
<a href="https://web.archive.org/web/20110722200015/http://www.egroupware.org/">Egroupware</a>
est un groupware fournissant un agenda, un client mail, un carnet
d’adresses, un système de réservations des ressources et plusieurs
autres choses, le tout dans une interface web. Je vous invite à tester
la <a href="https://web.archive.org/web/20110722200015/http://www.stylite.de/egroupware_demo_login">demo sur le site du
projet.</a></p>
<p>Ce rapport fait 38 pages et voici son sommaire:</p>
<ol>
<li><strong>Remerciements</strong></li>
<li><strong>Objectif du stage</strong></li>
<li><p><strong>L’entreprise</strong></p>
<ol>
<li>Historique</li>
<li>La structure actuelle</li>
<li>Le service informatique</li>
</ol>
</li>
<li><p><strong>Spécifications</strong></p>
<ol>
<li>Environnement de travail</li>
<li>L’existant</li>
<li><p>Besoins et contraintes</p>
<ol>
<li><em>Squid</em></li>
<li><em>Egroupware</em></li>
</ol>
</li>
</ol>
</li>
<li><p><strong>Mise en œuvre</strong></p>
<ol>
<li><p>Proxy</p>
<ol>
<li><em>Planning prévisionnel</em></li>
<li><p><em>Mise en œuvre</em></p>
<ol>
<li>Squid</li>
<li>Sarg</li>
<li>Squidguard</li>
</ol>
</li>
<li><em>Problèmes rencontrés</em></li>
<li><em>Annexes</em></li>
</ol>
</li>
<li><p>eGroupware</p>
<ol>
<li><em>Schéma fonctionnel</em></li>
<li><em>Planning previsionnel</em></li>
<li><p><em>Mise en œuvre</em></p>
<ol>
<li>Configuration de openldap</li>
</ol>
</li>
<li><p><em>Problèmes rencontrés</em></p>
<ol>
<li>Conflit de schéma openldap</li>
<li>Configuration de felamimail</li>
</ol>
</li>
<li><p><em>Préparation de la migration des utilisateurs</em></p>
<ol>
<li>Création du carnet d’adresses principal</li>
<li>Importation des agendas Lotus Notes</li>
<li>Importation des carnet d’adresse Lotus Notes</li>
<li>Exportation des mails depuis LotusNotes dans eGroupware</li>
<li>Importation mail depuis roundcube</li>
</ol>
</li>
<li><em>Annexes</em></li>
</ol>
</li>
</ol>
</li>
<li><p><strong>Procédure de migration serveur</strong></p>
<ol>
<li>Sur Revy</li>
<li>Sur Revnew</li>
</ol>
</li>
</ol>
<p><a href="http://blog.devarieux.net/wp-content/uploads/2015/08/RapportDeStage-Squid-Egroupware.pdf">RapportDeStage-Squid-Egroupware</a></p>
QRQVB : Les paquets UDP2009-12-29T11:23:00+01:002009-12-29T11:23:00+01:00Aldevartag:blog.devarieux.net,2009-12-29:/2009/12/qrqvb-les-paquets-udp.html<p>Suite de la Question Réseau Qui Va Bien, nouveau billet purement réseau
donc. Je comptais me lancer dans la description des paquets TCP, mais je
pense qu’il est plus intéressant de se pencher d’abord sur UDP avant
d’appréhender TCP.</p>
<p>UDP (Pour <em>User Datagram Protocol</em>) se situe dans …</p><p>Suite de la Question Réseau Qui Va Bien, nouveau billet purement réseau
donc. Je comptais me lancer dans la description des paquets TCP, mais je
pense qu’il est plus intéressant de se pencher d’abord sur UDP avant
d’appréhender TCP.</p>
<p>UDP (Pour <em>User Datagram Protocol</em>) se situe dans la couche 4 du <a href="http://blog.devarieux.net/2009/08/qrqvb-le-modele-osi/">modèle
OSI</a> (couche
transport). Pour rappel, au niveau de la couche 3 (IP), <a href="http://blog.devarieux.net/2009/09/qrqvb-datagramme-ip/">les
datagrammes</a>
sont routés d’une machine à une autre en fonction des adresses IP (en
fait, le routage se fait en fonction de l’adresse réseau, voir <a href="http://blog.devarieux.net/2009/09/309/">QRQVB :
L’adresse IP</a>). Lors de cette
opération de routage, aucune distinction n’est faite entre les
différents services pour lesquels ces paquets peuvent être destinés. Que
ce soit pour une connexion SSH (port 22) ou HTTP (port 80) ou autre, les
datagrammes IP sont tous indifféremment mélangés.</p>
<p>La couche 4 du modèle OSI ajoute un mécanisme qui permet
l’identification du service concerné. Plusieurs programmes de plusieurs
utilisateurs pouvant simultanément circuler sur le réseau, il est
indispensable de faire un tri entre les applications. Ici, l’idée est
d’associer la destination du paquet à une fonction. L’identification de
cette fonction ce fait à l’aide d’un chiffre nommé <strong>Port</strong>.</p>
<section id="en-tete-udp">
<h2>En tête UDP</h2>
<div class="m-image">
<a href="/images/encaps.png"><img src="https://blog.devarieux.net/images/encaps.png" /></a>
</div>
<p>Lors de l’étude des <a href="qrqvb-datagramme-ip.html">datagramme
IP</a>, nous
avions vu le contenu de l’entête du paquet (partie verte). Ici, nous
allons observer le contenu de l’entête du message (partie jaune) lorsque
l’on traite un p>aquet UDP.</p>
<p>Le paquet UDP est composé de 8 octets.</p>
<div class="m-image">
<a href="/images/entete.png"><img src="https://blog.devarieux.net/images/entete.png" /></a>
</div>
<p><strong>Les 2 premiers octets contiennent le port source</strong>. Codé sur 16 bits
donc. C’est le numéro de port de l’émetteur du paquet. C’est aussi le
numéro de port sur lequel le destinataire doit envoyer sa réponse.</p>
<p><strong>Les octets 3 et 4 stockent le port de destination.</strong> C’est sur ce port
que sera remis le paquet lors de sa livraison à la machine ciblée.</p>
<p>Le port étant un entier positif de 16 bits, on en déduit que les bornes
sont 0 – 65535 (2^16). Cependant, le port 0 n’est pas exploitable.</p>
<p><strong>Les octets 5 et 6 contiennent la longueur de l’entête UDP</strong> et du
message. Sa longueur minimal est 8 (entête UDP avec 0 données à
transporter) et sa longueur maximal 2^16 = 65535 (64ko).</p>
<p><strong>Les 2 derniers octets contiennent le cheksum</strong>. C’est la somme de
contrôle de l’entête UDP et des données qui suivent.</p>
</section>
<section id="ports-reserves">
<h2>Ports réservés</h2>
<p>Toute machine qui utilise la pile TCP/IP se doit de connaitre un
certains nombre de services bien connus, aussi appelé « well known port
number » pour pouvoir dialoguer avec les autres machines sur internet.
Sur une machines Unix, cette liste est placée dans le fichier
<strong>*/etc/services*</strong> et se doit d’être lisible par tous les utilisateurs
et toutes les applications. Voici un extrait du contenu de ce fichier :</p>
<pre>Nom Port/Protocol Commentaire
netstat 15/tcp
qotd 17/tcp quote
msp 18/tcp # message send protocol
msp 18/udp
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
ftp-data 20/tcp
ftp 21/tcp
fsp 21/udp fspd
ssh 22/tcp # SSH Remote Login Protocol
ssh 22/udp
telnet 23/tcp
smtp 25/tcp mail
time 37/tcp timserver
time 37/udp timserver
rlp 39/udp resource # resource location
nameserver 42/tcp name # IEN 116
whois 43/tcp nicname
tacacs 49/tcp # Login Host Protocol (TACACS)
tacacs 49/udp
re-mail-ck 50/tcp # Remote Mail Checking Protocol
re-mail-ck 50/udp
domain 53/tcp # name-domain server
domain 53/udp
mtp 57/tcp # deprecated
tacacs-ds 65/tcp # TACACS-Database Service
tacacs-ds 65/udp
bootps 67/tcp # BOOTP server
bootps 67/udp
bootpc 68/tcp # BOOTP client
bootpc 68/udp
tftp 69/udp
gopher 70/tcp # Internet Gopher
gopher 70/udp
rje 77/tcp netrjs
finger 79/tcp
www 80/tcp http # WorldWideWeb HTTP
www 80/udp # HyperText Transfer Protocol</pre>
<p>Les ports 1 à 1023 sont réservés aux « well known ports ». Ils ne
peuvent être utilisés que par des applications qui s’exécutent avec des
droits privilégiés (root). Les autres ports peuvent être utilisés
librement sans privilège particulier et sont en général employés par les
applications clientes. Par exemple, sur ma machine, en ce moment, mon
client IRC utilise le port 59175 pour communiquer avec le serveur irc
holmes.freenode.net.</p>
</section>
<section id="mode-non-connecte">
<h2>Mode non connecté</h2>
<p>Contrairement à TCP, UDP est conçu pour permettre un échange de données
entre 2 applications sans échange préliminaire. UDP est utilisé si les
données à transmettre n’ont pas besoin d’être fragmentées en plusieurs
paquet. La paquet est ainsi envoyé sans s’assurer qu’il arrive bien à
destination. UDP est appelé mode de transport non connecté par
opposition à TCP. Plus particulièrement, les paquets a destination d’une
application UDP sont conservés dans une pile de type FIFO. Si
l’application destinatrice ne les “consomme” pas assez rapidement, les
plus anciens paquets risquent d’être écrasés par les plus récents… Un
risque supplémentaire de perte de données.</p>
<p>Nous verrons comment TCP peut palier à ce problème dans la prochaine
QRQVB</p>
</section>
GNU/Linux : Résolution de problèmes2009-12-25T19:34:00+01:002009-12-25T19:34:00+01:00Aldevartag:blog.devarieux.net,2009-12-25:/2009/12/gnulinux-resolution-de-problemes.html<p>Une grande partie du travail sur les forums concernant les logiciels
libres est d'obtenir plus d'informations sur les problèmes des novices.
Il est très agréable d'aider les autres comme il peut être assez agaçant
d'essayer d'aider quelqu'un qui ne montre aucun effort pour s'aider
lui-même. Je ne pense pas que …</p><p>Une grande partie du travail sur les forums concernant les logiciels
libres est d'obtenir plus d'informations sur les problèmes des novices.
Il est très agréable d'aider les autres comme il peut être assez agaçant
d'essayer d'aider quelqu'un qui ne montre aucun effort pour s'aider
lui-même. Je ne pense pas que cela soit dû à de la fainéantise de la
part de celui qui pose la question. C'est simplement parce que les
novices ne connaissent pas les premières étapes de résolution des
problèmes sur GNU/Linux et ne savent pas quels types d'informations
rechercher ni comment les obtenir. J'espère que ce petit guide sera
utile pour ceux qui font leurs premiers pas sur linux.</p>
<section id="i-diagnostiquer-soi-meme">
<h2>I - Diagnostiquer soi-même</h2>
<section id="la-premiere-etape-est-la-collecte-d-informations">
<h3>1 - La première étape est la collecte d'informations.</h3>
<p>Si un programme plante ou ne fait pas ce qu'il est censé faire, il faut
se poser et réfléchir calmement.</p>
<p>Ouvrez un nouveau fichier dans votre éditeur de texte favori et
écrivez-y ce que vous faisiez quand le problème est apparu ainsi que
tous les messages d'erreurs reçus. Ces messages d'erreurs doivent être
recopiés exactement tel qu'ils sont apparus. Utilisez le copier/coller
si cela est possible.</p>
<p>Ouvrez un terminal et tapez <strong>tail /var/log/messages</strong>. Cette commande
affichera les 10 dernières lignes des logs du système. Si celui ci
contient un ou des messages qui sont clairement en rapport avec votre
problème, recopiez les également.</p>
<p>Les erreurs des applications graphiques sont en général dans le fichier
.Xsession-errors ou .xsession-errors dans votre dossier /home. La
commande pour visualiser les 10 dernières lignes est donc <strong>tail
~/.xsession-errors</strong>. Comme pour le fichier /var/log/messages, ajoutez
les lignes en rapport avec votre problème dans votre fichier de départ.
Si vous n'avez trouvé aucune information dans ces fichiers, essayez de
lancer l'application concernée depuis votre terminal. Lors de
l'apparition du bug, des messages devraient s'afficher.</p>
<p>Si votre système ne démarre plus suite à un problème, démarrez alors sur
une autre distribution (soit en dual-boot si vous en avez soit depuis un
live-cd). Il est toujours bon d'avoir un live-cd sous la main pour ce
genre d'opération. Une fois que vous avez démarré sur le live-cd, montez
votre partition root et récupérez les informations dans les fichiers
cités plus haut.</p>
</section>
<section id="le-probleme-est-il-reproductible">
<h3>2 - Le problème est-il reproductible?</h3>
<p>S'il est possible de reproduire le problème facilement, faites-le.
N'oubliez pas de le faire sur des fichiers peu important ou sur une
copie du fichier concerné afin de ne pas endommager vos données.</p>
</section>
<section id="est-ce-un-probleme-materiel">
<h3>3 - Est-ce un problème matériel ?</h3>
<p>Les problèmes non reproductibles sont souvent dus au matériel. Si vous
pensez que c'est le cas, regardez alors dans le fichier
<strong>/var/log/boot</strong> ainsi que <strong>/var/log/kern.log</strong> ou
<strong>/var/log/kernel.log</strong> suivant votre distribution pour voir si le
kernel reconnait bien votre matériel. Ce fichier étant très long, la
commande tail ne vous sera pas d'un grand secours. Utilisez plutôt
<strong>less /var/log/boot</strong>et parcourez les pages à la recherche d'un
message en rapport avec votre problème. Recopiez également ce message
dans votre fichier de départ.</p>
</section>
<section id="lisez-la-documentation-du-programme">
<h3>4 - Lisez la documentation du programme.</h3>
<p>Ceci est à faire en particulier si le programme ne réagit pas de la
manière souhaitée. Lisez l'aide en ligne du programme et utilisez
également le manuel universel (dans un terminal : man
nom_du_programme).</p>
</section>
<section id="recherchez-votre-message-d-erreur-sur-internet">
<h3>5 - Recherchez votre message d'erreur sur internet</h3>
<p>Copiez/collez le message d'erreur dans un moteur de recherche ou un
meta-moteur tel que ixquick et ajoutez-y le nom du programme. Vous
trouverez certainement des messages sur des forums d'utilisateurs qui
ont le même problème que vous. Lisez le thread complet, vous y trouverez
peut-être une solution.</p>
</section>
<section id="reflechissez-avec-logique">
<h3>6 - Réfléchissez avec logique</h3>
<p>Si, arrivé ici, vous commencez à avoir une idée sur la cause du
problème, vous pouvez peut être tester cette idée. Il y a beaucoup de
petites commandes simples qui peuvent vous aider à recueillir plus
d'informations sur votre problème et votre système, qui vont seront d'un
grand secours.</p>
<ul>
<li><strong>lspci</strong> pour lister votre matériel</li>
<li><strong>lsusb</strong> pour lister les périphériques usb</li>
<li><strong>cat /proc/cpuinfo</strong> pour avoir les caractéristiques de votre CPU</li>
<li><strong>free -m</strong> pour connaitre le taux de charge de votre RAM</li>
</ul>
</section>
<section id="maintenant-vous-pouvez-penser-a-demander-de-l-aide">
<h3>7 - Maintenant, vous pouvez penser à demander de l'aide.</h3>
<p>Si après tout ça, vous n'avez toujours pas résolu votre problème, il est
temps de demander de l'aide sur un forum d'utilisateurs. Avant de passer
à cette étape, rappelez vous que les utilisateurs des forums ne sont pas
payés pour répondre à vos questions. Ce sont seulement des utilisateurs
ayant une certaine expérience et qui font cela bénévolement.</p>
</section>
</section>
<section id="ii-obtenir-de-l-aide">
<h2>II - Obtenir de l'aide</h2>
<section id="d-abord-observer">
<h3>1 - D'abord, observer</h3>
<p>Commencez par choisir votre forum. Il est préférable dans un premier
temps de choisir le forum de votre distribution, puis le forum du
programme concerné. Si ce forum possède une FAQ, lisez-la. Lisez aussi
les règles du forum. Si votre question ne respecte pas les règles, il y
a de grandes chances pour que vous n'obteniez pas de réponse.</p>
</section>
<section id="ne-soyez-pas-hors-sujet">
<h3>2 - Ne soyez pas hors-sujet</h3>
<p>Trouvez le sous-forum qui correspond à votre problème. Ne postez pas
votre message dans plusieurs sous-forums, ceci est très mal vu.</p>
</section>
<section id="choisissez-bien-le-titre-de-votre-topic">
<h3>3 - Choisissez bien le titre de votre topic.</h3>
<p>N'utilisez pas de sujet tel que "Besoin d'aide" ou "J'ai un problème".
Ceci a tendance à irriter les gens.</p>
<p>Votre titre doit indiquer le plus clairement quel problème vous avez.
Ainsi, une personne qui pense pouvoir vous aider sera plus encline à
lire votre sujet et poster une réponse. Soyez aussi précis que possible.
Par exemple "Impossible d'obtenir une adresse IP" sera plus utile que
"Je n'arrive pas à aller sur internet".</p>
</section>
<section id="donnez-des-informations">
<h3>4 - Donnez des informations</h3>
<p>Dans le corps de votre message, donnez le nom et la version de votre
distribution, le nom et la version du programme utilisé et les
informations sur votre matériel si cela est nécessaire. Recopiez-y aussi
les messages d'erreurs (c'est là que le fichier que vous avez créé au
début devient utile). Indiquez ce que vous avez fait pour tenter de
résoudre le problème. En faisant cela, vous montrerez aux autres que
vous ne vous êtes pas jeté sur le forum dès que le problème est apparu.</p>
</section>
<section id="pas-de-langage-sms">
<h3>5 - Pas de langage SMS</h3>
<p>Ça saoule! Ça n'aide pas à vous faire comprendre et on vous répondra
d'autant moins.</p>
</section>
<section id="ne-perdez-pas-une-opportunite-d-apprendre">
<h3>6 - Ne perdez pas une opportunité d'apprendre</h3>
<p>Ne suivez pas les conseils aveuglément. Vous êtes ici pour apprendre
quelque chose. Si on vous demande d'utiliser un outil en ligne de
commande, utilisez les pages man pour savoir à quoi sert cet outil. Vous
pourrez ensuite réutiliser cet outil si vous rencontrez un problème
similaire. Si on vous demande de poster un fichier pour plus
d'informations, recherchez l'utilité de ce fichier. Les fichiers
systèmes importants possèdent souvent une page man dédiée.</p>
</section>
<section id="dites-merci">
<h3>7 - Dites merci</h3>
<p>Les logiciels libres reposent sur la communauté. Personne n'est payé
pour vous aider. Les personnes qui vous aident le font car elles ont
elles-mêmes reçu de l'aide dans le passé et veulent rendre la pareille.
En plus de dire merci, vous pouvez également aider les autres qui ne
savent peut-être pas quelque chose que vous savez. Vous ressentirez
alors une certaine satisfaction que les logiciels propriétaires ne
peuvent vous apporter.</p>
</section>
</section>
QRQVB : L'adresse IP2009-09-16T19:12:00+02:002009-09-16T19:12:00+02:00Aldevartag:blog.devarieux.net,2009-09-16:/2009/09/qrqvb-adresse-ip.html<section id="definition">
<h2>Définition :</h2>
<p>Une adresse IP identifie de manière unique une machine ainsi que le
réseau sur lequel elle est située. Chaque adresse est une série de 4
octets dont une partie correspond à l’<strong>identificateur du réseau</strong> et
l’autre partie à l’<strong>identificateur de la machine</strong>.
| Exemple d’adresse IP …</p></section><section id="definition">
<h2>Définition :</h2>
<p>Une adresse IP identifie de manière unique une machine ainsi que le
réseau sur lequel elle est située. Chaque adresse est une série de 4
octets dont une partie correspond à l’<strong>identificateur du réseau</strong> et
l’autre partie à l’<strong>identificateur de la machine</strong>.
| Exemple d’adresse IP : 172.19.174.125.</p>
<p>Concrètement, qu’est ce que cela signifie? En fait, puisque les machines
ne savent traiter qu’avec des nombres binaires (0 ou 1) l’adresse est
codée en binaire sur 4 octets. Sachant qu’un octet correspond à 8 bits,
cela nous donne, pour chaque octet 256 possibilités (2^8) pour une
valeur comprise en 0 et 255.</p>
</section>
<section id="allons-un-peu-plus-loin">
<h2>Allons un peu plus loin!</h2>
<p>C’est bien sympa d’avoir une adresse, encore faut-il qu’on puisse m’y
contacter! On vient de voir dans la définition que l’adresse IP est
divisée en 2 sous parties : <strong>l’identificateur de
réseau</strong> et <strong>l’identificateur d’hôte</strong>. C’est là qu’intervient le
masque de réseau. Alors puisque je ne suis pas fort en blablatage, je
vais plutôt vous montrer un exemple.
| Voici une adresse IP : 192.168.1.15
| Voici un masque de réseau : 255.255.255.0</p>
<div class="m-image">
<a href="/images/netmask1.png"><img src="https://blog.devarieux.net/images/netmask1.png" /></a>
</div>
<p>En fait, pour être plus précis, les bits se situant dans la partie de
l’identificateur réseau sont tous positionnés sur 1 et les bits de la
partie hôte sur 0. En procédant à une opération de ET logique entre
l’adresse IP et le masque de réseau, on trouve l’adresse réseau. Les
opérations de ET logique suivent cette règle :</p>
<pre>0 ET 0 = 0
0 Et 1 = 0
1 ET 0 = 0
1 ET 1 = 1</pre>
<p>Grâce à cette adresse réseau, un routeur pourra déterminer quel chemin
doivent emprunter nos paquets IP. Pour bien comprendre ce système, nous
allons jouer un peu avec le binaire, même si je sais que ça va en
rebuter plus d’un :p</p>
<div class="m-image">
<a href="/images/binaire.png"><img src="https://blog.devarieux.net/images/binaire.png" /></a>
</div>
<p>Ceci est important puisque c’est de cette manière qu’on va pouvoir
déterminer le nombre maximal de machines qui peuvent appartenir à un
réseau. Il faut également savoir que sur 1 réseau, 2 adresses sont
réservées. L’adresse <strong>‘bits hôte à 0′</strong> car c’est elle qui va définir
justement l’adresse de notre réseau, comme on vient de le voir, et
l’adresse <strong>‘bits hôte à 1′</strong> car elle correspond à l’adresse de
diffusion (broadcast). L’adresse de broadcast est nécessaire pour
diffuser un message sur tout le réseau. Le message de ce genre le plus
classique est la requête ARP. Celle ci permet à une machine de trouver
une autre machine sur le réseau en l’appelant.</p>
<p>Voici un exemple de capture de trame avec wireshark :</p>
<div class="m-image">
<a href="/images/arp2.png"><img src="https://blog.devarieux.net/images/arp2.png" /></a>
</div>
<p>Le premier paquet est donc une requête ARP. La machine source envoie ce
message sur tout le réseau : ‘who has 192.168.1.51? Tell 192.168.1.25′.
La machine qui a pour IP 192.168.1.51 envoie donc sa réponse directement
à 192.168.1.15 et lui dit que c’est l’adresse MAC 00:0a:78:9e:8a qui
possède cette IP. Tout ça pour vous dire que l’adresse IP ‘bits hôte à
1′ est donc réservée pour ce type de message.</p>
</section>
<section id="dimensionnement-de-reseau">
<h2>Dimensionnement de réseau</h2>
<p>Puisque le masque de réseau détermine le nombre maximal de machines sur
un réseau et que les adresses IP ne sont pas illimitées, on va pouvoir
travailler sur le dimensionnement du réseau en modifiant le masque. En
effet, <strong>il est possible d’emprunter des bits à la partie hôte pour
les donner à la partie réseau</strong>. Par exemple, le masque 255.255.255.0
permet d’avoir 256-2 = 254 hôtes différents sur le même réseau. Hors,
rares sont ceux qui disposent de 254 machines à interconnecter.</p>
<p>Admettons que mon réseau possède l’ip 192.168.1.0 (totalement au
hasard!) de masque 255.255.255.0 . Je dispose de 5 machines à connecter
sur ce réseau, jamais plus.</p>
<ul>
<li>Si je garde 1bit dans la partie hôte, je vais disposer de 2^1 = 2
hôtes possibles. On vient de voir plus haut que 2 adresses sont
reservées sur le réseau, (sisi, rapellez vous, juste au dessus!).
Donc 2-2 = 0, ce qui me fait 0 hôte disponible.</li>
<li>Si je garde 2 bits pour ma partie hôte, il va me rester (2^2)-2 = 2
hôtes possibles. Ce n’est toujours pas suffisant!!</li>
<li>Si je garde 3 bits pour la partie hôtes, j’obtiens (3^2)-2 = 6 hôtes
possibles. Ouf!! j’ai assez de place pour caser mes machines. On va
donc construire notre masque de réseau en gardant ces 3 bits sur 0,
ce qui nous donne :</li>
</ul>
<p>
11111111.11111111.11111111.11111 000<br />
<p>
Partie réseau Partie hôte<br />
Ce qui, transformé en décimal nous donne un masque : 255.255.255.248.<br />
</p>
</p>
<p>Ce qu’on vient de faire ici, c’est de créer des sous réseaux du réseau
192.168.1.0. Plusieurs sous réseaux composé chacun de 8 adresses IP.</p>
<pre>Sous réseau 1 : de 192.168.1.0 à 192.168.1.7 (avec 192.168.1.0 adresse de sous réseau et 192.168.1.7 adresse de broadcast)
Sous réseau 2 : de 192.168.1.8 (adresse du réseau) à 192.168.1.15 (adresse de broadcast)
Sous réseau 3 : de 192.168.1.16(adresse du réseau) à 192.168.1.23 (adresse de broadcast)
etc etc..
dernier sous réseau : de 192.168.1.248 (adresse de réseau) à 192.168.1.255 (adresse de broadcast)</pre>
<p>Voilà donc ce qui se cache derrière les adresses IP. Plus mon sous
réseau sera petit, moins j’aurais de broadcast sur ce réseau. Parce que
mine ça papote pas mal la dedans et ça a tendance à broadcaster dans
tous les sens. Malheureusement, le broadcast n’est pas gratuit. Il coûte
de la bande passante. Et quand la bande passante sature, on commence à
perdre des paquets.</p>
<p>C’est pour ça qu’il est important, en entreprise en tout cas, de bien
calculer le dimensionnement de son réseau et l’adressage IP de
l’entreprise, sans oublier de prévoir que si l’entreprise s’agrandit, il
va falloir rajouter des hôtes sur certains sous réseaux et en plus
ajouter un nouveau sous réseau à notre entreprise pour y connecter un
nouveau bâtiment par exemple. Ça a vite tendance à tourner cacahuète si
on fait pas attention.</p>
</section>
QRQVB : Datagramme IP2009-09-16T11:07:00+02:002009-09-16T11:07:00+02:00Aldevartag:blog.devarieux.net,2009-09-16:/2009/09/qrqvb-datagramme-ip.html<p>Je vais tenter dans cet article de décortiquer un datagramme IP et
notamment son en-tête. Nous allons commencer par l’observation des
encapsulations des données suivant le <a href="http://blog.devarieux.net/2009/08/qrqvb-le-modele-osi/">modèle
OSI</a> que nous
avons étudié la dernière fois. Les données (couche application) sont
encapsulées dans un message (couche 4, transport) qui est …</p><p>Je vais tenter dans cet article de décortiquer un datagramme IP et
notamment son en-tête. Nous allons commencer par l’observation des
encapsulations des données suivant le <a href="http://blog.devarieux.net/2009/08/qrqvb-le-modele-osi/">modèle
OSI</a> que nous
avons étudié la dernière fois. Les données (couche application) sont
encapsulées dans un message (couche 4, transport) qui est lui même
encapsulé dans un paquet (couche 3, réseau), lui même encapsulé dans une
trame (couche 2, liaison). Rien ne vaut un bon dessin pour
comprendre.</p>
<div class="m-image">
<a href="/images/encaps.png"><img src="https://blog.devarieux.net/images/encaps.png" /></a>
</div>
<p>Aujourd’hui, on va donc s’intéresser à ce que contient le petit carré
vert lorsque le paquet est un paquet IP.</p>
<p>Cet en-tête est codé par défaut sur 20 octets. Nous allons donc nous
appliquer à décrypter le contenu de chacun de ses octets. J’ai fait pour
cela un schéma pas terrible mais qui me servira de support pour les
explications :p.</p>
<div class="m-image">
<a href="/images/entete1.png"><img src="https://blog.devarieux.net/images/entete1.png" /></a>
</div>
<ul>
<li><p><strong>Le premier octet contient 2 informations.</strong></p>
<ul>
<li>La première est la version du protocole utilisé, codée sur 4 bits.
pour le protocole IPv4, on utilisera le code 0100 qui correspond
au 4 décimal. Pour IPv6, c’est 0110 (6 décimal).</li>
<li>La seconde information, codée également sur 4 bits contient l’IHM.
C’est la longueur, en mot de 32bits (4 octets), de l’en-tête du
datagramme. Par défaut, ces bits sont positionnés sur 0101, ce qui
correspond au 5 décimal, ce qui est logique pour un en-tête par
défaut de 20 octets.</li>
</ul>
</li>
<li><p><strong>Le deuxième octet est le TOS (type of service)</strong> et va définir la
manière dont le datagramme doit être traité. Il se décompose lui
aussi en 2 :</p>
<ul>
<li>3 bits pour la priorité à donner au datagramme (0 à 7)</li>
<li>4 bits qui définissent chacun une option activée ou pas (1 option
activée, 0 option desactivée)<ul>
<li>1er bit : D → Positionné sur 1 pour privilégier le délai
d’acheminement</li>
<li>2ème bit : T → Positionné sur 1 pour privilégier le débit</li>
<li>3ème bit : R → Positionné sur 1 pour privilégier la fiabilité</li>
<li>4ème bit : C → Positionné sur 1 pour privilégier le coût</li>
</ul>
</li>
<li>1 bit qui ne contient aucune information. Il est appelé MBZ pour
Must Be Zero. comme son nom l’indique, ce bit doit être positionné
sur 0.</li>
</ul>
</li>
<li><p><strong>Les 3ème et 4ème octets contiennent le champ Longueur Totale (Total
Lenght)</strong>. Codé sur 16 bits, il contient la taille, en octet, du
datagramme complet (en-tête + données). On en déduit donc que la
longueur totale du paquet ne peut dépasser 65535 octets. Grâce à
cette valeur, on peut calculer la taille des données :</p>
<ul>
<li>longueur données = Longueur totale – (IHM x 4)</li>
</ul>
</li>
<li><p><strong>Les 5ème et 6ème octets contiennent le champ Identification</strong>.
Celui ci intervient lors du ré-assemblage des paquets pour
reconstituer les données lorsque celles ci sont fragmentées.</p>
</li>
<li><p><strong>Les 7ème et 8ème octets contiennent 2 informations.</strong></p>
<ul>
<li>3 bits correspondent au champ <strong>flag</strong>. Il sert a déterminer
l’état de fragmentation.<ul>
<li>1er bit : Réservé, il doit être sur 0</li>
<li>2ème bit : Don’t Fragment. Indique si la fragmentation est
autorisée.</li>
<li>3ème bit : More Fragment. Positionné sur 1 il signifie que ce
datagramme n’est pas le dernier fragment.</li>
<li>13 bits correspondent au champ <strong>Position Fragment</strong>. Ce champ
indique la position du fragment par rapport au premier
datagramme et interviendra lors de la reconstitution du
message.</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Le 9ème octet contient le TTL (Time to Live).</strong> ‘Durée de vie’ en
français. Il indique le nombre maximal de routeurs que peut traverser
le datagramme. Il est initialisé par la station émettrice et
décrémenté de 1 par chaque routeur qui reçoit le datagramme et le
réexpédie. Si un routeur reçoit un datagramme dont le TTL est nul, il
le détruit et renvoie à l’expéditeur un message ICMP. Le but de ce
champ est d’éviter les paquets fantômes qui circuleraient en boucle
sur le réseau sans atteindre leur destination.</p>
<blockquote>
<p>Pour la petite histoire, c’est de cette manière que fonctionne
l’application <strong>traceroute</strong>. Lorsqu’on lance traceroute
<a href="http://www.devarieux.net">www.devarieux.net</a>, traceroute envoie
un ping vers www.devarieux.net avec un TTL de 1. Lorsque le premier
routeur reçoit le paquet, il le détruit et renvoie à l’expediteur un
message ICMP l’informant que le paquet a été détruit (time to live
exceeded). Ce message ICMP contient dans son en-tête l’adresse IP du
routeur. Suite à cela, traceroute recommence l’opération mais avec
un TTL de 2 et ainsi de suite jusqu’à toucher www.aldevar.fr. Et
c’est de cette manière qu’on obtient la route prise par notre
paquet. Attention ceci dit car 2 paquets envoyés vers la même
destination peuvent emprunter des routes différentes.</p>
</blockquote>
</li>
<li><p><strong>Le 10ème octet sert à coder le protocole</strong> qui se trouve dans les
données qui suivent l’en-tête. Il est codé sur 8 bits. Les protocoles
les plus communs sont ICMP (0000.0001), TCP (0000.0110) et UDP
(0001.0001).</p>
</li>
<li><p><strong>11ème et 12ème octets : Le checksum</strong>. C’est la somme de contrôle
de l’en-tête du datagramme. Chaque machine qui reçoit le paquet doit
recalculer ce checksum car la modification du TTL modifie celui ci.</p>
</li>
<li><p>Les octets 13 à 16 contiennent l’<strong>adresse IP de la machine
émétrice</strong>. C’est également l’adresse de réponse.</p>
</li>
<li><p>Et enfin les 4 derniers octets contiennent eux l’<strong>adresse IP de
destination</strong>.</p>
</li>
</ul>
<section id="capture-de-trame">
<h2>Capture de trame</h2>
<p>Puisqu’il n’est pas particulièrement évident pour nous, simples mortels,
de lire ces bits pour comprendre ce que contient le datagramme, on peut
utiliser un logiciel de capture de trame tel que <strong>wireshark</strong> en mode
graphique ou <strong>tcpdump</strong> en mode commande. Je vous laisse vous même
découvrir ces applications. Je vais me contenter ici de montrer un
screenshot d’une capture faite avec wireshark qui montre ce que ce
logiciel peut nous dire sur le contenu de nos paquets.</p>
<div class="m-image">
<a href="/images/trame01.png"><img src="https://blog.devarieux.net/images/trame01.png" /></a>
</div>
<p>Voici le type de paquet que nous avons capturé. C’est un
simple ping entre 2 machines se situant sur des réseaux différents.
Wireshark nous dit déjà que c’est un paquet ICMP. Voyons le détail de ce
datagramme :</p>
<div class="m-image">
<a href="/images/trame02.png"><img src="https://blog.devarieux.net/images/trame02.png" /></a>
</div>
<p>En dépliant le contenu de l’en-tête IP, voici ce que wireshark peut nous
dire :</p>
<ul>
<li>Nous sommes en IPv4.</li>
<li>Le header fait 20 octets (bytes et non bits).</li>
<li>La longueur total du datagramme est de 60 octets. On en conclue donc
que nous avons 40 octets de données.</li>
<li>Le message n’est pas fragmenté.</li>
<li>Le TTL est de 128 ce qui signifie qu’après avoir traversé 128
routeurs, le paquet sera détruit.</li>
<li>Le protocole contenu dans les data est ICMP</li>
<li>Le checksum est correct.</li>
<li>Enfin, à la fin, les IP de départ et de destination.</li>
</ul>
<p>Voilà, c’est terminé pour l’analyse de paquet de niveau 3. La prochaine
fois, j’essaierai d’expliquer le contenu d’un en-tête de niveau 4
(couche transport : UDP, TCP etc…) ou de niveau 2 (couche liaison, trame
ethernet). Si vous trouvez que cet article manque de précision n’hésitez
pas à m’en faire part.</p>
</section>
QRQVB : Le modèle OSI2009-08-17T18:30:00+02:002009-08-17T18:30:00+02:00Aldevartag:blog.devarieux.net,2009-08-17:/2009/08/qrqvb-le-modele-osi.html<p>Dans cette nouvelle catégorie (la Question Réseau Qui Va Bien), je vous
propose de (re)découvrir avec moi, quelques notions fondamentales de
réseau. Ces articles s'adressent en particulier à ceux qui souhaitent
comprendre les mécanismes d'Internet et/ou du routage en WAN ou en LAN.
J'essaierai d'être le plus clair …</p><p>Dans cette nouvelle catégorie (la Question Réseau Qui Va Bien), je vous
propose de (re)découvrir avec moi, quelques notions fondamentales de
réseau. Ces articles s'adressent en particulier à ceux qui souhaitent
comprendre les mécanismes d'Internet et/ou du routage en WAN ou en LAN.
J'essaierai d'être le plus clair possible. Si vous trouvez des erreurs,
non-sens dans ces articles, je suis ouvert à toutes critiques,
corrections. Et pour inaugurer cette catégorie, commençons donc par le
modèle OSI, qui est la base pour une bonne compréhension des mécanismes
des réseaux informatiques.</p>
<section id="definition">
<h2>Définition</h2>
<p>Le modèle OSI est une norme définie par l'ISO pour permettre
l'interconnexion des systèmes. Il propose un modèle d'architecture
réseau afin de s'assurer que tous les systèmes interconnectés puissent
communiquer entre eux quel que soit le constructeur du matériel. Les
constructeurs informatiques ont proposé des architectures réseaux
propres à leurs équipements. Par exemple, IBM a proposé SNA, DEC a
proposé DNA... Ces architectures ont toutes le même défaut : du fait de
leur caractère propriétaire, il n'est pas facile des les interconnecter,
à moins d'un accord entre constructeurs. Le modèle OSI ne précise pas
vraiment les services et protocoles à utiliser pour chaque couches. Il
décrit plutôt ce que doivent faire ces couches. Je sais que ça ne parait
pas très clair pour le moment, mais ça va le devenir.</p>
</section>
<section id="schema-du-modele">
<h2>Schéma du modèle</h2>
<div class="m-image">
<a href="images/modele_OSI.gif"><img src="https://blog.devarieux.net/images/modele_OSI.gif" /></a>
</div>
<p>Le modèle OSI est donc représenté en 7 couches distinctes. J'ai ici
représenté 2 machines (Système A et Système B) pour bien montrer que
lors de la communication de 2 hôtes, chaque couche 'discute' directement
avec la couche équivalente de l'hôte d'en face.</p>
<section id="couche-physique">
<h3>1°) Couche Physique</h3>
<p>La couche physique s'occupe de la transmission des bits de façon brute
sur un canal de communication. Plus clairement, elle est typiquement
représentée par votre carte réseau et sa prise ethernet (et non pas le
protocole ethernet!!). La couche phyique discute directement avec l'hôte
suivant sur le réseau. C'est à dire que lors d'une communication sur
internet, cette couche ne s'occupe de l'envoie des données que vers la
machine suivante, en général un routeur. La couche physique traite
exclusivement avec des bits 0 et 1 et normalise l'écriture de ces bits
(une tension de 5V corespond à un 1, -5V un 0).</p>
</section>
<section id="couche-liaison">
<h3>2°) Couche Liaison</h3>
<p>La couche de liaison (ou liaison de donnée) est un liant entre les 2
couches physiques des hôtes en communications. Elle fractionne les
données en trames et tente d'exempter la couche physique des erreurs de
transmissions. Elle doit être capable de renvoyer une trame lorsqu'il y
a un problème sur la ligne et intègre également un système de gestion de
flux pour éviter les engorgements. Par exemple une carte 100Mb/s relié à
une carte 1Gb/S doivent pouvoir communiquer sans que la carte 100Mb/s
recoive 10x trop de données. L'unité d'information de cette couche est
donc la trame qui est composé de quelques centaines d'octets.</p>
</section>
<section id="couche-reseau">
<h3>3°) Couche Réseau</h3>
<p>La couche réseau construit la liaison de bout en bout lors de la
communication de 2 hôtes. C'est la seule couche directement concernée
par la topologie du réseau. Elle va trouver la route parmis les routeurs
pour atteindre l'hôte cible. Lors d'un envoie de données, 2 paquets
différents peuvent emprunter des routes différentes suivant
l'architecture du réseau et ses point d'engorgement. C'est la dernière
couche supportée par TOUTES les machines du réseau (hôtes, switchs,
routeurs, serveurs). Son unité d'information est le paquet.</p>
</section>
<section id="couche-transport">
<h3>4°) Couche Transport</h3>
<p>Cette couche est responsable du bon acheminement des messages complets
au destinataire. Le rôle principal de la couche transport est de prendre
les messages de la couche session, de les découper s'il le faut en
unités plus petites et de les passer à la couche réseau et inversement
du coté du recepteur. Comme on l'a vu dans la couche réseau, 2 paquets
d'un même message peuvent prendre des routes différentes et donc arriver
dans le désordre. Le rôle de la couche transport est donc de remettre
ces paquets dans l'ordre. Elle peut aussi gérer le multiplexage lors de
communications multiples entre 2 mêmes hôtes (par exemple une connexion
http et ftp sur le même canal). Son unité d'information est le message.</p>
</section>
<section id="couche-session">
<h3>5°) Couche Session</h3>
<p>Le service principale de la couche session est la synchronisation des
communications. Qui veut parler? Qui parle? Elle permet aussi de prendre
des 'snapshots' des flots de données pour pouvoir reprendre le dialogue
là où il en était avant une coupure du canal de communication.</p>
</section>
<section id="couche-presentation">
<h3>6°) Couche Présentation</h3>
<p>La couche présentation est chargée du codage des données de la couche
application. En effet, toutes les couches plus basses transportent des
octets sans chercher comprendre leur signification. Ici, elle va
s'occuper d'encoder du texte, des images, de la video, de la voix etc...
en données transportables, c'est à dire en octet.</p>
</section>
<section id="couche-application">
<h3>7°) Couche Application</h3>
<p>Cette couche est le point de contact entre l'utilisateur et le réseau.
Elle lui apporte l'interface lui permettant de communiquer avec celui ci
(messagerie, http, ftp etc...).</p>
</section>
</section>
<section id="exemples-de-protocoles">
<h2>Exemples de protocoles</h2>
<ol>
<li>Physique → biphase, bipolaire simple</li>
<li>Liaison → ATM, Ethernet, PPP, TokenRing, Fiber Distributed Date
Interface (FDDI)</li>
<li>Réseau → IP, IPX, ICMP</li>
<li>Transport → TCP, UDP (pour les plus connus)</li>
<li>Session → SIP, Appletalk</li>
<li>Présentation → ASCII, Unicode, ASN.1, Videotex</li>
<li>Application → HTTP, SMTP, POP, FTP, DNS, SNMP</li>
</ol>
</section>