Une NetBSD 5.0.1 en DomU Xen, c’est tout mignon

Depuis hier soir, une nouvelle machine virtuelle (DomU) est online sur le serveur : de son petit nom hippo-dns (et d’adresse dns.hippopota.me), elle héberge simplement un serveur Bind9 afin de me permettre de gérer directement de chez moi mon nom de domaine.

En effet, précédemment je laissais cette tâche aux bons soin de mon registrar, mais le faire soi-même n’a rien de compliqué, et c’est encore un pas de plus vers l’indépendance et la connaissance.

Et donc il y a deux semaines, j’ai mis en place un nouveau DomU Debian Lenny pour ça, avec un succès total (merci monsieur Zorg au passage ;) ).

Mais, regrettant depuis pas mal de temps le manque de variété dans mes machines virtuelles (que des Debian Lenny, en fait), et ayant bricolé de façon fort satisfaisante avec l’OS qui va nous intéresser, je me suis mis en tête de basculer ce serveur DNS du côté démoniaque du libre.

Plus précisément, sous cette bannière orange :
(plus familièrement appelée la serviette orange, par les initiés)

Pourquoi ce choix ?

Tout simplement parce que c’est le seul BSD à supporter pleinement Xen en paravirtualisé, et ce, en Dom0 ou en DomU.
(pour FreeBSD c’est en cours et prévu de façon stable pour la 8.0 il me semble, mais limité à du DomU et uniquement en 32 bits)

De plus, mes diverses installations pour découvrir la bête m’ont laissé une très bonne impression, bien meilleure qu’avec OpenBSD ou FreeBSD … question de feeling, sûrement.

Pour l’installation ça se passe comme dans du beurre.
(je ne vais pas tout décrire, ça n’est vraiment pas intéressant, lire la doc sera beaucoup plus utile)
J’ai fait à ma sauce.
Mais globalement le chemin est celui décrit dans ce lien : on se prépare ses petits volumes logiques LVM, son petit fichier de conf de DomU, on télécharge deux kernels NetBSD que l’on place quelque part sur son Dom0, l’un servira à booter une install par FTP (netbsd-INSTALL_XEN3_DOMU.gz), et l’autre (netbsd-XEN3_DOMU.gz) servira à faire tourner le DomU une fois installé.
Les kernels sont dispos sur les miroirs NetBSD, par ici entre autres.

L’installeur NetBSD est très clair et plutôt simple je trouve, bien loin de celui d’OpenBSD par exemple :D

L’installation terminée, on modifie bien sûr son fichier de conf pour booter sur le kernel définitif, et un xm create plus tard … ça boote, tourne et s’administre à merveille, à quelques subtilités près, propres aux habitudes bien différentes à avoir sous un système BSD par rapport à une Debian.

J’ai compilé Bind 9.6.1-P1 depuis pkgsrc, ai repris ma conf Bind de Debian, et ai substitué ce nouveau DomU à l’ancien sous Debian, le tout sans le moindre problème.

Depuis, ça tourne et ça ne bronche pas (en même temps, vue la charge …).

Comme d’habitude, le petit uname de rigueur :

hippo-dns$ uname -a
NetBSD hippo-dns.hippopota.me 5.0.1 NetBSD 5.0.1 (XEN3_DOMU) #0: Thu Jul 30 00:31:11 UTC 2009  builds@b7.netbsd.org:/home/builds/ab/netbsd-5-0-1-RELEASE/amd64/200907292356Z-obj/home/builds/ab/netbsd-5-0-1-RELEASE/src/sys/arch/amd64/compile/XEN3_DOMU amd64

Je ne basculerais sûrement pas tous mes DomU sous NetBSD (je ne suis pas encore totalement à l’aise avec), mais c’est (je trouve) une alternative intéressante quand on veut un peu diversifier son parc virtuel, tout en gardant les nombreux avantages d’un système para-virtualisé (perfs, non-dépendance aux instructions CPU de virtualisation, …).

Viendez, c’est l’été et il reste de la place sur la serviette orange :o

DDoS

Hier soir, c’était ma première fois.

Et ça a fait un peu mal.

En effet, un peu fatigué par ma journée, je me mets en tête d’aller voir un truc sur mon site avant d’aller me coucher, et « tiens, ça ne loade pas ? ».

« Bizarre le serveur rame, pas moyen d’afficher une page … »

Impossible de chopper une connexion SSH sur le DomU web … o_O … et il ne répond pas au ping.

Ni une ni deux, je me connecte à mon Dom0 Xen et je regarde l’état des DomU : la machine virtuelle web (une Debian faisant tourner Apache et PHP) moulinait dans le vide, complètement zombifiée.
Impossible à éteindre proprement, je la destroy illico.

Je la redémarre dans la foulée, sans aucun problème, le site reprend vie, et je commence à regarder les logs système.

/var/log/messages :

[...]
Aug 10 20:57:06 hippo-web kernel: [2722357.751055] apache2 invoked oom-killer: gfp_mask=0x1201d2, order=0, oomkilladj=0
Aug 10 20:57:06 hippo-web kernel: [2722357.751083] Pid: 1698, comm: apache2 Not tainted 2.6.26-2-xen-amd64 #1
Aug 10 20:57:06 hippo-web kernel: [2722357.751089]  
Aug 10 20:57:06 hippo-web kernel: [2722357.751090] Call Trace:
Aug 10 20:57:06 hippo-web kernel: [2722357.751107]  [<ffffffff80266f86>] oom_kill_process+0x59/0x203
Aug 10 20:57:06 hippo-web kernel: [2722357.751114]  [<ffffffff80233fd5>] __capable+0x9/0x1c
Aug 10 20:57:06 hippo-web kernel: [2722357.751121]  [<ffffffff802674f4>] out_of_memory+0x186/0x1c0
Aug 10 20:57:06 hippo-web kernel: [2722357.751127]  [<ffffffff80269830>] __alloc_pages_internal+0x310/0x3b2
Aug 10 20:57:06 hippo-web kernel: [2722357.751135]  [<ffffffff8026b6da>] __do_page_cache_readahead+0x95/0x1a7
Aug 10 20:57:06 hippo-web kernel: [2722357.751142]  [<ffffffff80266797>] filemap_fault+0x15d/0x346
Aug 10 20:57:06 hippo-web kernel: [2722357.751150]  [<ffffffff802719bd>] __do_fault+0x51/0x4f5
Aug 10 20:57:06 hippo-web kernel: [2722357.751164]  [<ffffffff80276708>] handle_mm_fault+0x5f8/0xc46
Aug 10 20:57:06 hippo-web kernel: [2722357.751172]  [<ffffffff802181a3>] do_page_fault+0xb69/0xf46
Aug 10 20:57:06 hippo-web kernel: [2722357.751182]  [<ffffffff80435dc7>] error_exit+0x0/0x69
Aug 10 20:57:06 hippo-web kernel: [2722357.751188]  
Aug 10 20:57:06 hippo-web kernel: [2722357.751191] Mem-info:
Aug 10 20:57:06 hippo-web kernel: [2722357.751194] DMA per-cpu:
Aug 10 20:57:06 hippo-web kernel: [2722357.751198] CPU    0: hi:    0, btch:   1 usd:   0
Aug 10 20:57:06 hippo-web kernel: [2722357.751202] DMA32 per-cpu:
Aug 10 20:57:06 hippo-web kernel: [2722357.751206] CPU    0: hi:  186, btch:  31 usd: 176
Aug 10 20:57:06 hippo-web kernel: [2722357.751211] Active:238781 inactive:57 dirty:0 writeback:0 unstable:0
Aug 10 20:57:06 hippo-web kernel: [2722357.751213]  free:2052 slab:4341 mapped:4 pagetables:0 bounce:0
Aug 10 20:57:06 hippo-web kernel: [2722357.751221] DMA free:4068kB min:60kB low:72kB high:88kB active:7836kB inactive:0kB present:16160kB pages_scanned:15528 all_unreclaimable? yes
Aug 10 20:57:06 hippo-web kernel: [2722357.751229] lowmem_reserve[]: 0 1002 1002 1002
Aug 10 20:57:06 hippo-web kernel: [2722357.751238] DMA32 free:4140kB min:4016kB low:5020kB high:6024kB active:947288kB inactive:228kB present:1026160kB pages_scanned:668175 all_unreclaimable? no
Aug 10 20:57:06 hippo-web kernel: [2722357.751248] lowmem_reserve[]: 0 0 0 0
Aug 10 20:57:06 hippo-web kernel: [2722357.751255] DMA: 3*4kB 1*8kB 1*16kB 10*32kB 18*64kB 6*128kB 1*256kB 1*512kB 1*1024kB 0*2048kB 0*4096kB = 4068kB
Aug 10 20:57:06 hippo-web kernel: [2722357.751272] DMA32: 65*4kB 1*8kB 1*16kB 1*32kB 0*64kB 0*128kB 1*256kB 1*512kB 1*1024kB 1*2048kB 0*4096kB = 4156kB
Aug 10 20:57:06 hippo-web kernel: [2722357.751288] 59 total pagecache pages
Aug 10 20:57:06 hippo-web kernel: [2722357.751293] Swap cache: add 0, delete 0, find 0/0
Aug 10 20:57:06 hippo-web kernel: [2722357.751296] Free swap  = 0kB
Aug 10 20:57:06 hippo-web kernel: [2722357.751299] Total swap = 0kB
Aug 10 20:57:06 hippo-web kernel: [2722357.754803] 264192 pages of RAM
Aug 10 20:57:06 hippo-web kernel: [2722357.754815] 6109 reserved pages
Aug 10 20:57:06 hippo-web kernel: [2722357.754818] 50432 pages shared
Aug 10 20:57:06 hippo-web kernel: [2722357.754822] 0 pages swap cached
[...]

Indéfiniment jusqu’à 21:05, heure à laquelle le serveur a apparemment complètement implosé.

Donc Apache nous ferait une fuite mémoire ? Bizarre quand même, et de manière aussi virulente …

Un petit tour dans le errors.log d’Apache :

[...]
[Mon Aug 10 20:57:51 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 20:58:10 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 20:58:36 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 20:58:50 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:00:55 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:01:24 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:01:45 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:02:09 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:02:33 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:03:09 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:03:41 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:03:55 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:04:18 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:04:48 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[Mon Aug 10 21:05:34 2009] [error] (12)Cannot allocate memory: fork: Unable to fork new process
[...]

Une telle surcharge pondérale en si peu de temps, je commence à flairer le truc louche.

Et après un tour dans mon access.log, mes soupçons se confirment : tout au long de la journée, je commence à avoir des visites plutôt bizarres de machines situées à l’étranger.
Puis à 20:52, ça se déchaîne : un quantité hallucinante de requêtes simultanées de dizaines d’IP différentes, avec toutes le même UserAgent bateau : « Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ».

Et ce, jusqu’à 21:05, heure où le serveur web est tombé.
J’ai donc été victime d’une attaque par DDoS (déni de service distribué), un type d’attaque extrèmement difficile à contrer du fait de la multiplicité des IP assaillantes (des machines « zombies » mal protégées par leur propriétaire, et passées sous le contrôle d’une personne malveillante).
Le but de cette attaque est de saturer un serveur de requêtes simultanées pour le conduire au plantage par épuisement de ressources.

Et puis … pas grand chose depuis.
Après le reboot, le serveur tourne de nouveau à merveille, encore quelques accès de machines louches, mais pas d’attaque de l’ampleur de celle d’hier.

Qu’en retenir ?

Qu’il faut tout d’abord que j’essaye de m’en prémunir, il n’est pas très satisfaisant de voir son serveur s’écrouler en 13 minutes.
Des pistes ?

  • Configurer plus finement mon Apache : c’est ce que j’ai commencé à faire, en tant que mesure « d’urgence », en réduisant les timeout et le nombre maximum de connexions simultanées.
    Ça ne peut que retarder la mort du serveur en cas d’attaque, et donc seulement prolonger l’agonie, mais c’est toujours mieux que rien.
    Apparemment, des modules pour Apache fournissent des focntionnalités de protection, je vais m’y intéresser.
  • Abandonner Apache ?
    En effet, pour ce que j’en fais, Apache est relativement « usinesque ».
    Et sa réputation de voracité sous charge lourde et de vulnérabilité aux DoS me semble aujourd’hui bien fondée.
    J’aurais peut-être avantage à passer sur un serveur web plus léger et résistant à ce type d’attaque, tel NGINX.
    C’est à étudier.

D’autre part, je me demande bien l’intention qui était derrière ça.
Sûrement un petit « script kiddy » qui n’a rien de plus intelligent à foutre que de faire tourner des scripts tout prêts pour emmerder le monde.
La connerie humaine est habituelle, mais elle surprend toujours un peu quand elle se présente à nous :D

Le mot de la fin sera par contre positif : en effet, cet épisode démontre (s’il était encore nécessaire de le faire) toute l’utilité et la puissance de Xen.
En effet, si la machine virtuelle dans laquelle réside Apache s’est écroulée, tout le reste du serveur a continué à tourner comme une horloge (le Dom0 ainsi que les différents DomU officiant comme serveurs MySQL, NFS/Samba et Bind), montrant ainsi l’excellente isolation que Xen permet d’obtenir :)

Bref, un peu de piment dans la vie d’un admin en herbe :D

Nouveau serveur, les détails

Comme promis, quelques détails concernant le nouveau serveur de Hippopota.me : il est donc opérationnel depuis la semaine dernière, la migration s’est très bien faite (hormis deux-trois bêtises de ma part, c’était prévisible :D ) et tout tourne parfaitement.

Comparé à l’ancien (un petit P3 1Ghz avec 256Mo de RAM et un disque de 250Go IDE, sous Ubuntu Server 7.10), j’ai fait les choses en grand ;)

Un nouveau hardware

Laissez-moi donc vous le présenter :

Son hostname est « hippo », pour la base il s’agit d’un PC constitué d’un processeur Core 2 Duo E4400 et de 4 Gio de PC2-6400, montés sur une carte mère Gigabyte GA-EP35-DS3.

C’est tout simplement mon ancien PC desktop, que j’ai reconverti ;)
(et dans un nouveau boîtier)

Concernant la partie « disques » :

  • Un binôme de deux disques de 250 Gio (Samsung Spinpoint P120 & Hitachi P7K500) forme un RAID-1 soft qui a pour mission d’héberger le système et les machines virtuelles (j’y reviendrai ;) ). Le but étant d’assurer une continuité en cas de défaillance d’un disque, et éviter de perdre toute la configuration.
  • Un disque de 320 Gio (Samsung Spinpoint F1) s’occupe pour l’instant du stockage de nos fichiers persos. « Pour l’instant » car il est amené à être remplacé prochainement par du plus gros, normalement un 1 Tio.

Petite parenthèse « software » : j’ai tout partitionné en LVM, je peux donc repartitionner à loisir, ajouter et retirer des disques, faire des snapshots, … dans la joie et l’allégresse.

Niveau réseau, je profite de la puce Realtek 1Gbps intégrée, et j’ai ajouté une Intel PRO/100 PCI qui s’occupe du trafic sortant vers Internet (le port 1Gbps étant réservé au réseau local).
Je vais bientôt ajouter une deuxième Intel PRO/100 (le temps de la retrouver) qui sera dédiée à l’administration du serveur.
Il y a enfin une carte Leadtek DTV 1000 T que j’utiliserai pour faire du streaming TNT en local.

Pas de carte graphique ni d’écran ou de clavier, tout est administré par SSH.

Le tout est alimenté pour l’instant par une Seasonic S12 550W (bientôt remplacée par une Corsair CX400W) et assemblé à l’intérieur d’un Antec Three Hundred.

(l’OCZ Vendetta n’est là que temporairement)

Donc une configuration plutôt puissante pour l’usage, mais bon, le but est aussi de se faire plaisir, et c’est également le cas pour la partie software :D

Du software qui arrache

Le système d’exploitation devient donc Debian, en version 5.0 (Lenny) et x86_64 mais, grosse subtilité, il tourne derrière l’hyperviseur libre Xen, en version 3.2-1 :D

De la virtualisation avec un hyperviseur

Sur ce qu’est un hyperviseur, je ne vais pas réinventer la roue, en me contentant de citer Wikipedia :

En informatique, un hyperviseur est une plate-forme de virtualisation qui permet à plusieurs systèmes d’exploitation de travailler sur une machine physique en même temps.

L’hyperviseur est un noyau hôte allégé et optimisé pour ne faire tourner que des noyaux d’OS invités adaptés et optimisés pour tourner sur cette architecture spécifique, les OS invités ayant conscience d’être virtualisés.

Concrètement, ça me permet de faire fonctionner plusieurs OS en même temps sur le même serveur, de les affecter par exemple à telle ou telle carte réseau (ou utiliser des vlan), afin d’obtenir le même résultat qu’en ayant plusieurs machines, mais avec les contraintes d’une seule (consommation électrique, encombrement, …).

La différence avec un logiciel comme VirtualBox, c’est qu’il s’agit ici de para-virtualisation (PV) : l’OS invité est modifié pour pouvoir tourner au dessus de l’hyperviseur.
On comprend donc bien que cela n’est possible qu’avec des OS libres : actuellement on peut faire tourner du Linux, NetBSD, OpenSolaris et FreeBSD (expérimentalement pour l’instant).

Xen supporte également la virtualisation complète (HVM), mais :

  • Il est nécessaire de posséder un processeur disposant des instructions de virtualisation hardware (VT chez Intel, AMD-v chez AMD)
  • Les performances sont bien inférieures à du PV

Alors qu’en PV, n’importe quel processeur x86 ou x86_64 est supporté, et les performances sont de l’ordre de 80-90% du natif.

Néanmoins, cela permet de faire fonctionner un Windows comme machine virtuelle de Xen.
(c’est se donner beaucoup de mal pour faire tourner un mauvais OS, vous en conviendrez :D)

Sous Xen, il existe deux types de machines virtuelles, qui sont appelées « domaines » :

  • Le Domaine 0 (Dom0) : Il ne faut pas le confondre avec l’OS hôte, ici l’OS hôte c’est Xen, le Dom0 n’est qu’un système invité, une machine virtuelle, même si il est un peu spécial.
    Il ne peut y en avoir qu’un sur la machine (et il est indispensable), c’est la machine virtuelle principale, celle à laquelle l’hyperviseur accorde tous les privilèges liés au matériel et la seule qui peut gérer les autres machines virtuelles. C’est aussi à l’intérieur du Dom0 que sont transmises toutes les tâches d’I/O liées aux disques et au réseau, entre autres.
    Sa sécurité est capitale, quiconque prend la main sur le Dom0 peut administrer toutes les autres machines virtuelles.
  • Les DomU : ce sont les machines virtuelles qui n’ont aucun privilège matériel accordé par Xen, elles ne peuvent accéder qu’aux ressources qu’on leur accorde dans leur fichier de configuration.

Typiquement, pour des impératifs de sécurité et de performance, il faut faire tourner le moins de choses possible dans le Dom0 (et même rien du tout, si possible) et blinder le plus possible sa sécurité, pour faire tourner les services dans différents DomU, que l’on segmentera selon ses besoins.
Il est théoriquement possible de faire tourner autant de DomU que l’on veut, les seules limites seront matérielles (la mémoire est en général le facteur limitant).

Chaque DomU est un système indépendant (un kernel propre à chacun, et la possibilité de faire tourner des systèmes différents). Pour la sécurité, c’est un gros avantage, car si l’on a bien conçu son réseau et ses domaines, la perte d’un DomU n’entame pas la sécurité des autres.
De la même manière, diversifier ses DomU (OpenSolaris, NetBSD, Linux) permet de ne pas « mettre tous ses oeufs dans le même panier », encore un avantage du point de vue sécurité.

En pratique

Sur mon serveur, il y a donc deux DomU différents pour la partie web : un DomU pour la base de données, et un autre pour Apache/PHP. Ils sont situés sur la partie « exposée » (DMZ) de mon réseau.

J’ai également un autre DomU qui me sert de NAS (NFS & Samba), situé directement sur mon réseau local.

Pour l’instant, tous mes DomU sont des Debian Lenny x86_64.

En lançant diverses commandes depuis le Dom0, on peut gérer ses domaines, ici par exemple pour afficher l’état des domaines qui tournent :

hippo:~# xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0   946     1     r-----   6105.4
hippo-mysql                                 13   512     1     -b----     29.8
hippo-nas                                   11  1024     1     -b----     32.4
hippo-web                                   12  1024     1     -b----    193.5

(on peut observer dans l’ordre mon Dom0, puis mes 3 DomU, leur ID à ce moment-là, leur quantité de RAM allouée, le nombre de CPU virtuels affectés à chacun, leur état (ici « blocked » c’est à dire en idle) et l’utilisation totale CPU pour chacun.)

Pour se logger sur un domaine, on le fait soit classiquement par SSH (ou un autre moyen type VNC, …), soit directement depuis le Dom0 avec un « xm console <nomdudomU> ».

Il y a aussi un « top » spécifique, qui affiche en temps réel l’occupation en ressources de chaque domaine, etc … toutes les commandes sont décrites dans le manuel.

Les possibilités sont vraiment immenses, pour peu que l’on prenne le temps de lire la doc et de regarder un peu comment tout fonctionne.

Au final

Bref, ayant mis tout ça en place, j’en suis bien content, ça tourne à merveille et c’est vraiment sympa à faire :)
(en plus c’est un truc de nerd, ce qui ne gâche rien)

A l’avenir ça va évoluer, le nombre de DomU augmentera avec l’ajout de services de streaming, réseau, internet, mail, …

Cet article pourrait faire des pages entières, je pense pour l’instant me contenter de cette présentation succinte, et sûrement faire des articles au fur et à mesure sur des points précis de la configuration, mais n’hésitez pas à me demander des choses plus précises dans les commentaires (en même temps je ne fais que débuter dans le domaine …)

Cet article était surtout une manière de vous présenter ma jolie machine et de vous faire part de ma satisfaction quant à la manière dont je l’ai réalisée :)

Ah, j’allais oublier, la petite tradition pour chaque nouvelle machine, un petit « uname -a » s’impose :

Linux hippo 2.6.26-2-xen-amd64 #1 SMP Wed May 13 18:43:45 UTC 2009 x86_64 GNU/Linux

Longue vie à lui ! ;)


Quelques références sur Xen :