Tag - réseau

Entries feed

Saturday, June 4 2016

vnstat sur Raspberry Pi pour surveiller le trafic réseau

Nous allons voir ici comment installer vnstat pour surveiller le trafic réseau et afficher une petite page de synthèse sur l'utilisation du trafic. Cela peut-être utile par exemple pour mesurer le trafic traversant une passerelle Raspberry Pi construite tel que raconté ici.

vnstat en ligne de commande

Tout commence avec (e.g. sous Raspbian Jessie) :

apt install vnstat vnstati

Demandons alors à vnstat de créer une base de données du trafic pour l'interface que l'on veut surveiller :

vnstat -i eth0 -u

Désormais, un appel à la commande vnstat affiche en ligne de commande une synthèse sur le trafic réseau :

vnstat -u #Mise à jour des informations
vnstat #Affichage de la synthèse
Database updated: Sat Jun  4 13:02:00 2016

   eth0 since 29/05/16

          rx:  136.26 MiB      tx:  411.92 MiB      total:  548.18 MiB

   monthly
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
       May '16    134.72 MiB |  410.23 MiB |  544.94 MiB |    1.67 kbit/s
       Jun '16      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.09 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         8 MiB |       8 MiB |      16 MiB |

   daily
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
      29/05/16    134.72 MiB |  410.23 MiB |  544.94 MiB |   51.67 kbit/s
         today      1.55 MiB |    1.69 MiB |    3.24 MiB |    0.57 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated         1 MiB |       1 MiB |       2 MiB |

vnstat sur une page web

vnstati est une commande parente de vnstat qui génère une image de synthèse plutôt qu'un tableau. Pratique pour nous, êtres humains, qui aimons la bigarrure ! Alors demandons à vnstati de nous géréner quelques images à l'aide de ce script que l'on pourra placer dans cron :

#!/bin/bash
vnstat -u -i eth0
vnstati -s -i eth0 -o /var/www/html/summary.png
vnstati -h -i eth0 -o /var/www/html/hourly.png
vnstati -d -i eth0 -o /var/www/html/daily.png
vnstati -t -i eth0 -o /var/www/html/top10.png
vnstati -m -i eth0 -o /var/www/html/monthly.png

Et pour afficher ces images, nous allons utiliser une petite page web et nginx :

apt install nginx

puis remplaçons la page par défaut /var/www/html/index.nginx-debian.html par index.html contenant :

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Statistics</title>
</head>

<body>
<h2 align="center">Network Statistics</h2>
<hr align="center">
<p align="center"><img src="summary.png" alt="Summary"/><br/>
  Summary
</p>
<hr align="center">
<p align="center"><img src="hourly.png" alt="Traffic stats on a hourly basis for the last 24 hours "/><br/>
  Traffic stats on a hourly basis for the last 24 hours
</p>
<hr align="center">
<p align="center"><img src="daily.png" alt="Traffic stats on a daily basis for the last 30 days"/><br/>
  Traffic stats on a daily basis for the last 30 days
</p>
<hr align="center">
<p align="center"><img src="monthly.png" alt="Traffic stats on a monthly basis for the last 12 months"/><br/>
  Traffic stats on a monthly basis for the last 12 months
</p>
<hr align="center">
<p align="center"></p>
<p align="center"><img src="top10.png" alt="All time top 10 traffic days"/><br/>
  All time top 10 traffic days</p>
<hr align="center">
</body>
</html>

et si l'on pointe un navigateur vers l'adresse IP du Raspberry Pi, on voit alors s'afficher :

Screenshot_2016-06-04_15-28-00.png

Un Raspberry Pi en passerelle IPv4, pour surveiller des flux réseaux par exemple

Nous allons voir dans ce billet comment paramétrer un Rasperry Pi pour qu'il joue le rôle de passerelle IPv4. Attention, avec son interface ethernet 100 Mbps et sa puissance limitée, il est évident que le montage présenté ici peut convenir dans un environnement domestique mais sans doute pas au-delà.

Matériel

Prenons donc un Raspberry Bi (muni de Raspbian Jessie) et munissons-le d'un port ethernet USB. Le Pi dispose alors de 2 interfaces ethernet eth0 et eth1 :

pi-bi-eth.jpg

Il n'est pas obligatoire d'avoir deux interfaces réseaux mais cela est plus commode et permet un suivi plus fin du trafic (avec une seule interface, tout ce qui rentre ressort par la même interface et il est dès lors plus délicat de comparer flux entrants et flux sortants puisqu'ils s'annulent au niveau de l'interface unique.

Paramétrage du réseau

Attribuons des paramétrages réseau fixes à eth0 et eth1 dans /etc/dhcpcd.conf comme expliqué ici :

interface eth0
static ip_address=192.168.1.235/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

interface eth1
static ip_address=192.168.1.234/24

L'interface eth0 est paramétrée avec une IP fixe et utilise comme passerelle de sortie le routeur local (192.168.1.1 dans cet exemple). L'interface eth1 se voit attribuer seulement une adresse IP fixe mais pas de passerelle de sortie. Ainsi, la seule route vers l'extérieur passe au travers d'eth0, ce que nous confirme la commande ip route :

default via 192.168.1.1 dev eth0  metric 202 #La sortie par défaut via eth0, pas de sortie via eth1 !
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.235  metric 202 
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.234  metric 203

Il faut maintenant permettre au Raspberry Pi de faire transiter les paquets d'une interface à une autre. Pour ce faire, nous allons activer cette ligne dans /etc/sysctl.conf :

net.ipv4.ip_forward=1

et on ajoutera également ces 3 lignes pour s'assurer que le Raspberry Pi n'enseigne pas aux périphériques autour de lui à le "by-passer" (ce qu'un routeur fait par défaut pour garantir la performance et éviter les noeuds inutiles) :

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth1.send_redirects = 0

Pour activer cette configuration, on peut redémarrer ou exécuter :

sysctl -p

Désormais, le Raspberry Pi est capable de faire passer les communications d'eth1 à eth0 mais la route retour ne passe pas nécessairement par le Pi (le routeur n'a aucune raison, lui, de faire transiter le trafic retour vers le Pi s'il peut accéder directement au périphérique final ; évidemment ce cas ne se présente pas si le schéma de câblage fait du Pi le seul lien physique vers la porte de sortie).

Pour forcer la retour par le Pi, on exécutera cette commande iptables :

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Désormais, tout ce qui sort par eth0 voit son adresse source modifiée (filtre MASQUERADE appliquée en POSTROUTING) pour correspondre à l'adresse du Pi : au retour les paquets passeront donc forcément par le Pi qui renverra ensuite vers la bonne destination.

Et sur les périphériques ?

Sur chaque périphérique, il est alors possible d'indiquer comme passerelle l'adresse IP du Pi sur eth1 soit 192.168.1.234 dans cet exemple. Chacun saura comment indiquer à son DHCP local si nécessaire de transporter cette information plutôt que celle par défaut. Dès lors, le Pi devient le point de passage obligé du trafic réseau.

Pour quoi faire ?

Par exemple, nous pouvons maintenant examiner le flux traversant, mesurer le débit avec iftop, couper l'accès à internet à certaines heures, ... On pourra par exemple installer vnstat sur le Pi pour afficher des statistiques d'usage de la bande passante. Les idées ne manquent pas :-)

Sunday, May 29 2016

IP statique sur Raspbian Jessie : DHCPCD fait la loi !

Sur Raspbian Jessie, le système n'obéit pas au classique /etc/network/interfaces quand il s'agit de paramétrer le réseau ! Inutile donc de vous escrimer (comme moi) à modifier les paramétrages de ce fichier pour basculer vers une adresse statique au lieu du DHCP par défaut !

En effet, sur Raspbian Jessie, le réseau est paramétré par le service DHCPCD. C'est donc à son niveau qu'il faut agir.

Ainsi, pour attribuer une IP fixe au Pi, ouvrons le fichier /etc/dhcpcd.conf et ajoutons ces lignes à la fin du fichier :

interface eth0
static ip_address=192.168.1.234/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

Monday, March 28 2016

LemonLDAP::NG et Let's Encrypt

Nous allons voir dans ce court article comment obtenir des certificats Let's Encrypt pour des services LemonLDAP::NG. Les chemins d'accès évoqués dans la suite correspondent à une installation de LemonLDAP::NG sur Debian Jessie à partir du paquet officiel fourni sur les dépôts de LemonLDAP::NG.

Étape 1 : obtenir un certificat pour le Manager

Nous allons commencer par autoriser l'accès au dossier .well-known dans lequel Let's Encrypt travaille (pour mémoire, il y place une clé qu'un serveur externe vient interroger, permettant ainsi d'affirmer que le demandeur gère le domaine). D'abord dans la configuration d'Apache, dans le fichier /etc/apache2/sites-available/manager-apache2.conf, nous allons remplacer la ligne

RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|doc|fr-doc|lib).*"

par

RewriteCond "%{REQUEST_FILENAME}" "!^/(?:static|\.well-known|doc|fr-doc|lib).*"

Puis, dans le manager lui-même, il faut demander à LemonLDAP::NG de ne pas bloquer l'accès au même dossier .well-known aux utilisateurs non authentifiés. Ainsi, il faut se rendre dans Virtual Hosts -> manager.mondomaine.fr -> Access rule, et ajouter une nouvelle règle :

  • Regular expression: ^/\.well-known
  • Rule: skip

Screenshot_2016-03-28_06-02-19.png

Dès lors, Let's Encrypt devrait être capable d'accéder à la clé placée dans .well-known. Nous pouvons donc démarrer le processus avec le client Let's Encrypt :

certbot certonly --renew-by-default -a webroot --webroot-path /usr/share/lemonldap-ng/manager/ -d manager.mondomaine.fr

Étape 2 : obtenir un certificat pour le portail d'authentification

Facile :

certbot certonly --renew-by-default -a webroot --webroot-path /var/lib/lemonldap-ng/portal/ -d auth.mondomaine.fr

Étape 3 : obtenir un certificat pour une application placée derrière LemonLDAP::NG

Si l'application est protégée derrière LemonLDAP::NG, il faut commencer par indiquer à LemonLDAP::NG de laisser transiter les requêtes vers le dossier .well-known. A l'image de ce qui a été fait pour le manager, il faut se rendre dans Virtual Hosts -> manager.mondomaine.fr -> Access rule, et ajouter une nouvelle règle :

  • Regular expression: ^/\.well-known
  • Rule: skip

Puis tout simplement (si l'application sous-jacente ne filtre pas les accès à .well-known) :

certbot certonly --renew-by-default -a webroot --webroot-path /var/www/mon-app -d mon-app.mondomaine.fr

Wednesday, March 16 2016

Fail2ban pour protéger Samba de Locky

Face à la menace du "ransomware" Locky, j'ai décidé de protéger les données de mon serveur Samba à l'aide de Fail2ban. L'idée est simple : si des mouvements pouvant correspondre à une action de Locky sont détectés, alors l'IP à l'origine de l'action est bannie du serveur Samba.

Étape 1 : activer l'audit dans Samba

Samba dispose de puissantes fonctions d'audit qui permettent de garder trace de toutes les opérations sur un partage. Elles s'activent à l'aide des options full_audit dans le fichier /etc/samba/smb.conf. Attention toutefois à la volumétrie que cela peut représenter : si le serveur Samba est très sollicité, la taille des logs sera fort importante (surtout si l'on suit l'événement "open" qui est déclenché régulièrement lors de toute navigation sur le partage Samba) !

Plaçons donc le paramétrage suivante dans la section "Global" du fichier de configuration de Samba (/etc/samba/smb.conf par défaut) :

full_audit:priority = notice
full_audit:facility = local5
full_audit:success = mkdir rmdir rename unlink open
full_audit:prefix = %u|%I|%S

puis redémarrons Samba :

service samba restart

et voilà le fichier /var/log/samba/audit.log qui se remplit et recense tous les mouvements sur le serveur Samba. Une bonne rotation des logs sera nécessaire pour ne pas se faire piéger ! Attention également à la petite perte de performance que cette écriture régulière demandera.

Étape 2 : paramétrer le nouveau filtre d'exclusion pour Fail2ban

Nous allons demander à Fail2ban de bannir tout ordinateur qui effectuerait une opération sur fichier *.locky ou *.xxx sur le serveur. On crée le fichier /etc/fail2ban/filter.d/antilocky.conf suivant :

[Definition]
failregex = \|<HOST>\|NomDePartage\|.*\|ok\|.*\.(locky|xxx|mp3)

ignoreregex =

en remplaçant "NomDePartage" par le nom du partage Samba concerné.

Étape 3 : paramétrer une nouvelle prison dans Fail2ban

On paramètre comme il se doit Fail2ban dans /etc/fail2ban/jail.local en ajoutant notamment la section suivante :

[antilocky]
enabled = true
filter  = antilocky
backend = auto
logpath = /var/log/samba/audit.log
maxretry  = 2
banaction = iptables-allports
port = all

On peut alors redémarrer Fail2ban par :

service fail2ban restart

et vérifier dans les logs /var/log/fail2ban.log que la nouvelle prison se charge correctement.

Et voilà Fail2ban prêt à bannir tout ordinateur qui se connecterait au serveur Samba en manipulant des fichiers *.locky ou *.xxx. Evidemment il peut y avoir des faux positifs. Il est donc recommandé d'être vigilant et d'activer peut-être la notification par courriel des bannissements de ce type pour être en mesure de débannir dans le cas d'un faux positif et d'intervenir sur le poste infecté s'il s'avère qu'une réelle infection est en cours.

Étape 4 : limitations

La principale limitation est l'usage de l'extension de nom de fichier comme critère de signalement. Si des variantes du virus adoptent d'autres extensions (par exemple .pdf) alors il ne sera plus possible de détecter l'action frauduleuse de la sorte. On pourra éventuellement suivre le nombre d'opérations sur le partage Samba et alerter l'administrateur lorsque de trop nombreuses opérations de suppression sont en cours...

Saturday, February 27 2016

Tomato : utiliser la puissance d'iptables pour contrôler les flux sur les différentes interfaces

Voici quelques lignes à introduire dans la configuration d'un routeur/point d'accès propulsé par Tomato (dont on a déjà parlé dans ces articles) pour interdire aux périphériques branchés sur une interface d'accéder à certains sous-réseaux. Cela peut être pratique lorsque l'on veut interdire à certains périphériques (par exemple des périphériques connectés sur un réseau "invité") d'accéder à certaines ressources locales.

La petite subtilité est la suivante : il est nécessaire d'introduire les règles nouvelles en amont des règles existantes. Et pour ce faire, il faut donc utiliser l'option '-I' d'iptables en précisant la ligne à laquelle on souhaite insérer la nouvelle commande.

Ainsi :

iptables -P FORWARD DROP
iptables -I FORWARD 1 -i br0 -j ACCEPT
iptables -I FORWARD 2 -i br1 -d 192.168.0.0/16 -j REJECT
iptables -I FORWARD 3 -i br1 -j ACCEPT

conduit au comportement suivant :

  • par défaut tout est rejeté
  • on accepte tout en provenance de l'interface br0 (par exemple un Wifi 'maître des lieux')
  • on refuse tous les accès den provenance de l'interface br1 (par exemple un Wifi 'invité') à destination des IPs du sous-réseau 192.168.0.0/16
  • on accepte tout le reste de l'interface br1

Voilà, le tour est joué,

Thursday, February 4 2016

OpenSSL : détecter la péremption d'un certificat avec l'option -checkend

Dans un précédent article (ici), je proposais une méthode pour renouveler les certificats Letsencrypt en l'absence d'un mécanisme officiel pour le moment. Dans cette méthode (enfin ce script), je vérifiais la date du certificat avec "date -r", extrapolant la date de fin de validité à l'aide de la date de création du certificat et de la connaissance de la durée de validité par défaut des certificats de Letsencrypt.

Il y a en fait beaucoup plus intelligent ! Merci à mon beau-frère pour cette idée (toujours écouter au moins d'une oreille son beau-frère !)

Le manuel d'OpenSSL nous apprend l'existence de l'option suivante :

-checkend arg
checks if the certificate expires within the next arg seconds and exits non-zero if yes it will expire or zero if not.

Dès lors, il est facile de détecter si un certificat périme dans les 30 jours (2 592 000 secondes) :

if openssl x509 -checkend 2592000 -noout -in file.pem
then
  echo "Certificat valide encore au moins 30 jours"
else
  echo "Certificat périmant dans les 30 jours... à renouveler !"
fi

Monday, February 1 2016

Letsencrypt : renouveler intelligemment malgré les limites de la bêta

Depuis Mai 2016, le service Let's Encrypt n'est plus en bêta et les limitations de la bêta évoquées ici ne sont plus mordantes !

Depuis Mai 2016, le client letsencrypt est devenu certbot (https://certbot.eff.org/) ! les commandes évoquées plus bas sont sans doute valables en remplaçant letsencrypt-auto par certbot ! Il faut aussi noter que le client certbot dispose désormais de fonctions de renouvellement plus élaborées qu'auparavant ! Cet article est conservé pour archive et inspiration.

Letsencrypt se présente comme le futur du chiffrement sur internet. Bien que déjà fonctionnel, le service offert est encore en phase de test (bêta) et par conséquent certaines contraintes s'appliquent aux usagers testeurs. Parmi ces contraintes, les 2 les plus bloquantes sont :

  • pas de système de renouvellement automatique pour le moment (c'est prévu, vivement !)
  • limite imposée de 5 certificats par domaine par semaine (i.e. qu'il faut attendre une semaine pour pouvoir créer des certificats pour un nouveau sous-domaine d'un domaine qui possède déjà 5 certificats de sous-domaine)

Pour Letsencrypt qui émet des certificats à la validité courte de 3 mois, le renouvellement doit être fait régulièrement et il correspond ni plus ni moins à l'édition d'un nouveau certificat.

La contrainte évoquée plus haut est bloquante pour le renouvellement : en effet il n'est pas possible de renouveler plus de 5 certificats par semaine pour un même domaine...

Principe du renouvellement à terme

A terme, un système de renouvellement automatique sera intégré à Letsencrypt et il suffira de lancer tous les 2 mois (par exemple via cron) la commande demandant le renouvellement de tous les certificats en approche de péremption. Vivement cela !

Une méthode fonctionnelle aujourd'hui

Aujourd'hui, à nous de créer l'automatisme qui va bien et qui permettra aussi de contourner la limite des 5 renouvellements par semaine (en réalisant un roulement). Nous allons détailler ici un script qui, appelé chaque semaine, :

  • détecte les certificats qui ont moins de 30 jours de validité (2592000 secondes)
  • demande le renouvellement de chaque certificat dans ce cas

Voici le code du script :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done

Rapidement :

  • on commence par lister dans un tableau chaque domaine dont il faut s'occuper (en indiquant le chemin correspondant à ce domaine dans le dossier /etc/letsencrypt/live/) et, séparée par ";", la commande Letsencrypt utilisée pour le renouvellement. Il s'agit de la même commande que pour la création initiale du certificat sauf que l'on ajoute l'option "--renew-by-default"
  • on parcourt ensuite le tableau élément par élément :
    • en vérifiant l'âge du certificat (avec openssl)
    • en lançant la commande de renouvellement s'il est trop proche de la péremption

Si l'on utilise Letsencrypt avec Pound, on ajoutera 2 actions :

  • remplacer le fichier .pem utilisé par Pound par la nouvelle version obtenue
  • redémarrer Pound

Le script devient alors :

#!/bin/bash
declare -a list=(
"/etc/letsencrypt/live/domaine1.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine1/website -d domaine1.tld -d www.domaine1.tld"
"/etc/letsencrypt/live/sous.domaine1.tld;certbot --renew-by-default -a webroot --webroot-path /path/to/sous/domaine1/website -d sous.domaine1.tld -d www.sous.domaine1.tld"
"/etc/letsencrypt/live/domaine2.tld;certbot certonly --renew-by-default -a webroot --webroot-path /path/to/domaine2/website -d domaine2.tld -d www.domaine2.tld"
)

for line in "${list[@]}"
do
	IFS=";" read -ra stuff <<< $line
	folder=${stuff[0]}
	command=${stuff[1]}
        if openssl x509 -checkend 2592000 -noout -in $folder/fullchain.pem
        then
                echo "Nothing to do for $folder"
        else
                $command
                rm -f $folder/total.pem
                cat $folder/fullchain.pem $folder/privkey.pem > $folder/total.pem
                echo "Done for $folder"
        fi
done
service pound restart

Archive

Dans une ancienne version de ce billet, on utilisait le morceau de script suivant se basant sur la date de dernière modification du fichier de certificat plutôt que d'utiliser openssl, mais c'est moins propre. Pour archivage, voici le test qui était alors utilisé (renouvellement des certificats plus vieux que 60 jours) :

	timesincelastchange=$(expr $(expr $(date +%s) - $(date +%s -r $folder/fullchain.pem )) / 86400)
	if [ $timesincelastchange -gt 60 ]
	then
		$command
		echo "Done for $folder"
	else
		echo "Nothing to do for $folder"
	fi

Friday, July 10 2015

Routeur avec Tomato, Fibre Orange, VLAN 835

Comme déjà exposé ici, il est possible de se passer de la Livebox d'Orange et d'avantageusement la remplacer par un routeur "évolué" muni du micrologiciel Tomato.

Dans le précédent article, je détaillais le mode opératoire avec le routeur Asus RT-N16. J'ai eu l'occasion dernièrement de répéter l'opération avec l'Asus RT-N18U. Le nouveau mode opératoire est très similaire sauf qu'il ne faut pas utiliser de VID offset pour que cela fonctionne :

Paramétrage PPPoE pour le WAN

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

Puis on bascule le WAN dans le VLAN 835

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

  • On sélectionne la ligne correspondant au VLAN du WAN et on on saisit 835 comme VID.
  • Il ne faut pas oublier également de cocher la case 'Tagged' pour demander au retour de bien prendre en compte le trafic 'marqué' comme appartenant au VLAN 835.

vlan835-asus-rt-n18u.png

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

Sunday, May 17 2015

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

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

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

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

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

qos-settings-tomato.png

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

qos-plots-tomato.png

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

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

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

qos-limits.png

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

Bon QoSing !

Tuesday, March 10 2015

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

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

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

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

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

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

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

Thursday, January 8 2015

Activer un réseau Wifi invité sur un routeur avec le micrologiciel TomatoUSB

Nous allons détailler ici les étapes nécessaires pour activer un Wifi "invité" sur un routeur muni du micrologiciel Tomato (TomatoUSB). Par Wifi invité, j'entends un Wifi indépendant du Wifi principal : idéal par exemple pour partager sa connexion avec un voisin ou un ami que l'on ne souhaite pas voir fureter sur son réseau interne. Bien aussi pour les petites entreprises qui veulent présenter à leurs visiteurs un Wifi avec accès à internet mais déconnecté du reste du réseau de l'entreprise.

Voici donc comment procéder.

Etape 1 : créer une interface LAN spécifique avec son propre intervalle d'IP, son propre DHCP...

Dans TomatoUSB, dans l'onglet LAN, vous devriez vraisemblablement voir le bridge par défaut br0 correspondant à votre interface principale d'accès au Web. Nous allons ajouter une nouvelle interface br1 avec son propre DHCP et son propre intervalle d'IP.

guest-wifi-img1.png

Etape 2 : créer une interface sans fil virtuelle

Dans les fonctions avancées du micrologiciel TomatoUSB, nous allons cette fois ajouter une interface sans fil virtuelle.

guest-wifi-img2.png

Evidemment, il conviendra de choisir un code de sécurité différent de celui de l'interface principale !

Etape 3 : on place chaque réseau dans des VLANs distincts

On crée un nouveau VLAN distinct du VLAN principal utilisé pour br0. On branche donc br1 sur ce VLAN et voilà un bon cloisonnement !

guest-wifi-img3.png

Etape 4 : on rajoute une couche d'iptables

Dans Administration->Scripts, on ajoute les règles suivantes au pare-feu (iptables) pour n'autoriser aucun échange entre les 2 bridges.

iptables -P FORWARD DROP
iptables -A FORWARD -i eth0 -o br0 -j ACCEPT
iptables -A FORWARD -i br0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o br1 -j ACCEPT
iptables -A FORWARD -i br1 -o eth0 -j ACCEPT

et hop le tour est joué !

Friday, January 2 2015

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

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

La rotation des logs

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

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

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

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

Surveillance avec fail2ban

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

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

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

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

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

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

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

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

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

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

Monday, November 10 2014

Obtenir une bonne note chez SSLLabs avec Pound

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

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

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

Voici comment Joe décrit cette branche :

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

Compiler Pound 2.6-pcidss

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

qui doit retourner 2.6-pcidss.

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

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

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

Thursday, August 28 2014

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

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

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

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

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

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

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

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

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

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

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

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

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

On ajoute donc la ligne

localise-queries

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

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

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

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

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

"Fortiche" dnsmasq !

Sunday, May 11 2014

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

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

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

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

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

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

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

Bons paramétrages !

Sunday, March 23 2014

L'importance du paramètre TimeOut dans Pound

Pound est un reverse-proxy et un load-balancer libre fort perfomant. Il faut toutefois savoir que par défaut Pound n'attend pas plus de 15 secondes la réponse du serveur sous-jacent avant de retourner une erreur : "An internal server error occurred. Please try again later". Un 'timeout' de 15 secondes est suffisant pour de nombreux cas - cependant certaines requêtes sont parfois plus longues par exemple quand il s'agit de déclencher des requêtes importantes sur des bases de données, de lancer le téléchargement d'une grosse archive dans ownCloud ou de toute autre opération susceptible de prendre plus de 15 secondes à un serveur (notamment quand celui-ci est fortement sollicité par ailleurs).

Il est dès lors possible d'augmenter la durée du 'TimeOut' en ajoutant cette ligne :

  • soit dans la configuration globale de pound
  • soit dans la définitiond d'un 'backend' spécifique
TimeOut 150

Si 150 secondes n'est pas adapté, on modifie bien sûr la valeur.

Voilà qui devrait faire disparaître la plupart des erreurs "An internal server error occurred. Please try again later" !

Sunday, January 26 2014

SMTP Postfix en accord avec les RFC mais n'acceptant pas les utilisateurs s'authentifiant en clair

Quand on met à disposition un serveur SMTP à des utilisateurs, on aimerait s'assurer qu'ils ne communiquent pas leur mot de passe clair. Une solution consiste à interdire tout accès au SMTP sans SSL/TLS :

smtpd_tls_security_level = encrypt

mais cette option n'est pas compatible avec les RFC car alors tous les SMTPs doivent se connecter au vôtre avec SSL/TLS.

Il existe donc une autre possibilité plus élégante :

smtpd_tls_security_level = may
smtpd_tls_auth_only = yes

'' smtpd_tls_security_level = may'' autorise l'accès au serveur sans encryption (même si l'encryption est utilisée prioritairement si possible) tandis que "smtpd_tls_auth_only = yes" n'autorise les actions d'authentification (donc d'échange de mot de passe) que lorsque la connexion passe par un canal crypté.

Voilà qui répond au problème tout en respectant les RFC !

Sunday, November 10 2013

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

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

Au niveau des technologies utilisées...

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

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

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

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

aptitude install dibbler-client

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

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

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

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

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

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

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

On redémarre alors le réseau :

/etc/init.d/networking restart

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

puis on redémarre Dibbler par les commandes habituelles :

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

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

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

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

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

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

Puis on crée le volume physique :

pvcreate /dev/sdaX
vgcreate vg /dev/sdaX

et 2 volumes logiques de 50 Go :

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

Installation de LXC et déploiement du premier conteneur

aptitude install lxc lxc lxctl bridge-utils debootstrap unzip

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

cgroup        /sys/fs/cgroup        cgroup        defaults    0    0

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

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

On déploie un template fonctionnel :

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

et on lance la création du premier conteneur :

lxc-create -n myfirstcontainer -t debian-wheezy

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

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

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

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

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

auto eth0
iface eth0 inet static
    address 192.168.0.101

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

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

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

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

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

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

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

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

Lancement du conteneur

lxc-start -d -n myfirstcontainer

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

lxc-console -n myfirstcontainer

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

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

Dans le conteneur, on pourra vérifier que :

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

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

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

Exemple de configuration iptables sur l'hôte physique

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

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

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

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

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

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

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

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

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

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

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

## check backend every X secs:
Alive		180

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

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

ListenHTTP
	Address 88.123.123.123
	Port	80

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

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

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

End

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

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

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

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

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

End

- page 1 of 2