Categorie: OpenWRT
mail

Ce billet présente les quelques changements qui surviennent avec la nouvelle version stable d'OpenWRT. Je sais, je suis un peu en retard de plus d'un an m'enfin bon ... :P

Table des matières

Ce billet est dans la continuité de mes autres billets sur OpenWRT et notamment de ce billet : Créez votre image personnalisée d’OpenWRT : ce qui change avec Backfire 10.03.1. Référez-vous à ces billets si quelque chose ne vous semble pas clair dans ce billet.

Ce qui change / ce que je change

Depuis tout ce temps, il y a eu des mises à jour que ça soit pour la sécurité ou le confort. Passer de Backfire à Attitude Adjustment permet d'en profiter.

Je ne souhaite plus faire de DROP en output sauf ce qui est autorisé. Je souhaite tout autoriser en sortie. D'un point de vue de la sécurité pure, c'est une perte. D'un point de vue du confort des utilisateurs placés derrière ce firewall, c'est un gain. Et comme je ne suis plus le seul utilisateur de ce réseau ... Il suffira de modifier le script /etc/init.d/firewall qui positionne les règles.

J'aurais souhaité remplacer mon récursif-cache DNS actuel, djbdns dnscache, par un autre, comme Unbound. La raison est que dnscache ne supporte pas des types d'enregistrements (exemple : NAPTR) et surtout, il ne fait pas de validation DNSSEC. Malheureusement, en choisissant Unbound et Unbound-anchor, la taille de l'image générée est de 4,5M. En supprimant LuCi, je peux tomber à 4,1M. Dans tous les cas, l'image est trop imposante pour mon WRT54GL. Donc il n'y aura pas encore de récursif-cache validant sur ce réseau puisque je suis contraint de rester avec dnscache.

Je n'ai plus besoin du package ddns-scripts proposé par OpenWRT car je n'utilise plus DynDNS (ou un autre service équivalent) mais ma propre méthode. Il faudra simplement créer le fichier /etc/crontab/root et placer la clé privée dans l'arborescence de Buildroot comme indiqué dans le billet linké.

J'effectuerai la compilation dans un tmpfs. Cela permet un gain important, notamment quand vous utilisez une machine qui est limitée par ses IO disk comme moi. La compilation utilise ccache. Il faudra le configurer car, par défaut, il met ses fichiers dans le home directory de l'utilisateur ... donc le gain du tmpfs dans ce cas-là est quasi-nul ...

Recréer l’image officielle

Presque rien ne change par rapport à mon billet sur Backfire à part l'utilisation d'un tmpfs et quelques URL.

Nous allons d'abord préparer notre Debian Wheezy (qui est devenue stable, depuis ;) ) pour recevoir Buildroot :

sudo apt-get install asciidoc autoconf bison build-essential fastjar flex gawk gettext git-core intltool libextutils-autoinstall-perl libncurses5-dev libssl-dev libtool subversion zlib1g-dev

Nous allons créer le tmpfs (source : tmpfs : utiliser sa RAM comme répertoire de stockage. - Génération Linux. Personnellement, /tmp utilise déjà tmpfs. J'augmente donc simplement sa taille :

sudo mount -t tmpfs -o remount,size=7G tmpfs /tmp

En dessous de 8G de RAM, oubliez l'idée d'un tmpfs car la compilation du toolchain, du noyau et des packages que je sélectionne occupe facilement 5G/5,5G. Avec 8G de RAM, vous pouvez avoir un tmpfs de 7G qui vous permettra de compiler le cross-compiler, le noyau et les packages que vous voudrez (j'insiste : vous ne pourrez pas compiler tous les packages en "module").

Avec 7G sur 8G attribués au tmpfs, faites attention à ne pas lancer des applications gourmandes en RAM comme Firefox ou Eclipse (au pif hein :P ) en parallèle sinon le noyau va s'énerver et vous allez recevoir la visite de l'OOM Killer.

On se positionne dans notre tmpfs, on récupère les sources d'Attitude Adjustment (pour connaître l'adresse des dépôts : GetSource - OpenWrt) puis on se positionne dans le dossier des sources :

cd /tmp
svn co svn://svn.openwrt.org/openwrt/branches/attitude_adjustment
cd attitude_adjustment/

Dans la suite de ce billet, sauf mention contraire, je considérerai que votre répertoire courant est attitude_adjustment, c'est-à-dire la racine du buildroot.

On s'assure que tout le nécessaire est bien présent :

make defconfig && make prereq

On met à jour la liste des packages disponibles :

./scripts/feeds update -a && ./scripts/feeds install -a

Ensuite, on efface les fichiers de configuration de la compilation (créés automatiquement par make menuconfig, par exemple, nous y reviendrons) :

rm .config && rm .config.old

On récupère le fichier de configuration officiel (ici : déclinaison brcm47xx) :

wget http://downloads.openwrt.org/attitude_adjustment/12.09/brcm47xx/generic/config.brcm47xx_generic -O .config

Pour raccourcir le temps de la compilation, on désactive la compilation de l'image builder (« Build the OpenWrt Image Builder ») et du SDK (« Build the OpenWrt SDK ») :

make menuconfig

Par défaut, tous les packages sont compilés (en module) puis exclus de l’image finale. Pour éviter cette perte de temps lors de la compilation, on va demander à ce que les packages qui ne seront pas intégrés à l’image ne soient pas compilés. Pour cela, on commente les lignes qui finissent par “=m” (module) avec la commande suivante :

sed -i 's,^.*=m,# & is not set,g' .config

On configure ccache pour écrire dans le tmpfs au lieu du home directory de l'utilisateur courant :

export CCACHE_DIR=/tmp/.ccache

On lance la compilation :

make -j 9

La compilation va se vautrer :

make[3] -C package/dnsmasq compile
make -r world: build failed. Please re-run make with V=s to see what's going on
make: *** [world] Erreur 1

Je n'ai pas creusé l'origine de cette erreur mais il suffit de relancer la compilation (avec la même commande que ci-dessus) et cette fois, ça se passe sans emcombres.

Ajouter/supprimer des packages

Je garde les mêmes logiciels qu'avant (à l'exception de ddns-scripts, comme expliqué ci-dessus) et je ne supprime plus ppp/ppp-mod-pppoe (ce cela me semble être sans effet mais je n'ai pas creusé la question). Donc ça nous donne :

  • etherwake dans Network.
  • tcpdump-mini dans Network.
  • djbdns-dnscache dans Network -> IP adresses and Names.
  • ntpd dans Network -> Time Synchronization.
  • iptables-mod-conntrack-extra dans Network -> Firewall -> Iptables.
  • luci-i18n-french dans LuCi -> Translations

Je me suis rendu compte que Busybox intègre un serveur NTP minimaliste qui ne fournit pas le support des queries (il ne répond pas aux requêtes d'administration) ni les tools additionnels qui vont bien (ntpq par exemple). Source : NTP client/ NTP server sur le Wiki OpenWRT. Comme je souhaite conserver l'implé ntpd "classique" de l'université du Delaware (pour la possibilité de monitoring / de jouer avec ntpq principalement et aussi car c'est une valeur sûre à mes yeux depuis le temps que je l'utilise), je désactive le support NTP de Busybox dans base system -> busybox -> Networking utilities

On lance la compilation avec la méthode habituelle :

sed -i 's,^.*=m,# & is not set,g' .config
make -j9

La compilation va planter sur OpenSSL (qui est activé et compilé par dépendance pour ntpd, même si vous n'avez pas coché le support ntpd-ssl, mais qui ne sera pas intégré à l'image finale semble-t-il) :

make[6]: Entering directory `/media/montmpfs/attitude_adjustment/build_dir/target-mipsel_uClibc-0.9.33.2/openssl-1.0.1e/crypto/sha'
ccache_cc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include  -fPIC -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DDSO_DLFCN -DHAVE_DLFCN_H -I/media/montmpfs/attitude_adjustment/staging_dir/target-mipsel_uClibc-0.9.33.2/usr/include -I/media/montmpfs/attitude_adjustment/staging_dir/target-mipsel_uClibc-0.9.33.2/include -I/media/montmpfs/attitude_adjustment/staging_dir/toolchain-mipsel_gcc-4.6-linaro_uClibc-0.9.33.2/usr/include -I/media/montmpfs/attitude_adjustment/staging_dir/toolchain-mipsel_gcc-4.6-linaro_uClibc-0.9.33.2/include -DOPENSSL_SMALL_FOOTPRINT -DHAVE_CRYPTODEV -DOPENSSL_NO_ERR -DTERMIO -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float -fpic -fomit-frame-pointer -Wall -DSHA1_ASM -DSHA256_ASM -DAES_ASM -c   -c -o sha256-mips.o sha256-mips.S
sha256-mips.S: Assembler messages:
sha256-mips.S:1960: Error: opcode not supported on this processor: mips1 (mips1) `bnel $5,$23,.Loop'
make[6]: *** [sha256-mips.o] Error 1

La solution est donné sur la ML OpenSSL-dev : sha256-mips.S:1960: Error: opcode not supported on this processor: mips1 (mips1) `bnel $5,$23,.Loop'. La correction se fait comme suit :

sed -i 's/bnel/bne/' ./build_dir/target-mipsel_uClibc-0.9.33.2/openssl-1.0.1e/crypto/sha/asm/sha512-mips.pl

Le reste du billet Créez votre image personnalisée d’OpenWRT : ce qui change avec Backfire 10.03.1 (modifier les options du noyau, modifier les options de busybox, configurer les logiciels, ...) est encore valable donc je ne le reprends pas ici.

On constate que l'image de base occupe 3,2M au lieu de 3M pour une image Backfire 10.03.1 et que mon image personnalisée occupe 3,5M contre 3,2M à l'époque Backfire. Cela signifie que l'on s'approche de plus en plus de la limite de stockage d'un WRT54GL, qui, si la taille de l'image continue à augmenter, ne pourra plus accueillir de logiciels supplémentaires (comme etherwake, dnscache, ...) ...

news

DDNS indépendant sur OpenWRT

Table des matières

But

D'un côté, j'ai mon WRT54GL sous OpenWRT derrière une ligne ADSL (chez un FAI classique) avec une IP dynamique. Pour maintenir une correspondance entre un nom et l'adresse IP changeante, j'utilise les services de dyn.com.

De l'autre, j'ai un nom de domaine dont je gère moi-même le serveur de nom primaire. J'utilise BIND comme logiciel serveur.

Il serait bien que je prenne moi-même en charge la correspondance entre le nom de mon OpenWRT et son adresse IP. Pour ceux qui se demandent encore l'intérêt de la manip' : indépendance et tout ce que ça implique.

Contraintes

On parle de mon WRT54GL donc :

  • La méthode traditionnelle est de faire du DDNS (Dynamic DNS) dont l'échange est sécurisé grâce à une paire de clés grâce à un client comme nsupdate. Néanmoins, je n'ai pas la place pour installer un client sur mon OpenWRT.
  • Je n'ai pas la place pour installer les libs nécessaires au fonctionnement d'HTTPS avec curl ou wget. Or, si je fais mon propre système, je veux que tout soit sécurisé (de la récupération de l'IP jusqu'à sa mise à jour sur le serveur de nom.
  • Mon modem donne une IP RFC 1918 à mon WRT54GL donc le seul moyen de récupérer mon IP externe est de faire appel à un service externe. Or, je ne veux pas.

Ce que l'on va faire

OpenWRT dispose d'un client SSH ... donc toute la partie sécurité sera gérée par SSH lui-même.

Pour la périodicité de la vérification, OpenWRT dispose, par défaut, du classique cron.

Pour obtenir l'adresse IP de l'OpenWRT, pas besoin d'aller la récupérer sur un site web : on l'a récupérera depuis la variable d'environnement "SSH_CLIENT".

Pour mettre à jour la zone, on utilisera nsupdate qui sera déporté sur le serveur. Pas besoin de sécuriser l'échange avec une paire de clé vu que l'échange se fera sur localhost.

Pour résumer : Sur l'OpenWRT, cron lancera, de manière répétée, le client ssh. Le client SSH présent sur l'OpenWRT ira se connecter au serveur de nom en utilisant sa clé privée. Il lancera un script présent sur le serveur de nom. Ce script prendra la nouvelle IP en paramètre, fera quelques vérifications et utilisera nsupdate pour mettre à jour la zone.

Mise en œuvre

Dans la suite, "serveur" désignera le serveur de nom, "OpenWRT" désignera mon WRT54GL sous OpenWRT et "openwrt.guiguishow.info" sera le nom de domaine attribué à mon OpenWRT.

Script

#!/bin/bash
 
if [ $# -ne 1 ]
then
        echo "Trop ou pas assez d'arguments"
        logger "DDNS openwrt - Trop ou pas assez d'arguments"
        exit 2
fi
 

echo $1 | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" > /dev/null
if [ $? -ne 0 ]
then
        echo "La paramètre \"IP\" n'est pas au bon format."
        logger "DDNS openwrt - Paramètre IP pas au bon format."
        exit 2
fi
 
# Un petit délire pas utile : vérifier rapidement l'AS à qui a
# été distribuée l'IP passée en paramètre. Si ce n'est pas l'AS
# de mon FAI, alors soit il y a une erreur, soit le script
# n'est pas lancé depuis l'OpenWRT ... de là à parler d'une
# usurpation ... 
as=`whois $1 | grep origin | grep -oE "AS[0-9]{1,5}"`
if [ $? -eq 0 ] && [ $as != "AS5410" ]
then
        logger "DDNS openwrt - Usurpation"
        echo "." | mail -s "DDNS openwrt - USURPATION" guigui chez guiguishow pointinfo
        exit 1
fi
 
# Si l'IP passée en paramètre est la même que celle 
# actuellement dans la zone, on ne fait rien.
ipActuelle=`dig +short @127.0.0.1 openwrt.guiguishow.info`
if [ $ipActuelle !=  $1 ]
then
        cat > ./majDNSopenwrt << EOF
server 127.0.0.1
zone guiguishow.info
update delete openwrt.guiguishow.info. A
update add openwrt.guiguishow.info. 60 A $1
show
send
EOF

        nsupdate -v ./majDNSopenwrt > /dev/null 2>&1
 
        if [ $? -eq 0 ]
        then
                logger "DDNS openwrt - MAJ OK"
                echo "." | mail -s "DDNS openwrt - MAJ OK" guigui chez guiguishow pointinfo
        else
                logger "DDNS openwrt - MAJ NEEDED BUT FAIL"
                echo "." | mail -s "DDNS openwrt - MAJ NEEDED BUT FAIL" guigui chez guiguishow pointinfo
        fi
fi

ÉDIT du 06/08/2014 à 16h20 : b4n propose une version mieux écrite de ce script :

#!/bin/bash
 
EMAIL="guigui chez guiguishow pointinfo"
 
if [ $# -ne 1 ]
then
  echo "Trop ou pas assez d'arguments" >&2
  logger "DDNS openwrt - Trop ou pas assez d'arguments"
  exit 2
fi
 
if ! grep -qxE '([0-9]{1,3}\.){3}[0-9]{1,3}' <<<"$1"
then
  echo "Le paramètre \"IP\" n'est pas au bon format." >&2
  logger "DDNS openwrt - Paramètre IP pas au bon format."
  exit 2
fi
 
# Un petit délire pas utile : vérifier rapidement l'AS à qui a
# été distribuée l'IP passée en paramètre. Si ce n'est pas l'AS
# de mon FAI, alors soit il y a une erreur, soit le script
# n'est pas lancé depuis l'OpenWRT ... de là à parler d'une
# usurpation ...
if [ "$(whois "$1" | grep origin | grep -oE 'AS[0-9]{1,5}')" != "AS5410" ]
then
  logger "DDNS openwrt - Usurpation"
  mail -s "DDNS openwrt - USURPATION" "$EMAIL" <<<"."
  exit 1
fi
 
# Si l'IP passée en paramètre est la même que celle
# actuellement dans la zone, on ne fait rien.
if [ "$(dig +short @127.0.0.1 openwrt.guiguishow.info)" != "$1" ]
then
  if nsupdate -v /dev/stdin >/dev/null 2>&1 <<EOF
server 127.0.0.1
zone guiguishow.info
update delete openwrt.guiguishow.info. A
update add openwrt.guiguishow.info. 60 A $1
show
send
EOF
  then
    logger "DDNS openwrt - MAJ OK"
    mail -s "DDNS openwrt - MAJ OK" "$EMAIL" <<<"."
  else
    logger "DDNS openwrt - MAJ NEEDED BUT FAIL"
    mail -s "DDNS openwrt - MAJ NEEDED BUT FAIL" "$EMAIL" <<<"."
  fi
fi

Fin de l'édit

Chez moi, ce script s'appelle "DDNSOpenWRT.sh".

Installer nsupdate sur le serveur

Sous Debian, nsupdate se trouve dans le package dnsutils :

apt-get install nsupdate

Réglage de BIND

Il faut autoriser le DDNS sur la zone depuis localhost. Cela se passe dans la déclaration de la zone, donc normalement dans le fichier /etc/bind/named.conf.local. Il faut ajouter la directive "allow-update { 127.0.0.1; };". Exemple :

zone "guiguishow.info." IN {
        type master;
        [...]
        allow-update { 127.0.0.1; };
};

Au niveau des droits, BIND doit avoir le droit d'écrire (w) sur le fichier qui défini la zone ainsi que sur le dossier contenant ce fichier car BIND écrit des journaux (fichiers avec une extension .jnl).

Utilisateur dédié et paire de clés

Sur le serveur, on va créer un utilisateur (openwrt) qui sera dédié uniquement à l'activité DDNS.

adduser openwrt

Mettre un mot de passe.

On met le script dans le home directory de cet utilisateur (/home/openwrt).

On génére une paire de clé pour l'utiliser avec SSH :

ssh-keygen -t rsa

La partie publique va sur le serveur, dans /home/openwrt/.ssh/authorized_keys, comme d'habitude.

La clé privée doit aller sur l'OpenWRT. Néanmoins, dropbear accepte les clés uniquement sous un certain format (sinon erreur "ssh: Exited: String too long"). On installe dropbear sur notre machine de travail et on converti la clé openwrt.rsa -> openwrt.dropb) :

sudo apt-get install dropbear
/usr/lib/dropbear/dropbearconvert openssh dropbear openwrt.rsa openwrt.dropb

On transfère la clé sur l'OpenWRT :

scp openwrt.dropb root@openwrt:.

Un peu de sécurité

L'utilisateur openwrt ne doit rien pouvoir faire sur le serveur à part lancer le script. On va donc restreindre les commandes possibles à une seule avec la directive de configuration ForceCommand de SSH. On ajoute donc ceci au fichier /etc/ssh/sshd_config :

Match User openwrt
ForceCommand ~/DDNSOpenWRT.sh `env | grep SSH_CLIENT | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}"`

Créer un cron sur OpenWRT

Par défaut, crond n'est pas lancé s'il n'y a aucun fichier dans /etc/crontabs/ (voir le script dans /etc/init/ pour vous en convaincre).

Il suffit de créer un fichier /etc/crontabs/root avec le contenu suivant :

*/5 * * * * /usr/bin/ssh -i /path/to/cle/privee openwrt@serveur_de_nom '~/DDNSOpenWRT.sh `env | grep SSH_CLIENT | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}"`'

Ainsi, toutes les 5 minutes, une vérification sera faite.

Au prochain reboot, crond démarrera tout seul mais cette fois-ci, c'est à vous de le lancer :

/etc/init.d/cron start

Pour terminer, il ne reste plus qu'à supprimer les ddns-scripts. Pour cela, je commence à killer les processus (ps aux + kill -9). Ensuite je supprime le package (opkg remove --autoremove). Pensez aussi à supprimer luci-app-ddns si jamais vous l'avez. Puis je supprime les paramètres conservés par uci (uci delete ddns.myddns) . Enfin : reboot.

Inspiration

L'idée d'utiliser nsupdate côté serveur, dans un script, me vient de : Mise à jour dynamique d’entrée DNS chez GuiguiABloc.

tour

ÉDIT du 04 janvier 2014 : Ce billet traite de Backfire 10.03.1. Quelques petites choses ont changées avec Attitude Adjustment 12.09 et je vous conseille en conséquence de lire, en parallèle, cet autre billet : Créez votre image personnalisée d’OpenWRT : ce qui change avec Attitude Adjustment 12.09.

Table des matières

Comme avant, nous allons utiliser Buildroot mais sachez qu'en dehors d'un usage précis, l'Image Builder distribué par le projet OpenWRT suffit amplement pour créer une image personnalisée.

Note : selon ce que vous voulez obtenir, vous n'êtes pas obligé de suivre toutes les étapes de ce guide. Par exemple, si vous voulez simplement supprimer rdate proprement, vous vous contenterez de créer l'image officielle puis de configurer les options de busybox et de compiler le tout.

Préparatifs

Nous allons d'abord préparer notre Debian Wheezy pour recevoir Buildroot :

sudo apt-get install asciidoc autoconf bison build-essential fastjar flex gawk gettext git-core intltool libextutils-autoinstall-perl libncurses5-dev libssl-dev libtool subversion zlib1g-dev

Puis nous récupérons, via subversion, les sources stables de Backfire 10.03.1 :

svn co svn://svn.openwrt.org/openwrt/tags/backfire_10.03.1

On s'assure que tout le nécessaire est bien présent :

cd backfire_10.03.1
backfire_10.03.1$ make defconfig && make prereq

Dans la suite de ce guide, sauf mention contraire, je considérerai que votre répertoire courant est backfire_10.03.1, c'est-à-dire la racine du buildroot.

Recréer l’image officielle

Notre premier objectif sera de parvenir à la compilation de l'image officielle. Traduction : l'image que vous allez compiler, c'est celle qui est disponible en téléchargement sur le site officiel d'OpenWRT (ex. : openwrt-wrt54g-squashfs.bin). Cela n'a pas d'autres intérêts que de se faire la main.

On met à jour la liste des packages disponibles :

backfire_10.03.1$ ./scripts/feeds update -a && ./scripts/feeds install -a

Ensuite, on efface les fichiers de configuration de la compilation (créés automatiquement par make menuconfig, nous y reviendrons) :

backfire_10.03.1$ rm .config && rm .config.old

On récupère le fichier de configuration officiel (ici : déclinaison brcm47xx) et on le met en place :

backfire_10.03.1$ wget http://downloads.openwrt.org/backfire/10.03.1/brcm47xx/config && mv config .config

Par défaut, tous les packages sont compilés (en module) puis exclus de l’image finale. Pour éviter cette perte de temps lors de la compilation, on va demander à ce que les packages qui ne seront pas intégrés à l’image ne soient pas compilés. Pour cela, on commente les lignes qui finissent par “=m” (module) avec la commande suivante :

backfire_10.03.1$ sed -i 's,^.*=m,# & is not set,g' ./.config

On lance la compilation :

make V=99

La compilation va échouer avec une trace ressemblant à celle-ci :

make -C /home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs
make[4]: Entering directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs'
make all-recursive
make[5]: Entering directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs'
Making all in src
make[6]: Entering directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs/src'
Making all in mklibs-readelf
make[7]: Entering directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs/src/mklibs-readelf'
i686-pc-linux-gnu-g++ -DHAVE_CONFIG_H -I. -I../.. -O2 -I/home/zachary/openwrt/openwrt-dreambox/staging_dir/host/include -I/home/zachary/openwrt/openwrt-dreambox/tools/mklibs/include -g -O2 -MT elf.o -MD -MP -MF .deps/elf.Tpo -c -o elf.o elf.cpp
elf.cpp: In static member function 'static Elf::file* Elf::file::open(const char*)':
elf.cpp:68:5: error: '::close' has not been declared
make[7]: * [elf.o] Error 1
make[7]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs/src/mklibs-readelf'
make[6]: * [all-recursive] Error 1
make[6]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs/src'
make[5]: * [all-recursive] Error 1
make[5]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs'
make[4]: * [all] Error 2
make[4]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs'
make[3]: * home/zachary/openwrt/openwrt-dreambox/build_dir/host/mklibs/.built Error 2
make[3]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox/tools/mklibs'
make[2]: * [tools/mklibs/compile] Error 2
make[2]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox'
make[1]: * home/zachary/openwrt/openwrt-dreambox/staging_dir/target-arm_v4t_uClibc-0.9.30.1_eabi/stamp/.tools_install_nnynn Error 2
make[1]: Leaving directory `/home/zachary/openwrt/openwrt-dreambox'
make: * [world] Error 2

Comme l'indique ce bugreport, la solution est d'ajouter la ligne suivante :

#include <unistd.h>

au fichier backfire_10.03.1/build_dir/host/mklibs/src/mklibs-readelf/elf.cpp puis de relancer la compilation (make) sans faire de make clean au préalable.

Si la compilation réussie (et il n’y a pas de raisons pour qu’elle ne réussisse pas), vous trouverez les images, au format squashfs, dans le dossier ./bin/brcm47xx .

Félicitation, vous venez de créer votre propre image pour votre routeur ! Elle doit avoir une taille équivalente à celle que l’on peut télécharger sur le site officiel. Vous pouvez essayer votre image sur votre routeur mais ce n’est vraiment pas la peine voire une mauvaise idée : la mémoire étant de la flash, elle est plus limitée qu’un disque dur en terme de nombre de cycles d’écriture possibles malgré les algorithmes de lissage de l’usure. Essayer une image qui n’a aucun intérêt use le matériel plus qu’autre chose.

Nous allons maintenant créer une image personnalisée.

Créer une image vraiment personnelle

Modifier les options du noyau Linux

Pour modifier les options du kernel, rien n'a changé, il faut utiliser la commande :

make kernel_menuconfig

Une interface semi-graphique s'affichera au bout de quelques instants. Les options actuelles me convenant, je n'ai rien modifié. Mais il est toujours intéressant et instructif de regarder ce qui est déjà fait.

C'est également dans ce menu que vous pouvez, par exemple, activer le support du contrôle par groupe des processus, activez le support de systèmes de fichiers supplémentaires ou bien encore saisir un nom personnalisé pour votre noyau (la classe 8) pour frimer devant les copains).

Si vous faites des modifications, mettez "Exit" (bouton droit de la souris pour y accéder) et répondez "Yes" à la question de la sauvegarde de vos paramètres.

Ajouter/Supprimer des packages

La commande à utiliser :

backfire_10.03$ make menuconfig

Si vous n'avez pas un usage spécifique, vous pouvez désactiver la génération du SDK et de l'Image Builder. Vous gagnerez ainsi du temps à la compilation.

Pour notre part, nous activerons les packages suivants :

  • etherwake dans Network.
  • tcpdump-mini dans Network.
  • djbdns.-dnscache dans Network -> IP adresses and Names.
  • ddns-scripts dans Network -> IP adresses and Names.
  • ntpd dans Network -> Time Synchronization.
  • iptables-mod-conntrack-extra dans Network -> Firewall -> Iptables.
  • luci-i18n-french dans LuCi -> Translations

C’est également le moment de décocher les logiciels que vous ne voulez pas afin qu’ils ne soient pas intégrés à l’image. Pour notre part, nous supprimerons les packages suivants :

  • ppp dans Network.
  • ppp-mod-pppoe dans Network.
  • kmod-ppp dans Kernel Modules -> Network support.
  • kmod-pppoe dans Kernel Modules -> Network support.

Pour sauvegarder vos paramètres, mettez "Exit" (bouton droit de la souris pour y accéder) et répondez "Yes" à la question de la sauvegarde de vos paramètres.

À moins que vous ne teniez à désactiver tous les autres composants qui vont être compilés en modules mais pas intégrés à l'image à la main, utilisez la commande que nous avons déjà vu :

backfire_10.03$ sed -i 's,^.*=m,# & is not set,g' ./.config

Ces deux étapes (sauvegarde des paramètres et désactivations des modules) sont à faire avant chaque compilation si vous avez modifié quelque chose dans l’interface semi-graphique.

Vous pouvez compilez avec make. N'oubliez pas de faire un make clean avant ! Je ne vous le rappellerai plus à partir de maintenant, il faudra donc y penser !

Ajouter votre package personnel / vos modifications aux sources

Ici, rien ne change sur la méthodologie à employer.

Si vous avez créé/porté un logiciel pour OpenWRT, c'est le moment de le mettre en place dans l'arborescence avec son makefile et tout et tout. Je vous regarde faire ;) .

Ensuite, vous n'avez plus qu'à le sélectionner dans l’interface semi-graphique de configuration.

C'est également le moment de faire les modifications que vous voulez dans les sources. Par exemple, dans un billet, je vous avais montré comment optimiser la sécurité de dropbear et l'espace qu'il occupe dans la flash. C'est le moment d'appliquer ces modifications si vous le désirez. Je vous laisse aller les chercher dans l'article d'origine : OpenWRT : sécuriser l’accès SSH - Compiler dropbear pour n’autoriser que 3 essais de mot de passe par connexion.

Néanmoins, si comme moi, vous optimisez dropbear, sachez qu'il n'est plus possible de désactiver TWOFISH128 sinon, une erreur de compilation se produit :

make[4]: Leaving directory `/tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3'
touch /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/.built
rm -rf /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox
mkdir -p /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL
echo "Package: busybox" > /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL/control
echo "Version: 1.15.3-3.4" >> /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL/control
( DEPENDS=''; for depend in ; do DEPENDS=${DEPENDS:+$DEPENDS, }${depend##+}; done; echo "Depends: $DEPENDS"; echo "Provides: "; echo "Source: package/busybox"; echo "Section: base"; echo "Status: unknown ok not-installed"; echo "Essential: yes"; echo "Priority: optional"; echo "Maintainer: OpenWrt Developers Team <openwrt-devel@openwrt.org>"; echo "Architecture: brcm47xx"; echo "Installed-Size: 0"; echo -n "Description: "; getvar V_Package_busybox_description | sed -e 's,^[[:space:]]*, ,g'; ) >> /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL/control
chmod 644 /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL/control
(cd /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/CONTROL;  )
install -d -m0755 /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/etc/init.d
cp -fpR /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-install/* /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/
for tmp in  cron telnet; do install -m0755 ./files/$tmp /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/etc/init.d/$tmp; done
rm -rf /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/lib64
mkdir -p /tmp/backfire_10.03.1/bin/brcm47xx/packages
find /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox -name 'CVS' -o -name '.svn' -o -name '.#*' | xargs -r rm -rf
NM="mipsel-openwrt-linux-uclibc-nm" STRIP="/tmp/backfire_10.03.1/staging_dir/host/bin/sstrip" STRIP_KMOD="mipsel-openwrt-linux-uclibc-strip --strip-unneeded --remove-section=.comment --remove-section=.pdr --remove-section=.mdebug.abi32" /tmp/backfire_10.03.1/scripts/rstrip.sh /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox
rstrip.sh: /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox/bin/busybox:executable
ipkg-build -c -o 0 -g 0 /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox /tmp/backfire_10.03.1/bin/brcm47xx/packages
Packaged contents of /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-brcm47xx/busybox into /tmp/backfire_10.03.1/bin/brcm47xx/packages/busybox_1.15.3-3.4_brcm47xx.ipk
rm -rf /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox
mkdir -p /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/stamp /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox
install -d -m0755 /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox/etc/init.d
cp -fpR /tmp/backfire_10.03.1/build_dir/target-mipsel_uClibc-0.9.30.1/busybox-1.15.3/ipkg-install/* /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox/
for tmp in  cron telnet; do install -m0755 ./files/$tmp /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox/etc/init.d/$tmp; done
rm -rf /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox/lib64
cp -fpR /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox/. /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/
rm -rf /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/tmp-busybox
touch /tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm47xx/stamp/.busybox_installed
make[3]: Leaving directory `/tmp/backfire_10.03.1/package/busybox'
make[2]: Leaving directory `/tmp/backfire_10.03.1'
make[1]: *** [/tmp/backfire_10.03.1/staging_dir/target-mipsel_uClibc-0.9.30.1/stamp/.package_compile] Error 2
make[1]: Leaving directory `/tmp/backfire_10.03.1'
make: *** [world] Erreur 2

Je ne désactive donc plus TWOFISH et je supprime donc les deux lignes suivantes que je mettais dans le Makefile de dropbear :

$(SED) 's,^#define DROPBEAR_TWOFISH256,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_TWOFISH128,/* & */,g' $(PKG_BUILD_DIR)/options.h

Modifiez les options de busybox

backfire_10.03$ make menuconfig

Pour cela, il suffit d'aller dans Base system -> Busybox -> Configuration. Enjoy !

Rien ne change. Sauf que rdate n'est plus activé donc nous n'avons aucune raison de le désactiver :) .

Modifier des options générales

En dehors de Busybox, il reste encore plein d'options à explorer.

Il n'y a plus d'option pour choisir la langue par défaut de LuCi. Seule l'anglais est disponbile par défaut. Si plusieurs langue sont activées, la langue est choisie à la volée en fonction, je pense, des entêtes envoyées par le navigateur.

luci-admin-mini n'existe plus (seule la version complète luci-admin-full est disponible) et luci-admin-core n'est pas son équivalent (ce package n'a même rien à voir).

En revanche, vous pouvez toujours désactiver luci-i18n-english en éditant le fichier .config avec votre éditeur favori.

Cherchez la ligne suivante :

CONFIG_PACKAGE_luci-i18n-english=y

et commentez-là :

# CONFIG_PACKAGE_luci-i18n-english=y is not set

Enregistrer vos modifications et quittez vi.

Libre à vous d'explorer les autres options.

Note : Oui, j'ai lu la première ligne du fichier .config qui dit de ne pas le modifier à la main. Mais, n'ayant pas trouvé les packages qui dépendent de luci-admin-mini et de luci-i18n-english, je n'ai pas vraiment le choix. De plus, ce conseil est donné dans le cas où vous activez un logiciel sans activer ses dépendances (ex. : activer djbdns-dnscache sans activer djbdns-base). Autrement dit : si vous connaissez les dépendances d'un package que vous voulez installer, vous pouvez modifier le .config à la main sans problèmes.

Configurer les logiciels

Logiciels configurables avec uci

Il suffit de créer des scripts. Ces scripts seront placés dans un dossier files/etc/uci-defaults à la racine du buildroot. Tous les scripts se trouvant dans ce dossier seront exécutés une seule fois après le flashage du routeur quelque soit leur nom. Voici, à titre d'exemple, les scripts destinés à configurer les logiciels que nous avons installés ci-dessus :

backfire_10.03/files/etc/uci-defaults/ddns (pour ddns-scripts et DynDNS) :

#!/bin/sh
 
# DDNS parametres
uci set ddns.myddns.enabled=1 2>/dev/null
uci set ddns.myddns.interface=wan 2>/dev/null
uci set ddns.myddns.service_name=dyndns.org 2>/dev/null
uci set ddns.myddns.domain=<votre ndd> 2>/dev/null
uci set ddns.myddns.username=<votre login sur dynDNS> 2>/dev/null

 
uci set ddns.myddns.force_interval=24 2>/dev/null
uci set ddns.myddns.force_unit=hours 2>/dev/null
uci set ddns.myddns.check_interval=10 2>/dev/null
uci set ddns.myddns.check_unit=minutes 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null

Vous pouvez également marquer en dur votre mot de passe (uci set ddns.myddns.password=XXXX 2>/dev/null), mais je ne vous le conseille pas. Même si votre compte DynDNS n'est pas le compte le plus précieux que vous ayez, ce n'est pas une bonne pratique.

Dans la même veine, la bonne pratique voudrait que vous mettiez votre IP à jour sur DynDNS en utilisant le protocole HTTPS. C'est possible, voir le wiki d'OpenWRT à ce sujet mais les libs prennent beaucoup de place et je n'ai pas assez d'espace pour les accueillir.

Si vous êtes derrière une box ou qu'autre chose fait que l'interface wan (eth0.1) n'a pas une ip publique, il vous faudra utiliser un service externe pour récupérer votre ip publique et remplacer ces deux lignes :

uci set ddns.myddns.ip_source=network 2>/dev/null
uci set ddns.myddns.ip_network=wan 2>/dev/null

par

uci set ddns.myddns.ip_source=web 2>/dev/null
uci set ddns.myddns.ip_url=http://automation.whatismyip.com/n09230945.asp 2>/dev/null

backfire_10.03/files/etc/uci-defaults/dnscache (pour djbdns-dnscache) :

#!/bin/sh
 
# On configure dnscache
uci set djbdns.@dnscache[0].interface=lan 2>/dev/null
uci set djbdns.@dnscache[0].defaultallowif=lan 2>/dev/null
uci set djbdns.@dnscache[0].forwardonly=0 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null
 
# On met les bonnes autorisations sur le script d'init de dnscache
chmod ugo+x /etc/init.d/dnscache 2>/dev/null

 
# dnscache est déjà pris en compte par hotplugd, il n'a pas besoin d'init pour 
# se lancer
rm -f /etc/rc.d/S65dnscache 2>/dev/null

ATTENTION : dnscache est pris en charge par hotplugd uniquement si votre interface wan est configurée avec DHCP. Dans le cas d'une IP statique sur l'interface wan et d'après mes tests, hotplugd n'agit pas et init est nécessaire. Si vous êtes dans ce cas, ne supprimez pas le script d'init.

backfire_10.03/files/etc/uci-defaults/dnsmasq (pour dnsmasq) :

#!/bin/sh
 
# On désactive la fonctionnalité forward DNS de dnsmasq
uci set dhcp.@dnsmasq[0].port=0 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null
 
# On met les bonnes autorisations sur le script d'init de dnsmasq
chmod ugo+x /etc/init.d/dnsmasq 2>/dev/null

backfire_10.03/files/etc/uci-defaults/dropbear (pour dropbear) :

#!/bin/sh
 
# On désactive l'authentification par mot de passe
uci set dropbear.@dropbear[0].PasswordAuth=off 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null

backfire_10.03/files/etc/uci-defaults/firewall (pour configurer, un peu, netfilter) :
L'idée, c'est de définir, intégralement, nos propres règles, de A à z. Or, des règles sont chargées à chaque reboot du routeur à partir du fichier /etc/config/firewall. Plusieurs méthodes s'offrent, comme d'habitude, à vous : soit vous éditez /etc/config/firewall qui est un format classique d'uCi pour y intégrer vos règles. Soit vous supprimez ce fichier de l'image et vous définisez, dans un script d'init, les règles de filtrage qu'il convient d'appliquer. Ayant déjà un script standard qui charge mes règles de filtrage qui est pas trop mauvais, j'ai choisi cette deuxième solution. backfire_10.03/files/etc/uci-defaults/firewall contient donc :

#!/bin/sh

 
# On supprime les regles par defaut stockees dans uci
rm -rf /etc/config/firewall 2>/dev/null

 
# On met les bonnes autorisations sur le script d'init du firewall
chmod ugo+x /etc/init.d/firewall 2>/dev/null

backfire_10.03/files/etc/uci-defaults/ntpd (pour configurer, un peu, ntpd) :

#!/bin/sh
 
# ntpd est deja lance par hotplug.d, nous n'avons pas besoin qu'il soit lance par init
rm -f /etc/rc.d/S65ntpd 2>/dev/null

ATTENTION : ntpd est pris en charge par hotplugd uniquement si votre interface wan est configurée avec DHCP. Dans le cas d'une IP statique sur l'interface wan et d'après mes tests, hotplugd n'agit pas et init est nécessaire. Si vous êtes dans ce cas, ne supprimez pas le script d'init de ntpd.

backfire_10.03/files/etc/uci-defaults/system (pour configurer les options générales du système) :

#!/bin/sh
 
# Nom du routeur
uci set system.@system[0].hostname="Nouveau_Nom" 2>/dev/null

echo "Nouveau_Nom" > /proc/sys/kernel/hostname 2>/dev/null

 
# Fuseau horaire
uci set system.@system[0].zonename=Europe/Paris 2>/dev/null
uci set system.@system[0].timezone=CET-1CEST,M3.5.0,M10.5.0/3 2>/dev/null

 
# On finit de supprimer rdate (plus utile)
# uci del system.@rdate[0] 2>/dev/null
# rm -f /etc/hotplug.d/iface/40-rdate 2>/dev/null
 
# On valide tout
uci commit 2>/dev/null

backfire_10.03/files/etc/uci-defaults/network (pour configurer les interfaces réseau) :

#!/bin/sh
 
# Configuration interface LAN
uci set network.lan.proto=static
uci set network.lan.netmask=255.255.255.0
uci set network.lan.ipaddr=192.168.0.254
uci set network.lan.dns=192.168.0.254 #dnscache

 
# Configuration interface WAN
uci set network.wan.proto=static
uci set network.wan.ipaddr=192.168.1.253
uci set network.wan.netmask=255.255.255.0
uci set network.wan.gateway=192.168.1.254
uci set network.wan.dns=192.168.0.254 #dnscache

 
# On valide tout
uci commit 2>/dev/null

Je pense que les interfaces peuvent également être configurées depuis le .config puisqu'on peut y lire les lignes suivantes :

CONFIG_UCI_PRECONFIG_network_lan_dns=""

CONFIG_UCI_PRECONFIG_network_lan_proto="static"
CONFIG_UCI_PRECONFIG_network_lan_gateway=""
CONFIG_UCI_PRECONFIG_network_lan_netmask="255.255.255.0"
CONFIG_UCI_PRECONFIG_network_lan_ipaddr="192.168.1.1"

Mon test a échoué mais je pense que cela est dû à un autre paramètre que j'ai activé en même temps.

On peut même configurer l'adresse que prend le bootloader :

CONFIG_TARGET_PREINIT_IFNAME=""
CONFIG_TARGET_PREINIT_IP="192.168.1.1"
CONFIG_TARGET_PREINIT_NETMASK="255.255.255.0"
CONFIG_TARGET_PREINIT_BROADCAST="192.168.1.255"

Vu le nombre de fois où ce bootloader et son serveur TFTP m'ont sauvés la mise, je n'ai pas essayé de changer ces paramètres.

Vous avez compris le principe et vous pouvez créer vos propres scripts pour les logiciels que vous avez installés ou modifier les scripts ci-dessous afin de configurer plus finement certains logiciels (dnsmasq par exemple).

Logiciels ne pouvant pas être configurés avec uci

Il y a des logiciels qui possèdent leurs propres fichiers de configuration. Pour eux, il suffit de placer les fichiers dans l'arborescence, comme si vous étiez sur votre routeur. Par exemple, si à la fin du flashage, vous avez besoin qu'un fichier /etc/xxxx soit créez, alors placez-le dans backfire_10.03/files/etc/xxxx et il sera mis au bon endroit. Si le fichier existe déjà car il est fourni par un logiciel, par exemple, il sera écrasé par votre version.

Il y a une autre manière de procéder : mettre le fichier dans le package qui lui correspond. Exemple : vous avez un fichier de configuration pour ntpd (/etc/ntp.conf), alors vous le mettez dans feeds/packages/net/ntpd/files/etc/ntp.conf. Pour les packages par défaut (dropbear par exemple), le chemin est différent : packages/dropbear ...

Personnellement, j'ai choisi de tout mettre dans un même dossier car cela simplifie la maintenance.

Voici donc les fichiers que j'ai rajoutés.

backfire_10.03/files/etc/banner (le message de bienvenue lors d'une connexion SSH) :

Salut !

backfire_10.03/files/etc/ntp.conf (configuration de ntpd) :

server ntp-p1.obspm.fr iburst prefer
server canon.inria.fr iburst
 
restrict default ignore
restrict ntp-p1.obspm.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict canon.inria.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer
restrict 127.0.0.1
 
driftfile  /etc/ntp.drift

backfire_10.03/files/etc/services (nécessaire au bon fonctionnement de ntpd) :
Sans lui, vous aurez des messages d'erreur du genre "getaddrinfo: "ntp-p1.obspm.fr" invalid host address, ignored", "restrict: error in address 'ntp-p1.obspm.fr' on line 6. Ignoring...", "Deferring DNS for ntp-p1.obspm.fr 1" et "getaddrinfo(127.0.0.1) failed: Servname not supported for ai_socktype".

ntp             123/udp     # Network Time Protocol
ntp             123/tcp     # Network Time Protocol

backfire_10.03/files/etc/passwd (permet de rajouter des comptes utilisateur sans droits d'administration (ici : guest)) :

root:*:0:0:root:/root:/bin/ash
guest:*:65533:65533:guest:/home/guest:/bin/ash
nobody:*:65534:65534:nobody:/var:/bin/false
daemon:*:65534:65534:daemon:/var:/bin/false

backfire_10.03/files/etc/group (permet de rajouter des groupes utilisateurs destinés à accueillir les comptes standards) :

root:x:0:
guestg:x:65533:
nogroup:x:65534:

Authentification par clé publique/privée :

Mettez la clé publique de root dans backfire_10.03/files/etc/dropbear/authorized_keys si vous voulez utiliser l'authentification à clé publique pour vous connecter avec le compte root via SSH.

Pour chaque compte utilisateur créé, mettez sa clé publique dans un fichier ".ssh/authorized_keys" placé dans son home directory. Par exemple, pour le compte guest créé ci-dessous, la clé publique devra se trouver dans backfire_10.03/files/home/guest/.ssh/authorized_keys .

Si vous voulez utiliser l'authentification par clé publique pour vos comptes sans droits, ne changez surtout pas le propriétaire de leurs home directory (pas de chown -R guest:guestp /home/guest dans un script dans l'image). En effet, pour une raison qui m'échappe, l'authentification échoue sinon. Mais, dans ce cas-là, l'utilisateur n'est pas vraiment chez lui : il ne peut pas créer un répertoire par exemple. Heureusement, vous pouvez changer le proprietaire du home directory de chacun de vos comptes utilisateurs après le flashage et aucun problème n'apparait.

backfire_10.03/files/etc/hotplug.d/iface/15-dnsd (script permettant de relancer dnscache en cas de coupure de l'accès au net) :

#!/bin/sh
 
if [ "$INTERFACE" = "wan" ] 

then
	DNS_RUNNING=`ps  | grep dnscache | grep -v grep`

 
	case "${ACTION:-ifup}" in
        	ifup)
                	[ -z "$DNS_RUNNING" ] && /etc/init.d/dnscache start
       		;;

 
		ifdown)
               		[ -n "$DNS_RUNNING" ] && /etc/init.d/dnscache stop
        	;;

	esac
fi

ATTENTION : Il semble que ce script est inutile si vous êtes en IP statique sur l'interface WAN.

backfire_10.03/files/etc/init.d/dnscache (script d'init pour dnscache modifié pour logger les démarrages/arrêts du démon) :
ATTENTION : Le script n'est pas donné ici dans son intégralité. Attention donc aux copier/coller malheureux.

#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
 
[...]
 
start() {
    echo "Starting $DESC: $NAME"

    logger starting dnscache
    config_load djbdns
    config_foreach get_userids global
    mkdir -p $ROOT
    cp -fa /etc/dnscache/* $ROOT

    rm -f $ROOT/resolvers
    rm -f $ROOT/ignoreip
    chown -R $UID:$GID $ROOT

    config_foreach start_dnscache dnscache
}
 
[...]
 
stop() {
    echo -n "Stopping $DESC: $NAME"

    logger stopping dnscache
    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1

    echo " ."
}
 
restart() {
    echo "Restarting $DESC: $NAME... "

    stop
    sleep 2
    start
}

backfire_10.03/files/etc/init.d/dnsmasq (script d'init pour dnsmasq modifié afin d'indiquer uniquement notre résolveur DNS local) :
ATTENTION : Le script n'est pas donné ici dans son intégralité. Attention donc aux copier/coller malheureux.

#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
 
START=60
DNS_SERVERS=""
DOMAIN=""
 
[...]
 
start() {
        include /lib/network
        scan_interfaces
        config_load dhcp
 
        args=""
        config_foreach dnsmasq dnsmasq
        config_foreach dhcp_host_add host
        config_foreach dhcp_boot_add boot
        config_foreach dhcp_mac_add mac
        config_foreach dhcp_vendorclass_add vendorclass
        config_foreach dhcp_userclass_add userclass
        config_foreach dhcp_circuitid_add circuitid
        config_foreach dhcp_remoteid_add remoteid
        config_foreach dhcp_subscrid_add subscrid
        config_foreach dhcp_domain_add domain
        config_foreach dhcp_add dhcp
 

        /usr/sbin/dnsmasq $args && {
                rm -f /tmp/resolv.conf
                [ -n "$DOMAIN" ] && echo "search $DOMAIN" >> /tmp/resolv.conf
                DNS_SERVERS="192.168.1.1" #A REMPLACER SI VOTRE ROUTEUR A UNE IP LAN DIFFERENTE !
                for DNS_SERVER in $DNS_SERVERS ; do
                        echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
                done
        }
}

 
stop() {
        [ -f /tmp/resolv.conf ] && {
                rm -f /tmp/resolv.conf
                ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
        }
        killall dnsmasq
        return 0
}

backfire_10.03/files/etc/init.d/firewall (pour configurer, un peu plus, netfilter) :
À adapter à vos besoins et à complèter car il manque encore des choses (séparation tcp, udp, icmp et filtrage différencié, éviter d'autoriser des connexions sur le simple fait qu'elles sont établies mais préciser le port source, ...)

#!/bin/sh /etc/rc.common
 
START=45

 
start() {
	#On fait le menage
	stop
 
	############### TABLE FILTER
	##On créer les chaînes correspondant à nos zones
	iptables -t filter -N lan-lan
	iptables -t filter -N lan-bas
	iptables -t filter -N lan-wan

 
	iptables -t filter -N bas-lan
	iptables -t filter -N bas-bas
	iptables -t filter -N bas-wan

 
	iptables -t filter -N wan-lan
	iptables -t filter -N wan-bas
	iptables -t filter -N wan-wan

 
	##On redirige les paquets vers nos chaines
	iptables -t filter -A INPUT -i br-lan -j lan-bas
	iptables -t filter -A INPUT -i lo -j bas-bas
	iptables -t filter -A INPUT -i eth0.1 -j wan-bas

 
	iptables -t filter -A FORWARD -i br-lan -o br-lan -j lan-lan
	iptables -t filter -A FORWARD -i br-lan -o eth0.1 -j lan-wan 
	iptables -t filter -A FORWARD -i eth0.1 -o eth0.1 -j wan-wan
	iptables -t filter -A FORWARD -i eth0.1 -o br-lan -j wan-lan

 
	iptables -t filter -A OUTPUT -o br-lan -j bas-lan
	iptables -t filter -A OUTPUT -o lo -j bas-bas
	iptables -t filter -A OUTPUT -o eth0.1 -j bas-wan

 
	##On traite nos chaines
	#Du lan vers le routeur d'abord
	#Etablies/relatives
	iptables -t filter -A lan-bas -m state --state RELATED,ESTABLISHED -j ACCEPT
	#SSH

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT 
	#DNS

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT 
	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 53 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#DHCP

	iptables -t filter -A lan-bas -p udp -m state --state NEW -m udp --sport 68 --dport 67 -j ACCEPT
	#HTTP

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#NTP

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p udp -m state --state NEW -m udp --dport 123 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/3 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

 
 
	#Du lan vers internet ensuite
	#Etablies/relatives
	iptables -t filter -A lan-wan -m state --state RELATED,ESTABLISHED -j ACCEPT
	#FTP

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 20 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 21 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SSH

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#HTTP/HTTPS

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SMTPS/SMTP auth

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 465 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 587 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#POP3S

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 995 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SVN

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 3690 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p udp -m state --state NEW -m udp --dport 3690 -j ACCEPT
	#IRC

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 6667 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 6697 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Plesk

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 8443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Git

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 9418 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p udp -m state --state NEW -m udp --dport 9418 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT
	#Traceroute GNU\Linux, *BSD (?)

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p udp -m udp --dport 33434:33474  -m state --state NEW -j ACCEPT

 
 
	#Du routeur vers le lan
	#Etablies/relatives
	iptables -t filter -A bas-lan -m state --state RELATED,ESTABLISHED -j ACCEPT 
	#DHCP

	iptables -t filter -A bas-lan -p udp -m state --state NEW -m udp --sport 67 --dport 68 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A bas-lan -s 192.168.0.254/32 -d 192.168.0.0/24 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

 
 
	#Boucle locale
	iptables -t filter -A bas-bas -j ACCEPT
 

 
	#Du routeur vers internet
	#Etablies/relatives
	iptables -t filter -A bas-wan -m state --state RELATED,ESTABLISHED -j ACCEPT
	#FTP

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 20 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 21 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#DNS

	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT 
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 53 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#HTTP/HTTPS pour opkg

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#NTP

	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 123 -j ACCEPT
	#SMTPS/SMTP auth

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 465 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 587 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#POP3S

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 995 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SVN

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 3690 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 3690 -j ACCEPT
	#IRC

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 6667 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 6697 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Git

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 9418 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 9418 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A bas-wan -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT
	#Traceroute GNU\Linux, *BSD (?)

	iptables -t filter -A bas-wan -s 192.168.1.253/32 -p udp -m udp --dport 33434:33474  -m state --state NEW -j ACCEPT

 
	#D'internet vers le lan
	#Etablies/relatives
	iptables -t filter -A wan-lan -m state --state RELATED,ESTABLISHED -j ACCEPT

 
 
	#D'internet vers le routeur enfin
	#Etablies/relatives
	iptables -t filter -A wan-bas -m state --state RELATED,ESTABLISHED -j ACCEPT
	#SSH

	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --update --seconds 600 --hitcount 2 -j DROP
	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --set

	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -j ACCEPT

 
 
	##On change les politiques d'accés
	iptables -t filter -P INPUT DROP
	iptables -t filter -P FORWARD DROP
	iptables -t filter -P OUTPUT DROP

 
 
	##############TABLE NAT
	# On vide la regle par défaut de stop() 
	iptables -t nat -D POSTROUTING 1

 
	##On créer des chaines qui correspondent à nos zones
	iptables -t nat -N prerouting-lan
	iptables -t nat -N prerouting-wan

 
	iptables -t nat -N postrouting-lan
	iptables -t nat -N postrouting-wan
 
	##On redirige les paquets dans nos chaines

	#C'est ici que l'on peut rediriger des ports (ex. : proxy transparent, on redirige port 80/443 -> 8080)
	iptables -t nat -A PREROUTING -i br-lan -j prerouting-lan

 
	#C'est ici que l'on fait le DNAT (ex. : monter un serveur web sur le LAN, accessible sur internet)
	iptables -t nat -A PREROUTING -i eth0.1 -j prerouting-wan

 
	iptables -t nat -A POSTROUTING -o br-lan -j postrouting-lan
 
	#C'est ici que l'on fait le SNAT ou MASQUERADE si ip dynamique

	iptables -t nat -A POSTROUTING -o eth0.1 -j postrouting-wan
 
	##On traite nos chaines

	##SNAT/masquerade
	iptables -t nat -A postrouting-wan -s 192.168.0.0/24 -j SNAT --to-source 192.168.1.253

 
	##DNAT
	# Torrent
	#iptables -t nat -A prerouting-wan -p tcp -m tcp --dport 4444 -j DNAT --to-destination 192.168.1.138:4444
	#iptables -t nat -A prerouting-wan -p udp -m udp --dport 4444 -j DNAT --to-destination 192.168.1.138:4444
 
	##############TABLE MANGLE

	##Cette table sert pour la modification des paquets (ex:. marquer les paquets pour faire de la QoS ensuite)
	##Nous verrons cela plus tard
 
 
	##############TABLE RAW
	##Cette table sert à indiquer les connections qui ne doivent pas être suivies par conntrack
 
	echo "Firewall started"

	logger Firewall started
}
 
stop() {
	############### TABLE FILTER
	##On change les politiques d'accés
	iptables -t filter -P INPUT ACCEPT
	iptables -t filter -P FORWARD ACCEPT
	iptables -t filter -P OUTPUT ACCEPT

 
	##On fait le menage
	iptables -t filter -F
	iptables -t filter -X

 
 
	##############TABLE NAT
	##On change les politiques d'accés
	iptables -t nat -P PREROUTING ACCEPT
	iptables -t nat -P OUTPUT ACCEPT
	iptables -t nat -P POSTROUTING ACCEPT

 
	##On fait le menage
	iptables -t nat -F
	iptables -t nat -X

 
	#NAT
	iptables -t nat -A POSTROUTING -o eth0.1 -s 192.168.0.0/24 -j SNAT --to-source 192.168.1.253

 
 
	##############TABLE MANGLE
	##On change les politiques d'accés
	iptables -t mangle -P PREROUTING ACCEPT
	iptables -t mangle -P INPUT ACCEPT
	iptables -t mangle -P FORWARD ACCEPT
	iptables -t mangle -P OUTPUT ACCEPT
	iptables -t mangle -P POSTROUTING ACCEPT

 
	##On fait le menage
	iptables -t mangle -F
	iptables -t mangle -X

 
 
	##############TABLE RAW
	##On change les politiques d'accés
	iptables -t raw -P PREROUTING ACCEPT
	iptables -t raw -P OUTPUT ACCEPT

 
	##On fait le menage
	iptables -t raw -F
	iptables -t raw -X

 
	echo "Rules cleaned and firewall stopped"
	logger Rules cleaned and firewall stopped
}
 
restart() {
	start
 
	echo "Firewall restarted"

	logger Firewall restarted
}
 
reload() {
	start
 
	echo "Firewall reloaded"
	logger Firewall reloaded

}

À vous de continuer la configuration de votre système (ex. : VLAN). La méthode exposée ci-dessus fonctionne pour tous les fichiers.

Vous pouvez compiler puis essayer l'image ainsi générée. Tous vos logiciels doivent être configurés.

Si jamais vous avez une erreur durant la compilation

La liste ci-dessous est loin d'être exhaustive.

  • N'avez-vous pas oublié de faire un make clean avant de compiler ? Faites-le et relancez la compilation en faisant un make clean au préalable.
  • N'avez-vous pas oublié de faire un sed après avoir modifié une option avec make menuconfig ? Faites-le et relancez la compilation en faisant un make clean au préalable.
  • Lancez la compilation avec le paramètre V=99, lisez le message d'erreur. C'est parfois tout bête (espace disque manquant (sisi ...), mauvaise saisie dans un makefile, ...).

Si rien n'améliore la situation, supprimez vos modifications récentes (d'où l'intérêt d'avoir fait des sauvegardes du buildroot à chaque étape concluante) et retenter la compilation sans oublier de faire un make clean. Si jamais quelque chose qui compilait avant ne compile plus, redémarrez votre ordinateur (sisi, ça arrive, même sous UNIX ...).

Ce qui vous reste à faire après le flashage

Le serveur SSH est fonctionnel et telnetd est déjà désactivé. Il est nécessaire d'attendre un peu pendant que dropbear génère la paire de clés du serveur. Durant ce laps de temps, le serveur rejette les tentatives de connexions sur le port SSH.

Changez le mot de passe de root, même si vous utilisez une authentification par clé publique avec la commande passwd.

Changez le mot de passe de chacun des comptes utilisateurs sans droits avec passwd <login> .

Définissez le mot de passe pour le DDNS avec la commande : uci set ddns.myddns.password=XXXX

Modifiez le proprietaire du home directory de chacun de vos comptes utilisateurs sans droits : chown -R login:groupe home_directory

Profit !

Les sources de ce billet sont identiques à celles de l'ancien billet.

Créez votre image personnalisée d’OpenWRT

Avant de traiter le sujet du jour, je souhaite vous informer que j'ai relu tous les billets traitants d'OpenWRT et que j'ai modifié/corrigé la plupart d'entre eux. En effet, certains d'entre eux comportaient des phrases imprécises, d'autres des bourrelets inutiles et enfin d'autres comportaient des phrases qui pouvaient prêter à confusion.

Commençons à traiter le sujet du jour : créer une image personnalisée d'OpenWRT pour votre routeur. Attention : je parle ici d'un routeur déjà supporté par OpenWRT, pas d'une adaptation d'OpenWRT à votre routeur qui n'est pas encore supporté.

ÉDIT du 15 juillet 2012 : Ce billet traite de Backfire 10.03. Quelques petites choses ont changées avec Backfire 10.03.1 et je vous conseille en conséquence de lire, en parallèle, cet autre billet : Créez votre image personnalisée d’OpenWRT : ce qui change avec Backfire 10.03.1.

ÉDIT du 04 janvier 2014 : Ce billet traite de Backfire 10.03. Quelques petites choses ont changées avec Attitude Adjustment 12.09 et je vous conseille en conséquence de lire, en parallèle, cet autre billet : Créez votre image personnalisée d’OpenWRT : ce qui change avec Attitude Adjustment 12.09.

Table des matières

Pourquoi créer une image personnalisée ?

Tout est déjà dit sur le wiki d'OpenWRT, je traduis juste :

  • Inclure les logiciels dont vous avez besoin directement dans l'image squashfs permet de réduire l'espace disque qu'ils occupent sur la flash de votre routeur. Cela est dû aux propriétés du système de fichier squashfs qui est compressé. Pour vous donner un ordre d'idée des gains : prenons une Backfire 10.03 brcm47xx fraichement installée et installons dnscache, ntpd, etherwake, tcpdump-mini, luci-i18n-french, ddns-scripts, iptables-mod-conntrack-extra et supprimons luci-admin-mini et luci-i18n-english. Il me reste 196k d'espace libre. Maintenant, intégrons ces mêmes packages dans une image et installons-la sur le routeur. À la suite de cette installation, il reste 492k d'espace libre dans la mémoire de mon routeur. L'espace gagné vous permettra d'installer encore plus de logiciels :) .
  • Créer une image personnalisée vous évitera de tout réinstaller et de tout reconfigurer en cas de problème. Si une expérience vient à foirer, vous aurez juste à reflasher votre routeur avec votre image personnalisée pour retrouver une configuration aux petits oignons. Et si vous avez plusieurs routeurs, vous gagnerez un temps fou en déploiement.
  • Construire une image minimale qui correspond à vos besoins.
  • Apprendre ... Ça se passe de commentaires.

Préparatifs

Si vous n'avez pas déjà installé l'environnement de développement d'OpenWRT, alors le mieux est de récupérer l'image builder de votre déclinaison.

Si comme moi, vous avez déjà récupéré la totalité de l'environnement, buildroot, servez-vous en. Il est inutile de télécharger l'image builder puisque celui-ci est inclus dans buildroot.

Dans la suite de ce guide, je considérerai que vous avez déjà récupéré buildroot. Sauf mention contraire, je considérerai également que votre répertoire courant est backfire_10.03, c'est-à-dire la racine du buildroot. Si vous avez déjà compilé quelque chose, sauvegardez les binaire obtenus et faites un peu de ménage avec :

backfire_10.03$ make clean

Note : selon ce que vous voulez obtenir, vous n'êtes pas obligé de suivre toutes les étapes de ce guide. Par exemple, si vous voulez simplement supprimer rdate proprement, vous vous contenterez de créer l'image officielle puis de configurer les options de busybox et de compiler le tout.

Recréer l'image officielle

Si j'ai un conseil à vous donner, progressez à petits pas vers la création de votre image personnalisée : compilez une image de base, puis intégrez vos packages et compilez, puis effectuez leur configuration et compilez encore, puis ... Il est inutile de tout faire d'un coup : si la compilation foire (et elle le fera, faites-moi confiance), vous galérerez pour trouver l'origine du bug. Dans la continuité de ce conseil, je vous conseille également de sauvegarder l'intégralité du buildroot après une compilation réussie. Ainsi, si la prochaine compilation plante et que vous ne trouvez pas l'origine du bug, vous pourrez toujours reprendre depuis votre sauvegarde plutôt que de tout recommencer depuis le début.

En suivant ce conseil, notre premier objectif sera de parvenir à la compilation de l'image officielle. Traduction : l'image que vous allez compiler, c'est celle qui est disponible en téléchargement sur le site officiel d'OpenWRT (ex. : openwrt-wrt54g-squashfs.bin). Cela n'a pas d'autres intérêts que de se faire la main.

On y va ! :)

D'abord, on met à jour la liste des paquets disponibles :

backfire_10.03$ ./scripts/feeds update -a && ./scripts/feeds install -a

Ensuite, on efface les fichiers de configuration de la compilation (créés automatiquement par make menuconfig, nous y reviendrons) :

backfire_10.03$ rm .config && rm .config.old

On récupère le fichier de configuration officiel (ici : déclinaison brcm47xx) et on le met en place :

backfire_10.03$ wget http://downloads.openwrt.org/backfire/10.03/brcm47xx/OpenWrt.config && mv OpenWrt.config .config

Par défaut, tous les packages sont compilés (en module) puis exclus de l'image finale. Pour éviter cette perte de temps lors de la compilation, on va demander à ce que les packages qui ne seront pas intégrés à l'image ne soient pas compilés. Pour cela, on commente les lignes qui finissent par "=m" (module) avec la commande suivante :

backfire_10.03$ sed -i 's,^.*=m,# & is not set,g' ./.config

On lance la compilation :

backfire_10.03$ make

Je vous rappelle qu'en cas de bug, il est possible d'utiliser l'option "V=99" qui permet d'avoir des indices quand à l'origine du plantage. Si vous avez un processeur multicœur, je vous rappelle qu'il est possible d'utiliser l'option "-j <nombre de cœurs + 1> .

Le système va compiler le noyau, busybox et les packages installés par défaut. Vous êtes autorisé à aller vous chercher un café 8) .

Si la compilation réussie (et il n'y a pas de raisons pour qu'elle ne réussisse pas), vous trouverez les images, au format squashfs, dans le dossier ./bin/brcm47xx .

Félicitation, vous venez de créer votre propre image pour votre routeur ! Elle doit avoir une taille équivalente à celle que l'on peut télécharger sur le site officiel. Vous pouvez essayer votre image sur votre routeur mais ce n'est vraiment pas la peine voire une mauvaise idée : la mémoire étant de la flash, elle est plus limitée qu'un disque dur en terme de nombre de cycles d'écriture possibles malgré les algorithmes de lissage de l'usure. Essayer une image qui n'a aucun intérêt use le matériel plus qu'autre chose.

Nous allons maintenant créer une image personnalisée.

Créer une image vraiment personnelle

Comme fil rouge, je vous propose de créer une image personnalisée contenant (presque) toutes les manipulations que je vous ai présentées sur ce blog : un résolveur DNS, un serveur NTP, ... Cela vous permettra de vous faire la main et de créer votre image bien à vous par la suite.

Si vous ne comprenez pas la raison d'être d'une modification ou si vous voulez plus d’explications, reportez-vous au billet qui traite de la modification en question. Ils sont tous dans la catégorie "OpenWRT".

Modifier les options du noyau Linux

Si vous voulez consulter et/ou modifier les options du noyau, utilisez la commande :

backfire_10.03$ make kernel_menuconfig

Une interface semi-graphique s'affichera au bout de quelques instants. Les options actuelles me convenant, je n'ai rien modifié. Mais il est toujours intéressant et instructif de regarder ce qui est déjà fait.

C'est également dans ce menu que vous pouvez, par exemple, activer le support du contrôle par groupe des processus, activez le support de systèmes de fichiers supplémentaires ou bien encore saisir un nom personnalisé pour votre noyau (la classe 8) pour frimer devant les copains).

Si vous faites des modifications, mettez "Exit" (bouton droit de la souris pour y accéder) et répondez "Yes" à la question de la sauvegarde de vos paramètres.

Ajouter/Supprimer des packages

Rien de plus facile : il suffit d'utiliser la commande :

backfire_10.03$ make menuconfig

Dans l'interface semi-graphique qui s'affiche, vous pouvez ajouter ou supprimer des packages.

Si vous n'avez pas un usage spécifique, vous pouvez désactiver la génération du SDK et de l'Image Builder. Vous gagnerez ainsi du temps à la compilation.

Pour notre part, nous activerons :

  • etherwake dans Network.
  • tcpdump-mini dans Network.
  • djbdns.-dnscache dans Network -> IP adresses and Names.
  • ddns-scripts dans Network -> IP adresses and Names.
  • ntpd dans Network -> Time Synchronization.
  • iptables-mod-conntrack-extra dans Network -> Iptables.
  • luci-i18n-french dans LuCi -> Translations.

C'est également le moment de décocher les logiciels que vous ne voulez pas afin qu'ils ne soient pas intégrés à l'image.Pour notre part, nous supprimerons les packages suivants :

  • ppp dans Network.
  • ppp-mod-pppoe dans Network.
  • kmod-ppp dans Kernel Modules -> Network support.
  • kmod-pppoe dans Kernel Modules -> Network support.

Pour sauvegarder vos paramètres, mettez "Exit" (bouton droit de la souris pour y accéder) et répondez "Yes" à la question de la sauvegarde de vos paramètres.

À moins que vous ne teniez à désactiver tous les autres composants qui vont être compilés en modules mais pas intégrés à l'image à la main, utilisez la commande que nous avons déjà vu :

backfire_10.03$ sed -i 's,^.*=m,# & is not set,g' ./.config

Ces deux étapes (sauvegarde des paramètres et désactivations des modules) sont à faire avant chaque compilation si vous avez modifié quelque chose dans l’interface semi-graphique.

Vous pouvez compilez avec make. N'oubliez pas de faire un make clean avant ! Je ne vous le rappellerai plus à partir de maintenant, il faudra donc y penser !

Deuxième pause café ! :D

Vous devriez obtenir une image d'une taille de 3Mo/3.1Mo environ . Il est encore inutile de tenter de l'installer sur votre routeur pour les raisons déjà évoquées ci-dessus.

Ajouter votre package personnel / vos modifications aux sources

Si vous avez créé/porté un logiciel pour OpenWRT, c'est le moment de le mettre en place dans l'arborescence avec son makefile et tout et tout. Je vous regarde faire ;) .

Ensuite, vous n'avez plus qu'à le sélectionner dans l’interface semi-graphique de configuration.

C'est également le moment de faire les modifications que vous voulez dans les sources. Par exemple, dans un billet, je vous avais montré comment optimiser la sécurité de dropbear et l'espace qu'il occupe dans la flash. C'est le moment d'appliquer ces modifications si vous le désirez. Je vous laisse aller les chercher dans l'article d'origine : OpenWRT : sécuriser l’accès SSH - Compiler dropbear pour n’autoriser que 3 essais de mot de passe par connexion.

Vous pouvez compiler et fabriquer l'image. Là encore, il me paraît inutile de l'essayer. Si vous voulez juste tester la compilation d'un package personnel, vous pouvez compiler uniquement ce package avec la commande :

backfire_10.03$ make package/dropbear/compile

Modifiez les options de busybox

Busybox est très personnalisable. Sa configuration se fait encore via le menu obtenu via la commande :

backfire_10.03$ make menuconfig

Pour cela, il suffit d'aller dans Base system -> Busybox -> Configuration. Enjoy !

Dans le cadre de ce tutoriel, nous allons :

  • Désactiver "rdate" dans Linux System Utilities.
  • Activer "history saving" dans Busybox Settings -> Busybox Library Tuning. Cela permet de sauvegarder l'historique des commandes saisies par chaque utilisateur entre deux connexions. Cela peut être utile.

À vous de continuer à personnaliser votre installation. Vous pouvez compiler mais je ne pense pas que cela soit nécessaire vu le peu de modifications que nous avons apportées.

Modifier des options générales

En dehors de Busybox, il reste encore plein d'options à explorer.

Dans le cadre de notre fil rouge, nous allons commencer par changer la langue par défaut de LuCi. Pour cela, cochez "Image configuration", appuyez sur Entrée et cochez "Preinit configuration option". Dans "Default Language", tapez "fr" et validez.

Maintenant, nous allons supprimer luci-admin-mini. Nous ne pouvons pas le faire depuis le menu de configuration car d'autres packages dépendent de lui. Nous allons forcer sa désinstallation en éditant directement le fichier .config, chose qu'il faut éviter de faire au maximum.

backfire_10.03$ vi .config

Cherchez la ligne suivante :

CONFIG_PACKAGE_luci-admin-mini=y

et commentez-là :

# CONFIG_PACKAGE_luci-admin-mini=y is not set

Appliquons le même raisonnement pour le package "luci-i18n-english".

Enregistrer vos modifications et quittez vi.

Libre à vous d'explorer les autres options.

Vous pouvez compiler l'image. Et si vous le souhaitez, vous pouvez même installer cette image sur votre routeur.

Note : Oui, j'ai lu la première ligne du fichier .config qui dit de ne pas le modifier à la main. Mais, n'ayant pas trouvé les packages qui dépendent de luci-admin-mini et de luci-i18n-english, je n'ai pas vraiment le choix. De plus, ce conseil est donné dans le cas où vous activez un logiciel sans activer ses dépendances (ex. : activer djbdns-dnscache sans activer djbdns-base). Autrement dit : si vous connaissez les dépendances d'un package que vous voulez installer, vous pouvez modifier le .config à la main sans problèmes.

Configurer les logiciels

Logiciels configurables avec uci

Il suffit de créer des scripts. Ces scripts seront placés dans un dossier files/etc/uci-defaults à la racine du buildroot. Tous les scripts se trouvant dans ce dossier seront exécutés une seule fois après le flashage du routeur quelque soit leur nom. Voici, à titre d'exemple, les scripts destinés à configurer les logiciels que nous avons installés ci-dessus :

backfire_10.03/files/etc/uci-defaults/ddns (pour ddns-scripts et DynDNS) :

#!/bin/sh
 
# DDNS parametres
uci set ddns.myddns.enabled=1 2>/dev/null
uci set ddns.myddns.interface=wan 2>/dev/null
uci set ddns.myddns.service_name=dyndns.org 2>/dev/null
uci set ddns.myddns.domain=<votre ndd> 2>/dev/null
uci set ddns.myddns.username=<votre login sur dynDNS> 2>/dev/null
uci set ddns.myddns.ip_source=network 2>/dev/null
uci set ddns.myddns.ip_network=wan 2>/dev/null
uci set ddns.myddns.force_interval=24 2>/dev/null
uci set ddns.myddns.force_unit=hours 2>/dev/null
uci set ddns.myddns.check_interval=10 2>/dev/null
uci set ddns.myddns.check_unit=minutes 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null

Vous pouvez également marquer en dur votre mot de passe (uci set ddns.myddns.password=XXXX 2>/dev/null), mais je ne vous le conseille pas. Même si votre compte DynDNS n'est pas le compte le plus précieux que vous ayez, ce n'est pas une bonne pratique.

Dans la même veine, la bonne pratique voudrait que vous mettiez votre IP à jour sur DynDNS en utilisant le protocole HTTPS. C'est possible, voir le wiki d'OpenWRT à ce sujet mais les libs prennent beaucoup de place et je n'ai pas assez d'espace pour les accueillir.

Si vous êtes derrière une box ou qu'autre chose fait que l'interface wan (eth0.1) n'a pas une ip publique, il vous faudra utiliser un service externe pour récupérer votre ip publique et remplacer ces deux lignes :

uci set ddns.myddns.ip_source=network 2>/dev/null
uci set ddns.myddns.ip_network=wan 2>/dev/null

par

uci set ddns.myddns.ip_source=web 2>/dev/null
uci set ddns.myddns.ip_url=http://automation.whatismyip.com/n09230945.asp 2>/dev/null

backfire_10.03/files/etc/uci-defaults/dnscache (pour djbdns-dnscache) :

#!/bin/sh
 
# On configure dnscache
uci set djbdns.@dnscache[0].interface=lan 2>/dev/null
uci set djbdns.@dnscache[0].defaultallowif=lan 2>/dev/null
uci set djbdns.@dnscache[0].forwardonly=0 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null
 
# On met les bonnes autorisations sur le script d'init de dnscache
chmod ugo+x /etc/init.d/dnscache 2>/dev/null

 
# dnscache est déjà pris en compte par hotplugd, il n'a pas besoin d'init pour 
# se lancer
rm -f /etc/rc.d/S65dnscache 2>/dev/null

ATTENTION : dnscache est pris en charge par hotplugd uniquement si votre interface wan est configurée avec DHCP. Dans le cas d'une IP statique sur l'interface wan et d'après mes tests, hotplugd n'agit pas et init est nécessaire. Si vous êtes dans ce cas, ne supprimez pas le script d'init.

backfire_10.03/files/etc/uci-defaults/dnsmasq (pour dnsmasq) :

#!/bin/sh
 
# On désactive la fonctionnalité forward DNS de dnsmasq
uci set dhcp.@dnsmasq[0].port=0 2>/dev/null

 
 
# On valide tout
uci commit 2>/dev/null
 
# On met les bonnes autorisations sur le script d'init de dnsmasq
chmod ugo+x /etc/init.d/dnsmasq 2>/dev/null

backfire_10.03/files/etc/uci-defaults/dropbear (pour dropbear) :

#!/bin/sh
 
# On désactive l'authentification par mot de passe
uci set dropbear.@dropbear[0].PasswordAuth=off 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null

backfire_10.03/files/etc/uci-defaults/firewall (pour configurer, un peu, netfilter) :
L'idée, c'est de définir, intégralement, nos propres règles, de A à z. Or, des règles sont chargées à chaque reboot du routeur à partir du fichier /etc/config/firewall. Plusieurs méthodes s'offrent, comme d'habitude, à vous : soit vous éditez /etc/config/firewall qui est dans un format classique d'uCi pour y intégrer vos règles. Soit vous supprimez ce fichier de l'image et vous définisez, dans un script d'init, les règles de filtrage qu'il convient d'appliquer. Ayant déjà un script standard qui charge mes règles de filtrage qui est pas trop mauvais, j'ai choisi cette deuxième solution. backfire_10.03/files/etc/uci-defaults/firewall contient donc :

#!/bin/sh

 
# On supprime les regles par defaut stockees dans uci
rm -rf /etc/config/firewall 2>/dev/null

 
# On met les bonnes autorisations sur le script d'init du firewall
chmod ugo+x /etc/init.d/firewall 2>/dev/null

backfire_10.03/files/etc/uci-defaults/ntpd (pour configurer, un peu, ntpd) :

#!/bin/sh
 
# ntpd est deja lance par hotplug.d, nous n'avons pas besoin qu'il soit lance par init
rm -f /etc/rc.d/S65ntpd 2>/dev/null

ATTENTION : ntpd est pris en charge par hotplugd uniquement si votre interface wan est configurée avec DHCP. Dans le cas d'une IP statique sur l'interface wan et d'après mes tests, hotplugd n'agit pas et init est nécessaire. Si vous êtes dans ce cas, ne supprimez pas le script d'init de ntpd.

backfire_10.03/files/etc/uci-defaults/system (pour configurer les options générales du système) :

#!/bin/sh
 
# Nom du routeur
uci set system.@system[0].hostname="Nouveau_Nom" 2>/dev/null

echo "Nouveau_Nom" > /proc/sys/kernel/hostname 2>/dev/null

 
# Fuseau horaire
uci set system.@system[0].zonename=Europe/Paris 2>/dev/null
uci set system.@system[0].timezone=CET-1CEST,M3.5.0,M10.5.0/3 2>/dev/null

 
# On finit de supprimer rdate
uci del system.@rdate[0] 2>/dev/null
rm -f /etc/hotplug.d/iface/40-rdate 2>/dev/null

 
# On valide tout
uci commit 2>/dev/null

backfire_10.03/files/etc/uci-defaults/network (pour configurer les interfaces réseau) :

#!/bin/sh
 

# Configuration interface LAN
uci set network.lan.proto=static
uci set network.lan.netmask=255.255.255.0
uci set network.lan.ipaddr=192.168.0.254
uci set network.lan.dns=192.168.0.254 #dnscache

 
# Configuration interface WAN
uci set network.wan.proto=static
uci set network.wan.ipaddr=192.168.1.253
uci set network.wan.netmask=255.255.255.0
uci set network.wan.gateway=192.168.1.254
uci set network.wan.dns=192.168.0.254 #dnscache

 
# On valide tout
uci commit 2>/dev/null

Je pense que les interfaces peuvent également être configurées depuis le .config puisqu'on peut y lire les lignes suivantes :

CONFIG_UCI_PRECONFIG_network_lan_dns=""

CONFIG_UCI_PRECONFIG_network_lan_proto="static"
CONFIG_UCI_PRECONFIG_network_lan_gateway=""
CONFIG_UCI_PRECONFIG_network_lan_netmask="255.255.255.0"
CONFIG_UCI_PRECONFIG_network_lan_ipaddr="192.168.1.1"

Mon test a échoué mais je pense que cela est dû à un autre paramètre que j'ai activé en même temps.

On peut même configurer l'adresse que prend le bootloader :

CONFIG_TARGET_PREINIT_IFNAME=""
CONFIG_TARGET_PREINIT_IP="192.168.1.1"
CONFIG_TARGET_PREINIT_NETMASK="255.255.255.0"
CONFIG_TARGET_PREINIT_BROADCAST="192.168.1.255"

Vu le nombre de fois où ce bootloader et son serveur TFTP m'ont sauvés la mise, je n'ai pas essayé de changer ces paramètres.

Vous avez compris le principe et vous pouvez créer vos propres scripts pour les logiciels que vous avez installés ou modifier les scripts ci-dessous afin de configurer plus finement certains logiciels (dnsmasq par exemple).

Logiciels ne pouvant pas être configurés avec uci

Il y a des logiciels qui possèdent leurs propres fichiers de configuration. Pour eux, il suffit de placer les fichiers dans l'arborescence, comme si vous étiez sur votre routeur. Par exemple, si à la fin du flashage, vous avez besoin qu'un fichier /etc/xxxx soit créez, alors placez-le dans backfire_10.03/files/etc/xxxx et il sera mis au bon endroit. Si le fichier existe déjà car il est fourni par un logiciel, par exemple, il sera écrasé par votre version.

Il y a une autre manière de procéder : mettre le fichier dans le package qui lui correspond. Exemple : vous avez un fichier de configuration pour ntpd (/etc/ntp.conf), alors vous le mettez dans feeds/packages/net/ntpd/files/etc/ntp.conf. Pour les packages par défaut (dropbear par exemple), le chemin est différent : packages/dropbear ...

Personnellement, j'ai choisi de tout mettre dans un même dossier car cela simplifie la maintenance.

Voici donc les fichiers que j'ai rajoutés.

backfire_10.03/files/etc/banner (le message de bienvenue lors d'une connexion SSH) :

Salut !

backfire_10.03/files/etc/ntp.conf (configuration de ntpd) :

server ntp-p1.obspm.fr iburst prefer
server canon.inria.fr iburst
 
restrict default ignore
restrict ntp-p1.obspm.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict canon.inria.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer
restrict 127.0.0.1
 
driftfile  /etc/ntp.drift

backfire_10.03/files/etc/services (nécessaire au bon fonctionnement de ntpd) :
Sans lui, vous aurez des messages d'erreur du genre "getaddrinfo: "ntp-p1.obspm.fr" invalid host address, ignored", "restrict: error in address 'ntp-p1.obspm.fr' on line 6. Ignoring...", "Deferring DNS for ntp-p1.obspm.fr 1" et "getaddrinfo(127.0.0.1) failed: Servname not supported for ai_socktype".

ntp             123/udp     # Network Time Protocol
ntp             123/tcp     # Network Time Protocol

backfire_10.03/files/etc/passwd (permet de rajouter des comptes utilisateur sans droits d'administration (ici : guest)) :

root:*:0:0:root:/root:/bin/ash
guest:*:65533:65533:guest:/home/guest:/bin/ash
nobody:*:65534:65534:nobody:/var:/bin/false
daemon:*:65534:65534:daemon:/var:/bin/false

backfire_10.03/files/etc/group (permet de rajouter des groupes utilisateurs destinés à accueillir les comptes standards) :

root:x:0:
guestg:x:65533:
nogroup:x:65534:

Authentification par clé publique/privée :

Mettez la clé publique de root dans backfire_10.03/files/etc/dropbear/authorized_keys si vous voulez utiliser l'authentification à clé publique pour vous connecter avec le compte root via SSH.

Pour chaque compte utilisateur créé, mettez sa clé publique dans un fichier ".ssh/authorized_keys" placé dans son home directory. Par exemple, pour le compte guest créé ci-dessous, la clé publique devra se trouver dans backfire_10.03/files/home/guest/.ssh/authorized_keys .

Si vous voulez utiliser l'authentification par clé publique pour vos comptes sans droits, ne changez surtout pas le propriétaire de leurs home directory (pas de chown -R guest:guestp /home/guest dans un script dans l'image). En effet, pour une raison qui m'échappe, l'authentification échoue sinon. Mais, dans ce cas-là, l'utilisateur n'est pas vraiment chez lui : il ne peut pas créer un répertoire par exemple. Heureusement, vous pouvez changer le proprietaire du home directory de chacun de vos comptes utilisateurs après le flashage et aucun problème n'apparait.

backfire_10.03/files/etc/hotplug.d/iface/15-dnsd (script permettant de relancer dnscache en cas de coupure de l'accès au net) :

#!/bin/sh
 
if [ "$INTERFACE" = "wan" ] 

then
	DNS_RUNNING=`ps  | grep dnscache | grep -v grep`

 
	case "${ACTION:-ifup}" in
        	ifup)
                	[ -z "$DNS_RUNNING" ] && /etc/init.d/dnscache start
       		;;

 
		ifdown)
               		[ -n "$DNS_RUNNING" ] && /etc/init.d/dnscache stop
        	;;

	esac
fi

ATTENTION : Il semble que ce script est inutile si vous êtes en IP statique sur l'interface WAN.

backfire_10.03/files/etc/init.d/dnscache (script d'init pour dnscache modifié pour logger les démarrages/arrêts du démon) :
ATTENTION : Le script n'est pas donné ici dans son intégralité. Attention donc aux copier/coller malheureux.

#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
 
[...]
 
start() {
    echo "Starting $DESC: $NAME"

    logger starting dnscache
    config_load djbdns
    config_foreach get_userids global
    mkdir -p $ROOT
    cp -fa /etc/dnscache/* $ROOT

    rm -f $ROOT/resolvers
    rm -f $ROOT/ignoreip
    chown -R $UID:$GID $ROOT

    config_foreach start_dnscache dnscache
}
 
[...]
 
stop() {
    echo -n "Stopping $DESC: $NAME"

    logger stopping dnscache
    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1

    echo " ."
}
 
restart() {
    echo "Restarting $DESC: $NAME... "

    stop
    sleep 2
    start
}

backfire_10.03/files/etc/init.d/dnsmasq (script d'init pour dnsmasq modifié afin d'indiquer uniquement notre résolveur DNS local) :
ATTENTION : Le script n'est pas donné ici dans son intégralité. Attention donc aux copier/coller malheureux.

#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org
 
START=60
DNS_SERVERS=""
DOMAIN=""
 
[...]
 
start() {
        include /lib/network
        scan_interfaces
        config_load dhcp
 
        args=""
        config_foreach dnsmasq dnsmasq
        config_foreach dhcp_host_add host
        config_foreach dhcp_boot_add boot
        config_foreach dhcp_mac_add mac
        config_foreach dhcp_vendorclass_add vendorclass
        config_foreach dhcp_userclass_add userclass
        config_foreach dhcp_circuitid_add circuitid
        config_foreach dhcp_remoteid_add remoteid
        config_foreach dhcp_subscrid_add subscrid
        config_foreach dhcp_domain_add domain
        config_foreach dhcp_add dhcp
 

        /usr/sbin/dnsmasq $args && {
                rm -f /tmp/resolv.conf
                [ -n "$DOMAIN" ] && echo "search $DOMAIN" >> /tmp/resolv.conf
                DNS_SERVERS="192.168.1.1" #A REMPLACER SI VOTRE ROUTEUR A UNE IP LAN DIFFERENTE !
                for DNS_SERVER in $DNS_SERVERS ; do
                        echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
                done
        }
}

 
stop() {
        [ -f /tmp/resolv.conf ] && {
                rm -f /tmp/resolv.conf
                ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
        }
        killall dnsmasq
        return 0
}

backfire_10.03/files/etc/init.d/firewall (pour configurer, un peu plus, netfilter) :
À adapter à vos besoins et à complèter car il manque encore des choses (séparation tcp, udp, icmp et filtrage différentié, éviter d'autoriser des connexions sur le simple fait qu'elles sont établies mais préciser le port source, ...)

#!/bin/sh /etc/rc.common
 
START=45

 
start() {
	#On fait le menage
	stop
 
	############### TABLE FILTER
	##On créer les chaînes correspondant à nos zones
	iptables -t filter -N lan-lan
	iptables -t filter -N lan-bas
	iptables -t filter -N lan-wan

 
	iptables -t filter -N bas-lan
	iptables -t filter -N bas-bas
	iptables -t filter -N bas-wan

 
	iptables -t filter -N wan-lan
	iptables -t filter -N wan-bas
	iptables -t filter -N wan-wan

 
	##On redirige les paquets vers nos chaines
	iptables -t filter -A INPUT -i br-lan -j lan-bas
	iptables -t filter -A INPUT -i lo -j bas-bas
	iptables -t filter -A INPUT -i eth0.1 -j wan-bas

 
	iptables -t filter -A FORWARD -i br-lan -o br-lan -j lan-lan
	iptables -t filter -A FORWARD -i br-lan -o eth0.1 -j lan-wan 
	iptables -t filter -A FORWARD -i eth0.1 -o eth0.1 -j wan-wan
	iptables -t filter -A FORWARD -i eth0.1 -o br-lan -j wan-lan

 
	iptables -t filter -A OUTPUT -o br-lan -j bas-lan
	iptables -t filter -A OUTPUT -o lo -j bas-bas
	iptables -t filter -A OUTPUT -o eth0.1 -j bas-wan

 
	##On traite nos chaines
	#Du lan vers le routeur d'abord
	#Etablies/relatives
	iptables -t filter -A lan-bas -m state --state RELATED,ESTABLISHED -j ACCEPT
	#SSH

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT 
	#DNS

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT 
	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 53 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#DHCP

	iptables -t filter -A lan-bas -p udp -m state --state NEW -m udp --sport 68 --dport 67 -j ACCEPT
	#HTTP

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#NTP

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/32 -p udp -m state --state NEW -m udp --dport 123 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A lan-bas -s 192.168.0.0/24 -d 192.168.0.254/3 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

 
	#Du lan vers internet ensuite
	#Etablies/relatives
	iptables -t filter -A lan-wan -m state --state RELATED,ESTABLISHED -j ACCEPT
	#FTP

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 20 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 21 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SSH

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#HTTP/HTTPS

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SMTPS/SMTP auth

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 465 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 587 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#POP3S

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 995 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SVN

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 3690 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p udp -m state --state NEW -m udp --dport 3690 -j ACCEPT
	#IRC

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 6667 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 6697 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Plesk

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 8443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Git

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 9418 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p udp -m state --state NEW -m udp --dport 9418 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A lan-wan -s 192.168.0.0/24 -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

 
	#Du routeur vers le lan
	#Etablies/relatives
	iptables -t filter -A bas-lan -m state --state RELATED,ESTABLISHED -j ACCEPT 
	#DHCP

	iptables -t filter -A bas-lan -p udp -m state --state NEW -m udp --sport 67 --dport 68 -j ACCEPT

 
	#Boucle locale
	iptables -t filter -A bas-bas -j ACCEPT
 
	#Du routeur vers internet

	#Etablies/relatives
	iptables -t filter -A bas-wan -m state --state RELATED,ESTABLISHED -j ACCEPT
	#FTP dans tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 20 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 21 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#DNS

	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT 
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 53 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#HTTP/HTTPS pour opkg/HTTP dans tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#NTP

	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 123 -j ACCEPT
	#SMTPS/SMTP auth pour tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 465 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 587 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#POP3S dans tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 995 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#SVN

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 3690 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 3690 -j ACCEPT
	#IRC dans tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 6667 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 6697 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Plesk pour tunnel SSH

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 8443 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	#Git

	iptables -t filter -A bas-wan -p tcp -m state --state NEW -m tcp --dport 9418 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	iptables -t filter -A bas-wan -p udp -m state --state NEW -m udp --dport 9418 -j ACCEPT
	#ICMP (echo request)

	iptables -t filter -A bas-wan -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

 
	#D'internet vers le lan
	#Etablies/relatives
	iptables -t filter -A wan-lan -m state --state RELATED,ESTABLISHED -j ACCEPT

 
	#D'internet vers le routeur enfin
	#Etablies/relatives
	iptables -t filter -A wan-bas -m state --state RELATED,ESTABLISHED -j ACCEPT
	#SSH

	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --update --seconds 600 --hitcount 2 -j DROP
	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --set

	iptables -t filter -A wan-bas -p tcp --dport 22 -m state --state NEW -j ACCEPT

 
	##On change les politiques d'accés
	iptables -t filter -P INPUT DROP
	iptables -t filter -P FORWARD DROP
	iptables -t filter -P OUTPUT DROP

 
 
	##############TABLE NAT
	##On créer des chaines qui correspondent à nos zones
	iptables -t nat -N prerouting-lan
	iptables -t nat -N prerouting-wan

 
	iptables -t nat -N postrouting-lan
	iptables -t nat -N postrouting-wan
 
	##On redirige les paquets dans nos chaines

	#C'est ici que l'on peut rediriger des ports (ex. : proxy transparent, on redirige port 80/443 -> 8080)
	iptables -t nat -A PREROUTING -i br-lan -j prerouting-lan

 
	#C'est ici que l'on fait le DNAT (ex. : monter un serveur web sur le LAN, accessible sur internet)
	iptables -t nat -A PREROUTING -i eth0.1 -j prerouting-wan

 
	iptables -t nat -A POSTROUTING -o br-lan -j postrouting-lan
 
	#C'est ici que l'on fait le SNAT ou MASQUERADE si ip dynamique

	iptables -t nat -A POSTROUTING -o eth0.1 -j postrouting-wan
 
	##On traite nos chaines

	##SNAT/masquerade
	iptables -t nat -A postrouting-wan -s 192.168.0.0/24 -j MASQUERADE

 
	##DNAT
	# Torrent
	#iptables -t nat -A prerouting-wan -p tcp -m tcp --dport 4444 -j DNAT --to-destination 192.168.1.138:4444
	#iptables -t nat -A prerouting-wan -p udp -m udp --dport 4444 -j DNAT --to-destination 192.168.1.138:4444
 
	##############TABLE MANGLE

	##Cette table sert pour la modification des paquets (ex:. marquer les paquets pour faire de la QoS ensuite)
	##Nous verrons cela plus tard
 
 
	##############TABLE RAW
	##Cette table sert à indiquer les connections qui ne doivent pas être suivies par conntrack
 
	echo "Firewall started"

	logger Firewall started
}
 
stop() {
	############### TABLE FILTER
	##On change les politiques d'accés
	iptables -t filter -P INPUT ACCEPT
	iptables -t filter -P FORWARD ACCEPT
	iptables -t filter -P OUTPUT ACCEPT

 
	##On fait le menage
	iptables -t filter -F
	iptables -t filter -X

 
 
	##############TABLE NAT
	##On change les politiques d'accés
	iptables -t nat -P PREROUTING ACCEPT

	iptables -t nat -P OUTPUT ACCEPT
	iptables -t nat -P POSTROUTING ACCEPT
 
	##On fait le menage

	iptables -t nat -F
	iptables -t nat -X
 
	#NAT

	iptables -t nat -A POSTROUTING -o eth0.1 -s 192.168.0.0/24 -j MASQUERADE

 
 
	##############TABLE MANGLE
	##On change les politiques d'accés
	iptables -t mangle -P PREROUTING ACCEPT
	iptables -t mangle -P INPUT ACCEPT
	iptables -t mangle -P FORWARD ACCEPT
	iptables -t mangle -P OUTPUT ACCEPT
	iptables -t mangle -P POSTROUTING ACCEPT

 
	##On fait le menage
	iptables -t mangle -F
	iptables -t mangle -X

 
 
	##############TABLE RAW
	##On change les politiques d'accés
	iptables -t raw -P PREROUTING ACCEPT
	iptables -t raw -P OUTPUT ACCEPT

 
	##On fait le menage
	iptables -t raw -F
	iptables -t raw -X

 
	echo "Rules cleaned and firewall stopped"
	logger Rules cleaned and firewall stopped
}
 
restart() {
	start
 
	echo "Firewall restarted"

	logger Firewall restarted
}
 
reload() {
	start
 
	echo "Firewall reloaded"
	logger Firewall reloaded

}

À vous de continuer la configuration de votre système (ex. : VLAN). La méthode exposée ci-dessus fonctionne pour tous les fichiers.

Vous pouvez compiler puis essayer l'image ainsi générée. Tous vos logiciels doivent être configurés.

Si jamais vous avez une erreur durant la compilation

La liste ci-dessous est loin d'être exhaustive.

  • N'avez-vous pas oublié de faire un make clean avant de compiler ? Faites-le et relancez la compilation en faisant un make clean au préalable.
  • N'avez-vous pas oublié de faire un sed après avoir modifié une option avec make menuconfig ? Faites-le et relancez la compilation en faisant un make clean au préalable.
  • Lancez la compilation avec le paramètre V=99, lisez le message d'erreur. C'est parfois tout bête (espace disque manquant (sisi ...), mauvaise saisie dans un makefile, ...).

Si rien n'améliore la situation, supprimez vos modifications récentes (d'où l'intérêt d'avoir fait des sauvegardes du buildroot à chaque étape concluante) et retenter la compilation sans oublier de faire un make clean. Si jamais quelque chose qui compilait avant ne compile plus, redémarrez votre ordinateur (sisi, ça arrive, même sous UNIX ...).

Ce qui vous reste à faire après le flashage

Le serveur SSH est fonctionnel et telnetd est déjà désactivé. Il est nécessaire d'attendre un peu pendant que dropbear génère la paire de clé du serveur. Durant ce laps de temps, le serveur rejette les tentatives de connexions sur le port SSH.

Changez le mot de passe de root, même si vous utilisez une authentification par clé publique avec la commande passwd.

Changez le mot de passe de chacun des comptes utilisateurs sans droits avec passwd <login> .

Définissez le mot de passe pour le DDNS avec la commande : uci set ddns.myddns.password=XXXX

Modifiez le proprietaire du home directory de chacun de vos comptes utilisateurs sans droits : chown -R login:groupe home_directory

Profit !

Sources

P.S. : Oui, j'ai remarqué les bugs de mon hébergeur (site inaccessible, billet qui disparait (ou plutôt base de données qui perd des données ...)). Ça devrait aller mieux ... peut-être :D .

mail

Installer un serveur NTP sur OpenWRT

Table des matières

Pourquoi ?

Vous avez peut-être lu mon billet sur comment utiliser un client NTP sous OpenWRT et vous vous demandez peut-être pourquoi je décide maintenant d'utiliser un serveur.

Tout simplement car je me suis aperçu que j'avais fait une erreur lors de mon choix d'utiliser seulement un client NTP.

En effet, comment vais-je synchroniser les autres machines de mon réseau ? Comme avant, en utilisant un serveur externe ? Avouez que cela fait beaucoup de requêtes, ce qui encombre inutilement ma bande passante comme la bande passante du serveur externe. De plus, si la connexion au net tombe, un serveur local permettra de conserver le même temps (qui perdra en précision, certes) sur toutes les machines du LAN.

De plus, un serveur NTP permet une plus grande précision (certains se demanderont si on a besoin d'une telle précision ... à chacun de juger). À titre d'exemple : selon la documentation officielle, ntpclient utilise le premier serveur qu'il peut joindre parmi ceux que vous lui avez spécifiés. NTPd utilise des algorithmes plus complexes pour déterminer le meilleur serveur de temps de la liste.

Il doit surement y avoir d'autres arguments en faveur d'un serveur NTP mais je pense que je vous ai donné les principaux

Quel serveur choisir ?

root@OpenWrt:~# opkg list | grep -i NTP
chrony - 1.23-3 - A NTP implementation that has been specifically written to work
 connection to the network where your NTP servers are.
[...]
ntpd - 4.2.6-4 - The ISC ntp suite is a collection of tools used to synchronize
 the system clock with remote NTP time servers and run/montior
 local NTP servers.
 This package contains the ntpd server.
[...]
openntpd - 3.9p1-3 - A free and easy to use NTP (Network Time Protocol) implementation.

OpenWRT donne le choix entre trois implémentations du protocole NTP :

  • ntpd de ntp.org, le démon de référence maintenu par l'ISC.
  • openntpd, un démon maintenu par le projet OpenBSD.
  • chronyd, un démon NTP à préférer en cas de connexion instable au réseau.

Ma connexion est relativement stable donc chrony n'est pas fait pour moi. Le choix entre openntpd ou ntpd dépend de vos préférences ... Openntpd est sous licence BSD, ntpd est sous licence ISC. Openntpd est une implémentation allégée avec une configuration plus simple (je n'ai pas dit "simpliste" !) du protocole NTP mais le fait qu'il soit développé par l’équipe du projet OpenBSD est un gage de sécurité supplémentaire (openntpd tourne sous un compte sans droits par exemple). ntpd propose une configuration plus touffue (je n'ai pas dis "plus efficace"), un mécanisme d'authentification ainsi que des outils permettant de surveiller le fonctionnement du démon, ce que ne propose pas openntpd. Opennptd propose un système de poids pour choisir la priorité des serveurs NTP à interroger plutôt qu'une simple option "prefer" comme ntpd ... Bref, comme vous le voyez, la décision vous revient, dépend de vos besoins et est très personnelle.

Personnellement, j'ai choisi ntpd, le démon historique pour 2 raisons :

  • Sous OpenWRT, openntpd réclame le support de l'ipv6 (sinon un message "fatal: client_query socket: Address family not supported by protocol" s'affichera lors du lancement. Il faut donc installer le package kmod-ipv6. Je ne souhaite pas avoir le support ipv6 sur mon routeur pour l'instant (tant que mon FAI ne me proposera pas du full ipv6 en fait) et donc m’encombrer d'un package inutile. Source : can't start the NTP daemon (openntpd) sur forum.openwrt.org
  • Openntpd ne permet pas de déplacer le fichier servant à stocker la dérive de l'horloge. Celui-ci se trouve dans /var/db qui est un répertoire tmpfs donc effacé au redémarrage du routeur. Donc le serveur doit recalculer la dérive à chaque redémarrage. Même si ce n'est pas une opération lourde, c'est dommage.

Dans la suite de ce guide, je m’intéresserai donc uniquement à ntpd de ntp.org.

Installation de ntpd

Vous avez l'habitude :

opkg update && opkg install ntpd

Configuration de ntpd

Modification du fichier de configuration

La configuration se fait dans le fichier /etc/ntp.conf (attention, pas de "d" à "ntp" !). Voici le fichier que je vous propose :

## Les serveurs externes qui seront utilisés pour se synchroniser (strate 1 et 1)
server ntp-p1.obspm.fr iburst prefer
server canon.inria.fr iburst
 
## Contrôle des accès
# Par défaut, on ne répond à rien ...
restrict default ignore

# ... exception faite des serveurs externes sur lesquels on va se synchroniser ... 
# (rien ne circule sauf la correction du temps : dans l'ordre, on n'autorise 
# pas la création de hooks pour des journaux à distance, on ne peut pas consulter 
# ou modifier la configuration du serveur, les serveurs ne peuvent pas tenter 
# d'établir une connexion en tant que peer)
restrict ntp-p1.obspm.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict canon.inria.fr mask 255.255.255.255 nomodify notrap nopeer noquery

# ... et des stations du réseau local (on peut demander le temps et consulter 
# l'état du serveur, les autres actions sont refusées)
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer
 
# ... et en local (on peut tout faire)
restrict 127.0.0.1
## Fin du contrôle des accès
 
# On stocke le décalage de l'horloge système. Cela permet de maintenir, un peu, 
# l'heure en cas de coupures du net. Ne pas placer ce fichier dans un répertoire 
# temporaire : cela évite aussi à ntpd d'avoir à refaire les calculs permettant
# de déterminer la dérive de l'horloge après chaque redémarrage.
driftfile  /etc/ntp.drift

Malgré les commentaires, je souhaite ajouter quelques détails :

  • Pour trouver des serveurs NTP, vous pouvez faire une recherche Google et/ou consulter le site du Comité Réseau des Universités. Veuillez à respecter les conditions d'utilisation (ce n'est pas compliqué à envoyer, un mail). Essayez de choisir des serveurs qui ne sont pas sur le même réseau/FAI afin d'accroître la redondance en cas de problème sur un réseau. Ce point est relativement compliqué vu que beaucoup de serveur sont fournis par l'enseignement supérieur et donc sont sur le réseau RENATER. Ce point n'est pas non plus le point capital : même si tout un réseau venait à tomber (ce qui est déjà rare), votre horloge ne sera pas instantanément déréglée E de plusieurs minutes. Par contre, veuillez à choisir des serveurs qui ne sont pas dépendant l'un de l'autre. Exemple : vous choisissiez d'utiliser S1 et S2, deux serveurs pris au hasard et vous vous rendez compte qu'en fait S2 se synchronise sur S1 ... Pour vérifier cela, utilisez la commande "ntpq -np <ip_du_serveur>" sur chaque serveur que vous souhaitez utiliser.
  • Comme vous pouvez le constater, j'utilise des serveurs de strate 1. On pourra discuter sur les usages qu'un particulier peut faire de ces serveurs et de la précision associée. On pourra également s'interroger sur qui a réellement besoin d'une horloge en strate 2 et de sa grande précision (pourvu que la source soit fiable) : une PME, une institution bancaire, l'armée ?! Bref, je m'arrête là. Bien qu'on recommande habituellement l'usage de serveurs de strate 2 voire 3 pour un particulier, je signale que je ne suis pas le seul à utiliser un serveur de strate 1 : voir à ce sujet l'article "Installation pas à pas de Debian 6.0 (Squezze)" dans GNU/Linux Magazine/France n°139 de juin 2011.
  • L'option iburst permet de répéter les tentatives quand un serveur est inaccessible.
  • L'option prefer permet de marquer un et un seul serveur comme étant ... notre serveur de temps de référence préféré.

ÉDIT 25/08/2011 à 2h15 :
Attention :
De nombreux guides (y compris celui-ci avant cette correction) suggèrent d'utiliser l'horloge locale en insérant les lignes suivantes dans le fichier de configuration :

server 127.127.1.0
fudge 127.127.1.0 stratum 10

Cela permet, en théorie, d'utiliser l'horloge locale afin que le serveur continue à fonctionner dans le cas où les serveurs externes deviendraient inaccessibles. Cela permet également de pouvoir synchroniser les clients alors que le serveur n'est pas encore totalement synchronisé avec les serveurs externes. Et, en effet, cela fonctionne.

Mais sur OpenWRT, lors de chaque reboot, l'horloge revient à l'heure de compilation du noyau. Probablement car il n'y a pas de circuit temporel sur le WRT54GL. Donc, le fait d'utiliser l'horloge locale comme référence fait que ntpd va mettre doucement à jour l'heure au lieu de la mettre brutalement à jour au démarrage du système puis de la synchroniser régulièrement. Et comme le décalage est important, la synchronisation initiale va prendre beaucoup de temps. Trop de temps. Donc, je ne conseille pas cette option sous OpenWRT.
Fin de l'édit

A noter : Par défaut, ntpd envoie ses journaux à syslog. Ils sont donc accessibles via la commande logread. Si vous voulez les enregistrer dans un fichier différent, il est possible d'utiliser l'option "logfile /path/fichier" dans le fichier de configuration. Il est également possible d'utiliser l'option "logconfig" pour régler les informations qui seront logguées (via syslog ou via le fichier). "logconfig +all" permet de tout logguer. Je ne conseille néanmoins pas cette option sur le long terme vu la masse d'information qui est envoyée mais elle peut servir lors d'une phase de débogage. Referez-vous au man pour voir les autres valeurs que peut prendre cette option.

Il n'y a rien d'autre à configurer : un script d'init et un script pour le démon hotplugd ont déjà été fourni par OpenWRT.

On pensera tout de même à configurer convenablement le pare-feu du routeur. Mais là, c'est une autre histoire :) .

Faire en sorte que ntpd n'écoute pas sur toutes les interfaces réseau

Pour cela, ntpd possède un paramètre, "-I", qui permet de préciser les interfaces sur lesquelles le démon écoutera. Bizarrement, il faut indiquer également l'interface de sortie (= l'interface par laquelle les paquets à destination des serveurs NTP externes passeront). De ce fait, ntpd doit, au minimum, écouter sur l'interface externe et sur l'interface LAN. Il le fait par défaut donc pas besoin de lui indiquer. Si vous avez plusieurs VLAN et que vous ne voulez pas proposer de serveur NTP sur l'un d'eux, il est préférable, à mon avis, de ne pas autoriser le plan d'adressage de ce VLAN dans le fichier de configuration de ntpd voir de bloquer le trafic NTP avec iptables. Si malgré tout vous voulez faire en sorte que ntpd écoute uniquement sur les interfaces que vous spécifiez, voici comment procéder.

Il suffit de modifier le fichier /etc/init.d/ntpd. Dans la fonction start, la ligne :

/usr/sbin/ntpd -g -p $PIDFILE

devient :

/usr/sbin/ntpd -g -p $PIDFILE -I <1ere_interface> -I <2eme interface>

Puis, relancez le démon :

/etc/init.d/ntpd restart

"ignore" versus serveur de strate >= 2

En effet, si vous utilisez un serveur dont la strate d'appartenance est supérieure à 1 combiné avec l'option de configuration "restrict default ignore", vous obtiendrez une sortie ressemblant à celle ci-dessous avec l'outil ntpq -p :

91.121.20.142   .INIT.          16 u    -   64    0    0.000    0.000   0.000

Votre serveur tente de savoir sur quel serveur se synchronise le serveur de strate > 1 que vous avez défini dans le fichier de configuration et il n'y parvient pas. Ce qui est normal puisque le serveur de référence du serveur de strate > 1 que vous utilisez n'a pas été autorisé dans le fichier de configuration. Le serveur défini est donc exclu du processus de sélection d'un serveur de référence. Cela n'a donc rien à voir avec les pool qui utilisent des serveurs aléatoires et ne permettent donc pas à ntpd de pouvoir réaliser l'association avec eux comme on le lit sur certains forums.

Deux méthodes s'offrent à vous pour résoudre ce problème :

  1. Ne pas utiliser l'option "restrict default ignore" dès le début afin de connaître les adresses des serveurs sur lesquels se synchronisent les serveurs que vous utilisez. Ainsi, vous n'avez plus qu'à les autoriser explicitement dans votre ntp.conf et à appliquer l'option "restrict default ignore" par la suite.
  2. La méthode n°1 trouvera ses limite dans le cas d'un pool de serveurs (ex. : fr.pool.ntp.org) car le serveur qui vous sert de référence change souvent (round-robin DNS (= fr.pool.ntp.org ne pointe pas toujours sur le même serveur de temps). Il vous faudrait donc pas mal de temps pour faire la liste complète de tous les serveurs qui servent de référence aux serveurs du pool. Dans ce cas là, au lieu d'utiliser l'option "restrict default ignore", vous devez utiliser l'option "restrict default notrap noquery nopeer". Vous pouvez supprimer les règles restrict que nous avons créées pour chaque serveur. Cela signifie aussi que toute machine arrivant à contacter votre routeur pourra se synchroniser sur celui-ci. Attention donc à bien configurer iptables sur l'interface eth0.1 si vous voulez éviter que votre bande passante ne soit pompée par des bots.

Test

D'abord, voyons les commandes que nous allons utiliser :

  • ntpq se trouve dans le package ntp (Debian) ou ntp-utils (OpenWRT). Vous pouvez utiliser cette commande depuis votre routeur.
  • ntpdate se trouve dans le package ntpdate (Debian).

Pour tester votre serveur, il vous suffit d'utiliser la commande ntpq -pn (l'adresse est facultative si vous lancez la commande depuis votre routeur). Vous devez obtenir une sortie qui ressemble à celle-ci :

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 145.238.203.14  .TS-2.           1 u   25   64    1   41.906  -35.002   0.113
 192.93.2.20     .GPSi.           1 u   24   64    1   42.545  -35.312   0.222
*127.127.1.0     .LOCL.          10 l   33   64    1    0.000    0.000   0.031

En essayant quelques dizaines de minutes plus tard (ça peut aller jusqu'à 30 minutes voire 1 heure), vous obtiendrez quelque chose comme :

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*145.238.203.14  .TS-2.           1 u   20   64    7   41.446  -38.169   3.057
+192.93.2.20     .GPSi.           1 u   22   64    7   42.545  -35.312   1.275
 127.127.1.0     .LOCL.          10 l   93   64    6    0.000    0.000   0.031

Vous constatez que le serveur ntp-p1.obspm.fr a été choisi comme serveur de référence et que le serveur canon.inria.fr est candidat en cas de problème. L'horloge locale a, quand a elle, été rejetée par l'algorithme de sélection. La valeur du champ pool doit augmenter progressivement jusqu'à atteindre 1024. La valeur du champ reach doit augmenter progressivement (1, 3, 7, 17, 37, 77, 177) jusqu'à atteindre 377. Cela indique que les 8 dernières tentatives de connexion à ce serveur ont réussi. En effet, chaque tentative réussie est marquée avec le chiffre 1 et chaque échec est marqué avec le chiffre 0. Ainsi, 2 réussites sur 2 essais donnent 11 en binaire et donc 3 en octal. 8 réussites sur 8 essais donnent 11111111 en binaire et donc 377 en octal.

D'autres commandes de ntpq permettent d'obtenir l'état des serveurs de référence de votre serveur (ex. : ntpq -c 'associations' 192.168.1.1) mais je ne vous les expliquerai pas dans ce billet. Reportez-vous au man ntpq pour obtenir plus d'informations.

Si tout est en ordre, vous êtes en mesure de synchroniser votre ordinateur avec votre routeur. Pour tester cela, utilisez la commande ntpdate . Vous devez obtenir une sortie ressemblant à celle-ci :

24 Aug 02:03:04 ntpdate[2448]: adjust time server 192.168.1.1 offset 0.002604 sec

Configuration des clients

Pour synchroniser vos clients en temps réel, je vous recommande d'utiliser ntpd/openntpd/chronyc plutôt que de créer une cron qui lancera ntpdate régulièrement pour la simple et bonne raison que ntpd permet un ajustement plus doux de l'horloge et qu'il ne consomme que très peu de ressources.

La configuration d'un client avec ntpd se fait comme nous l'avons vu : on définit le serveur sur lequel on se synchronise (le routeur), on ne répond à rien sauf aux requêtes locales et on laisse sortir les requêtes vers le routeur. En somme, on utilise un fichier ntp.conf comme celui-ci :

server 192.168.1.1 iburst prefer
 
server 127.127.1.0
fudge 127.127.1.0 stratum 10

restrict default ignore
restrict 192.168.1.1 mask 255.255.255.255 nomodify notrap nopeer noquery
restrict 127.0.0.1
 
driftfile  /etc/ntp.drift

Et on ajuste les règles du pare-feu en conséquence.

Pour aller plus loin avec NTPD

Je vais vous proposer quelques idées pour peaufiner votre installation et vous faire cogiter encore un peu ;) .

Rendre son serveur public ?

Si vous répondez aux exigences demandées, vous pouvez envisager d'ouvrir votre serveur au public. Dans ce cas-là, pensez à modifier le fichier de configuration car le "restrict default ignore", ça va pas l'faire ;) .

Vous pouvez également mettre en place de la QoS afin que votre bande passante ne soit pas entièrement consommée par des requêtes NTP.

Dans le fichier de configuration de ntpd, vous pouvez utiliser la directive "discard", qui permet d'appliquer des limites de nombre de paquets pour éviter les abus des clients. Utilisez ensuite la directive "limited" pour appliquer ces restrictions. Exemple :

discard average 3 minimum 2
restrict default notrap noquery nopeer limited

Ici, nous spécifions un espacement minimum entre les requêtes de 2 secondes et un espacement minimum moyen entre les requêtes de 8 secondes.

Attention : average est donné en log2. Ainsi, si vous voulez 8 secondes d'espacement minimum moyen entre deux paquets, vous indiquerez la valeur 3 (car log2(8) = 3). Utilisez ce convertisseur. La valeur de l'option "minimum" est donnée en secondes.

Enfin, vous pouvez activer l'envoi d'un paquet KoD (Kiss-of-Death) : il permet d'informer le client qu'il a dépassé les limites mises en place avec discard. Il doit donc cesser d'envoyer autant de paquets sinon il ne sera plus en mesure de récupérer le temps sur notre serveur. Activer cette option n'est pas nécessaire car, par défaut, les paquets qui dépassent la limite sont ignorés de toute façon. Mais informer le client permet d'avertir les clients un peu trop "speed".

Voir la documentation officielle pour plus d'informations sur discard/limited/kod.

Après, rien ne vous empêche d'ouvrir votre serveur pour vos proches/amis ou de le rendre totalement public même si vous ne pouvez pas rejoindre le pool ntp.org.

Me concernant, ma connexion ne répond pas aux exigences (ip dynamique, bande passante qui sera limite en pointe). Mon serveur restera donc privé.

Sécuriser la liaison entre votre serveur et vos clients

Il est possible de sécuriser ces échanges à l'aide de la cryptographie à clé publique ou de la cryptographie symétrique. OpenWRT propose ntpd avec le support d'OpenSSL dans le package ntpd-ssl.

Comme je ne souhaite pas cela en place sur mon LAN, je vous laisse vous débrouiller.

Devenir votre propre référence

Non, je ne suis pas fou. Si tout le monde n'a pas une horloge atomique chez soi ( :) ), certains peuvent avoir un module GPS qui se branche sur un port série ou sur un port USB. Ce module peut être utilisé comme source de temps puisque les satellites GPS contiennent des horloges atomiques qui leur permettent de rendre leur service. Le temps acquis par le module peut être diffusé par ntpd sur l'ensemble de votre réseau.

Comme je n'ai pas ce matériel sous la main, je vous laisse, là encore, vous débrouiller 8) .

Références documentaires

news
help
tour
Bear