alix

Mon réseau

Ça faisait un petit moment que je devais refaire ma homepage. C'est chose faite (rechargez la page si vous avez encore l'ancienne en cache, c'est full statique avec un trèèèès long ttl).

J'y décris un peu ce qui se passe dans les trois serveurs que j'administre, pour moi, pour les amis, pour des logiciels libres comme wmfs et pour les causes que je défends avec une association, le cerf de grésigne et un miroir wikileaks.

En modifiant ma map nagios j'ai réussi à faire quelque chose de pas mal pour mieux visualiser la chose :

network

Ça fait maintenant deux ans que l'aventure a commencée, objectif auto-hébergement et auto-formation à l'administration systèmes. Je dois dire que ça a plutôt bien marché puisque l'infrastructure et mes connaissances n'ont cessés de progresser.

  • Fin 2008 Pendant les 3 premiers mois philpep.org n'existait que sur mon portable (sous gentoo, allumé 24h/24), c'était un serveur git pour partager mon code.
  • Début 2009 j'ai récupéré un vieux pentium III gracieusement donné par une association Toulousaine sur lequel j'ai installé FreeBSD (7.0 puis 7.1) qui a commencé à faire du mail.
  • Mai 2009 je récupère un pentium 4 avec plus de RAM.
  • Fin 2009 je m'achète une alix2d3
  • Début 2010 je prends une machine virtuelle chez lost-oasis (sous FreeBSD puis Debian) pour fournir un MX et DNS secondaire.
  • Juillet 2010 je m'achète une nouvelle machine avec plus de RAM et qui consomme moins
  • Fin 2010, la machine virtuelle est maintenant chez Hetzner, et sous FreeBSD 8.1 avec un vpn entre mes deux locations.

NanoBSD avec / en nfs

date
3 / 11 / 2010
comments
0

Dans un précédent post j'expliquais comment utiliser le script /usr/src/tools/tools/nanobsd.sh des sources FreeBSD pour construire un système FreeBSD pour l'embarqué.

Dans le processus de création d'un tel système, il peut être utile de tester son système sans utiliser la carte flash. On peut adapter le système en le testant sur NFS et n'écrire l'image finale sur la carte flash que quand on a fini.

kernel

Il faut compiler le kernel avec support NFS et NFS comme système de fichier racine

options NFSCLIENT
options NFS_ROOT

dhcpd.conf

Avec l'option root-path on spécifie le path du montage nfs au client dhcp.

filename "pxeboot";
next-server 192.168.0.20; # le serveur tftpd
option root-path "192.168.0.20:/usr/obj/nanobsd.solo/_.w; # le montage NFS

inetd.conf

Le bootloader pxeboot est récuperé via tftp, lui même activé par inetd

tftp    dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot

pxeboot

On compile pxeboot avec un baud de 115200 sur la sortie série.

cd /usr/src/sys/boot
make BOOT_PXELDR_ALWAYS_SERIAL=1 BOOT_COMCONSOLE_SPEED=115200
mkdir /tftpboot
cp i386/pxeldr/pxeboot /tftpboot

nfs

Juste une ligne dans /etc/exports, 192.168.0.1 étant l'IP donnée par mon serveur dhcp à la machine cible.

/usr/obj/nanobsd.solo/_.w -alldirs -maproot=root 192.168.0.1

rc.conf

On active tout ça dans /etc/rc.conf

 inetd_enable="YES"
 nfs_server_enable="YES"
 rpcbind_enable="YES"
 mountd_flags="-r"
 dhcpd_enable="YES"

Et on démarre les services :

 /usr/local/etc/rc.d/isc-dhcpd start
 /etc/rc.d/inetd start
 /etc/rc.d/rpcbind start
 /etc/rc.d/nfsd start

Maintenant il faut modifier le système généré par NanoBSD car il s'attend à avoir la carte flash comme système de fichier.

J'ai juste crée une fonction dans ma config nanobsd (fonction à enlever quand on crée les images disques bien entendu) :

post_nfsroot {
    rm ${NANO_WORLDDIR}/etc/fstab
    rm ${NANO_WORLDDIR}/conf/default/etc/remount
    echo "" > ${NANO_WORLDDIR}/conf/base/etc/fstab
}

late_customize_cmd post_nfsroot

Voilà, n'oubliez pas l'option -i pour gagner le temps de construction des images disques et bon debug :)

Ma conf NanoBSD

Je suis l'heureux possesseur d'une alix 2D3, un temps elle a tournée sous OpenBSD mais quand est venue la carte wifi non supportée j'ai du changer d'OS pour FreeBSD et les drivers madwifi. Un jour j'en ai eu marre de me battre avec mount -uw / et les devices md(4) et j'y ais mis une pfsense, au début l'interface web c'est convi, mais vite on se sent limité, et ne pas éditer mon pf.cont(5) avec vim me rendait malade.

Puis j'apprends qu'il existe un script dans les sources FreeBSD qui permet de faire une FreeBSD pour l'embarqué (ie, petite taille, lecture seule + ram disk). C'est marqué dans le titre, il s'agit de nanobsd(8).

C'est très bien foutu et on est assez émerveillé quand on connait pas les techniques de l'embarqué comme moi.

En gros vous faites un fichier de config en shell, /usr/src/tools/tools/nanobsd/nanobsd.sh se charge de vous compiler le world et le kernel et mettre tout ça dans une image disque.

Il y a beaucoup de paramètres customisables, une simple lecture du script vous les donnera tous. Nanobsd génère 2 images, une image disque complete (.disk.full) et une image avec seulement une partition (.disk.image). L'image complète comporte 3 partitions, les deux premières sont identiques en tailles et contiennent les mêmes données que .disk.image, lors de la première installation vous utilisez .disk.full, et pour mettre à jour vous utilisez _.disk.image à écrire sur la partition que vous n'utilisez pas actuellement (comme ça pas besoin de sortir la carte flash pour mettre à jour).

Nanobsd monte une des deux partitions sur / (en read-only), et deux ram disk pour /etc et /var (/tmp est linké avec /var/tmp, /usr/local/etc sur /etc/local). Pour rendre les changements sur /etc persistants, on utilise la troisième partition qui se monte sur /cfg, tout les fichiers de /cfg sont écrits sur /etc au boot.

Il y a un script simple pour comparer /etc et /cfg pour sauvegarder les changements.

% mount /cfg
% touch /cfg/rc.conf # si le fichier n'existe pas dans /cfg il n'est pas copié
% umount /cfg
% sh /root/save_cfg
/etc/rc.conf --> /cfg/rc.conf
%

Voyez le tgz avec ma config, vous y trouverez la config kernel, la config nanobsd, et les fichiers que j'ai mis dans /usr/src/tools/tools/nanobsd/Files/

Avec en particulier dnsmasq.conf qui bloque au niveau dns les publicités (avec une liste updatée tous les jours).

Mon alix sert donc de routeur, serveur dns/dhcp/impression. Sendmail relaye vers mon serveur interne, et syslog envoie tout à mon serveur.

% cd /usr/src/tools/tools/nanobsd/
% cp ~/solo/alix.cfg .
% cp -r ~/solo/Files/* Files/
% cp ~/solo/SOLO /usr/src/sys/i386/conf/
% sh nanobsd.sh -c alix.cfg
% wait
% qemu -hda /usr/obj/nanobsd.solo/_.disk.full -m 512 -no-acpi -nographic -cpu pentium
# Hmm quelque chose ne va pas, mais j'ai pas envie de rebuild world et/ou kernel
% sh nanobsd.sh -h

Mon script utilise des packages préconstruits, si vous voulez les compiler vous même il y a une fonction pour ça dans nanobsd.sh

Pour finir (ou commencer), voici la doc nanobsd

Voilà, ma config est certainement loin d'être parfaite niveau taille système mais ma carte flash fait 4G (donc 2G utilisable pour le système) et c'est largement suffisant pour faire tourner une FreeBSD "pas trop dépouillée".

Pour mettre à jours (j'ai gzip mon image avant) en supposant que le système tourne sur la partition 1:

% ssh phil@aldo cat /usr/obj/nanobsd.solo/_.disk.image.gz | zcat | sh updatep2
% reboot

J'ai modifié updatep{1|2} en ajoutant gpart set -a active -i PARTITION_INDEX ad0 en raison d'un problème que vous aurez peut être (la nouvelle partition est pas marquée active...)

Si le sujet vous intéresse, il y a un projet linux embarqué sympa qui s'appelle buildroot où là on peut carrément construire sa chaîne de compilation croisée (arm, mips etc), et construire un système embarqué très personalisé. Dommage qu'il n'existe pas un tel projet basé sur le kernel BSD (un jour peut être...)

Jouons avec kvm

date
13 / 2 / 2010
comments
1

J'ai codé un petit programme tout simple qui fait clignoter les leds de mon routeur dès qu'un service est par terre. Ma méthode (qui ne doit pas être la meilleure mais je m'en fout un peu) consiste à regarder régulièrement la liste des processus et détecter l'arrêt d'un service quand le processus associé n'existe plus. J'ai commencé avec un script shell, puis étant assez mauvais pour tout ce qui ressemble de près ou de loin à du script j'ai décidé de le faire en C (langage d'excellence n'est ce pas...?).

Je me suis volontairement compliqué la tache en utilisant des fonctions très proches du système, ainsi s'il est possible d'obtenir une liste de processus via ps(1) avec un popen(3) super crade ou encore sysctl(3) j'ai voulu utiliser kvm(3) kernel memory interface qui est en programmation système la méthode la plus appropriée (d'ailleurs 'ps' est codé avec ça), c'est juste une interface qui va nous permettre d'accéder au données du kernel (une copie bien entendu), ici la liste des processus en cours.

Le hic c'est que si les fonctions de kvm sont très standard l'implémentation est très différente suivant les systèmes, comme à peu près toute implémentation, l'important c'est que l'interface soit standard. Ainsi à la lecture de la structure qui décrit les processus kinfo_proc de sys/user.h on se dit chouette pleins d'info à disposition, sauf que sur OpenBSD c'est pas du tout la même forme (ni le même fichier d'ailleurs). D'où l'importance d'une interface riche et c'est ce que nous promet kvm.

Assez causé passons au code (je n'explique pas ou peu le code en dehors des fonctions kvm)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <libgen.h>
#include <fcntl.h>
#include <limits.h>
#include <paths.h>
#include <kvm.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <sys/user.h>

void
start_leds(void)
{
    /* Ici on execute /usr/sbin/gioctl -q gpio0 led3 (on|off)
     * suivant la parité du conteur statique 'i'
     * 60 fois avec une pause d'une seconde. */
    static int i = 1;
    switch(fork())
    {
        case -1:
            err(1, "fork");
            break;
        case 0:
            execl("/usr/sbin/gpioctl", "gpioctl", "-q", "gpio0",
                    "led3", (i%2) ? "on" : "off", (char*)NULL);
            err(1, "execl");
            break;
        default:
            wait(NULL);
            break;
    }
    sleep(1);
    if (i++ <= 60)
        return start_leds();
    return;
}

int
main(int argc, char *argv[])
{
    kvm_t *kd;
    char berr[_POSIX2_LINE_MAX];
    struct kinfo_proc *p, *procs;
    int n, j, k, found = 0;
    char **pargv;

    if (argc < 2)
        errx(1, "Usage check_proc procs ...");

    /* On accède aux données du kernel qui tourne actuellement (NULL) */
    if (!(kd = kvm_open(NULL, NULL, NULL, O_RDONLY, berr)))
        errx(1, "%s", berr);

    /* On demande la liste des processus, kinfo_proc est décrite
     * dans sys/sysctl.h sur OpenBSD et sys/user.h sur FreeBSD.
     * Il nous la donne dans un tableau continu de pointeurs de
     * taille qu'on récupère dans 'n'. */
    if (!(procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &n)))
        err(1, "kvm_getprocs: %s", kvm_geterr(kd));

    for (k = 1; k < argc; k++)
    {
        for (j = 0, p = procs; j < n; j++, p++)
        {
            /* On accède à la liste des arguments du programme qui a
             * généré le processus courant. */
            pargv = kvm_getargv(kd, p, 0);
            if (pargv && pargv[0] &&
                    strstr(pargv[0], argv[k]))
                {
                    found++;
                    break;
                }
        }
    }

    if (-1 == kvm_close(kd))
        err(1, "kvm_close");

    if (found != argc-1)
        start_leds();

    return 0;
}

Et l'exécution, on veut tester si un processus du nom de 'dhcpd' tourne sur le système, si ce n'est pas le cas on lance le clignotement de la led pendant une minute :

# gcc -o check_proc check_proc.c -lkvm
# ./check_proc dhcpd

Le mien s'exécute dans un cron toute les minutes :

* * * * * /root/bin/check_proc named dhcpd adsuck ntpd

Alix fail et OpenWrt

Ce week end j'ai essuyé pas mal d'échecs en tout genres, j'ai une superbe alix qui tourne sur OpenBSD et j'ai une carte wifi en minipci dessus qui marche passablement mal sur OpenBSD (tous les modes ne marchent pas et beaucoup de pertes de paquets quand ça marche).

Du coup je me mis en tête le fait que ça tournera mieux sous un autre OS, j'ai donc essayé dans l'ordre FreeBSD, Debian et OpenWrt. Aucuns n'a su faire tourner ma carte même avec les derniers drivers, j'avais même pas d'interface, comme quoi le support matériel sur OpenBSD est pas aussi mauvais qu'on le pense.

Donc si quelqu'un à réussi à faire tourner convenablement la carte Engenius NMP-8602+ 400mW a/b/g miniPCI sur un OS libre merci de me faire signe.

J'ai donc remis OpenBSD dessus et enlevé la carte wifi (si quelqu'un est intéressé je suis prêt à la céder d'ailleurs, toute neuve jamais servie :>)

J'ai quand même beaucoup joué avec le boot pxe sur sortie série Linux/BSD donc je suis bien rodé là dessus maintenant. Et surtout j'ai découvert OpenWrt, une toute petite distribution linux pour l'embarqué, faite à la base pour flasher les firmware proprio sur les routeurs du marché elle tourne aussi bien sur tout autre matériel et c'est un projet très dynamique et original. L'installation par pxe est super simple, il suffit de compiler un ramdisk et de démarrer dessus.

$ ls -l /usr/local/pxe/
total 1796
-rw-r--r--  1 phil  phil   1786396 Feb  7 15:41 openwrt-x86-vmlinuz
-rwxr-xr-x  1 root  wheel    16466 Feb  6 21:31 pxelinux.0
drwxr-xr-x  2 root  wheel      512 Feb  7 15:41 pxelinux.cfg
$ cat /usr/local/pxe/pxelinux.cfg/default
# Simplement spécifier la vitesse du port série
# 38400 ici
serial 0 38400 0
console 0
label linux
kernel openwrt-x86-vmlinuz
append init=/etc/preinit console=tty0 console=ttyS0,38400n8 reboot=bios

Après c'est du pxe classique, tftp et dhcpd et ça démarre :

openwrt

Après il suffit d'envoyer l'image sur le disque dur (soit la votre, soit celle qui est distribuée) :

root@Solo:/# wget http://downloads.openwrt.org/kamikaze/8.09.2/x86/openwrt-x86-squashfs.image
root@Solo:/# dd if=openwrt-x86-squashfs.image of=/dev/hda

Et c'est tout !

À coté de ça vous avez une interface de configuration web convi, un petit sshd dropbear et pleins de packages disponible (très orienté réseau bien sûr). Ça doit être encore plus réjouissant quand on flashe un routeur wifi proprio :)

Mais bon, alix mérite qu'on l'exploite plus que ça, j'aime bien l'interface web mais j'aime mieux éditer mon pf.conf avec vim.