lalahop

OpenWRT : watchdog – en voilà un bon toutou !

Table des matières

Je vous propose un court billet afin de vous familiariser avec la notion de watchdog et à son utilisation sous OpenWRT. Les personnes connaissant ce concept peuvent zapper ce billet car elles n'apprendront rien de nouveau car je ne vais pas approfondir le sujet.

Définition

Je ne saurai pas mieux expliquer le concept de watchdog que Wikipédia : Chien de garde (informatique).

Implémentation sous OpenWRT

Le watchdog n'est disponible que dans la déclinaison brcm47xx de Backfire, pas dans la brcm-2.4. Peut-être est-il disponible sous les autres versions d'OpenWRT, Kamikaze brcm-2.4 par exemple, je ne les ai pas essayées. Je ne sais pas non plus s'il est disponible sur tous les routeurs mais dans le cas d'un WRT54GL v1.1, il l'est.

Sous OpenWRT, le watchdog est fourni par busybox et il se matérialise par un fichier /dev/watchdog et un démon. Par défaut, si rien n'a été écrit durant 60 secondes dans le fichier spécial /dev/watchdog, alors le routeur redémarre. C'est pour cela que le démon watchdog doit écrire dans ce fichier pour réinitialiser le compteur. Par défaut, il le fait toutes les 5 secondes. En temps normal, seul un blocage complet du système peut empêcher l'écriture dans le watchdog pendant 60 secondes.

Le watchdog permet donc d'accroitre la stabilité du système. Si vous utilisez votre routeur à distance et qu'une fausse manipulation (ex. : lancer 2 fois tcpdump) fige le système et qu'aucun watchdog n'est présent, vous ne pourrez pas réinitialiser le système ni vous en servir. Avec le watchdog, il vous suffit d'attendre que celui-ci agisse selon le timeout défini. La problématique est la même lorsqu'un logiciel fige le système (ex. sous OpenWRT : knockd peut parfois planter le système lors de son lancement).

Il n'y a pas de fonctions supplémentaires du genre redémarrage dans le cas où la charge système devient trop importante ou bien encore redémarrage dans le cas où un processus ne tourne plus comme c'est le cas sur d'autres systèmes : Watchdog sur Gentoo Wiki Archives.

Provoquer le chien

Si vous voulez tester le watchdog, plusieurs solutions s'offrent à vous selon votre niveau de sadisme (niark niark).

Tuer le démon

Lancez la commande :

killall watchdog

et attendez 60 secondes 🙂 .

Source : Watchdog - ArmadeusWiki

Utilisez une fork bomb

Pour ceux qui ne connaissent pas le principe : Fork bomb - Wikipédia FR.

Lancez la commande

bomb() {
 bomb | bomb &
}; bomb

et attendez une minute 🙂

Source : Understanding Bash fork() bomb ~ :(){ :|:& };: - NixCraft

Écrire un code dans le watchdog

On trouve également des sites qui nous disent qu'on peut écrire des données dans le watchdog avec echo. Exemples :

Ces commandes ne fonctionnent pas. Si vous ne tuez pas le démon watchdog, vous obtiendrez une erreur "-ash: can't create /dev/watchdog: Device or resource busy" qui est tout à fait normale. Si vous tuez le démon et que vous lancez une des commandes sus-citées, vous n'obtiendrez aucun résultat. En tout cas, c'est ce que j'ai observé.

Désactiver le watchdog

Il suffit de lancer les commandes suivantes :

/etc/init.d/watchdog disable
reboot

Et si vous voulez le réactiver un jour, ce seront les commandes :

/etc/init.d/watchdog enable
reboot

Régler plus finement le watchdog

Comme nous l'avons déjà dit, le démon watchdog est minimaliste. Il suffit de lancer le démon sans argument pour se rendre compte du peu d'options disponibles :

Options:
        -T N    Reboot after N seconds if not reset (default 60)
        -t N    Reset every N seconds (default 30)
        -F      Run in foreground

Régler le timing

Par défaut, le démon réinitialise le watchdog toutes les 5 secondes et si il n'a pas été réinitialisé durant 60 secondes, le système redémarre.

Vous pouvez néanmoins changer le timing. À titre d'exemple, la commande suivante permet de réinitialiser le watchdog toutes les 2 secondes et de redémarrer le routeur si le watchdog n'a pas été réinitialisé au bout de 30 secondes :

watchdog -T 30 -t 2

Pour appliquer ce changement, cela se passe dans le fichier /etc/init.d/watchdog . Il suffit de remplacer la 7e ligne ("watchdog -t 5 /dev/watchdog") par la ligne que vous aurez décidée ("watchdog -T 30 -t 2" dans notre cas). Toujours dans notre cas, voici ce que cela donnerai (fichier /etc/init.d/watchdog) :

#!/bin/sh /etc/rc.common
# Copyright (C) 2008 OpenWrt.org
 
START=97

start() {
        [ -c /dev/watchdog ] && [ -x /sbin/watchdog ] && \
                watchdog -T 30 -t 2
}

Personnellement, je recommande de ne pas modifier les valeurs par défaut ou alors de bien les tester tant que vous avez un accès local. Cela dépend bien évidemment des usages. Vous vous demandez peut-être ce qui peut bien arriver. Voici deux exemples :

  • Mettre une valeur de réinitialisation trop haute par rapport à la valeur de redémarrage (ex. : reset = 15 et reboot = 30) car dans ce cas, un plantage temporaire provoquera le redémarrage du système. Dans mon exemple, vous conviendrez qu'il n'y a qu'un ou deux essai(s) possible(s) avant un redémarrage. Il suffit que le routeur soit débordé alors que l’écriture devait être effectuée et c'est le drame alors que si ça se trouve, le système était occupé à charger un programme gourmand et que cela aurait pris 15 secondes maximum ...
  • Mettre une valeur de redémarrage trop faible peut entrainer une boucle infinie. Supposons un logiciel qui démarre durant le processus de boot et peut parfois mettre plus de temps à démarrer (qui a dit knockd ?) sans pour autant faire planter le système durablement. Si le watchdog est trop sensible, le système redémarrera. Le chargement sera a nouveau effectué et n'aura pas le temps de se faire et on repart donc pour un redémarrage, etc. .

Avoir des fonctionnalités avancées

Si vous avez besoin de fonctions plus avancées (ex. : redémarrer en fonction de la charge ou redémarrer un processus si celui-ci n'est plus en cours d’exécution), vous pouvez les implémenter à travers des scripts. Quelques exemples (à vous de leur chercher un intérêt dans votre situation et de vérifier si le script est optimisé pour la version stable actuelle d'OpenWRT) :

Conclusion - mais que fait donc la variable nvram watchdog ?

Pour les plus attentifs, une variable watchdog (de valeur 5000 par défaut) existe dans la nvram du WRT54GL :

nvram show | grep watchdog
watchdog=5000

Je ne sais pas à quoi elle correspond et Google n'est pas bavard sur le sujet.

J'ai tenté de la descendre à 1000 (nvram set watchdog=1000 && nvram commit && reboot) en croyant qu'elle indique un temps en millisecondes puis j'ai lancé une fork bomb en ayant pris le soin de désactiver le démon watchdog avant. Résultat : il ne s'est rien passé.

J'ai tenté de passer la valeur de cette variable à 10 en me disant qu'elle représente un temps en secondes, sans trop y croire. Après avoir renouvelé l’expérience que je viens de décrire, je ne suis pas plus avancé.

Ma dernière hypothèse est qu'elle concerne le démarrage du système. Si les premières couches qui se chargent au boot plantent, il faut bien relancer le système. Je ne suis pas en mesure de tester cette hypothèse.

Si quelqu'un a une information sur ce sujet, qu'il n'hésite pas 🙂 .

Réactions

Table des matières

Je souhaite réagir à différents billets vus sur différents blogs.

La fin de l'internet illimité ?

Billet d'origine : La fin de l'internet illimité ? chez le Hollandais Volant

Je n'ai pas grand-chose à rajouter ... tout est dit. Déjà que les FAI ont perverti l'esprit initial d'internet en mettant en place un débit asymétrique entre l'émission et la réception ... La base d'internet c'était justement l'égalité entre tous. Tout le monde pouvait devenir l'hébergeur d'un service et/ou d'un contenu ... Le web 2.0 (et bientôt le cloud) a fait croire aux utilisateurs qu'ils pouvaient publier ce qu'ils voulaient, qu'ils avaient le contrôle ... vaste blague.

Ce problème d'inégalité va être aggravé par le fait que les FAI freinent le déploiement de l'IPv6. Certains abonnés vont donc se retrouver derrière un NAT géant ... Essayez de faire un serveur derrière un NAT sans pouvoir faire de DNAT.

Maintenant, on nous parle de limiter la consommation générale ou de brider certains services en fonction d'un forfait. Ça me dépasse ... Comment certaines sociétés (dans les deux sens) peuvent-elles sacrifier une des plus merveilleuses inventions de l'Humanité ?

Le combat commence. Législatif évidemment, mais aussi technique vu les députés que l'on a (on reparle d'HADOPI, de LOPPSI, de la nouvelle CNI, ... ?) ...

Les filtrages selon le protocole (pas de P2P dans ce forfait !) et/ou destination (pas de Youtube dans ce forfait !) pourront être déjoués avec des proxies, des VPN, des tunnels (HTTP, DNS, ...) mais à quel prix sur le confort d'utilisation ?

Les limitations de consommations tous azimuts pourront être contrés (avec des limites tout de même) avec des services proposant des proxies "compressants" : le client envoi un flux fortement compressé au serveur, le serveur va chercher la ressource et la retourne au client sous forme compressée. On me souffle dans l'oreille que ce principe existe déjà sur les pages web ou chez Opéra (Opéra Turbo). En effet et j'en vois une version améliorée. Néanmoins, les consommateurs de flux lourds et faiblement compressibles seront toujours pénalisés (par le temps ou la qualité). Je ne parle pas des FAI alternatifs car ils sont plus chers (avec des bonus, je ne conteste pas) et donc ceux qui n'ont pas les moyens de se payer le superforfaitdelamortkitue ne pourront pas se payer un abonnement chez un FAI alternatif. Et il y a les solutions auxquelles je n'ai même pas pensé et celles qui n'ont pas encore été inventées.

Je crois en l'humain et je crois qu'il y a toujours une solution. Pour le pire et le meilleur : ils ont voulu sanctionner l'usage illégal du P2P sans proposer de solutions viables et en utilisant des moyens douteux et contestables ? On a vu le résultat (VPN, DDL, attaque de TMG, ...). Ils ont voulu condamner la liberté d'expression (pays arabes (même si c'est la galère pour certains d'entre eux à l'heure actuelle en fonction des sacro-saints intérêts économiques), Wikileaks ou même SebSauvage), on a vu le résultat (mass mirroring rendu accessible à tous (ex. : le projet autoblog), effet Streisand/Flamby, ...) . Ils favorisent encore et toujours la finance, on verra bien le résultat ... Ils veulent limiter toujours plus la liberté d'expression ... on reparlera de l'expansion des réseaux anonymes et chiffrés qui rendront impossible l'identification des vrais criminels ...

Et quand beaucoup de gens en auront beaucoup trop marre, on passera à l'internet version 2.0 : les réseaux maillés voir des réseaux maillés avec des liens chiffrés et une sortie dans un pays dont la masse politique est plus intelligente. Tout ça sans FAI.

J'ajouterai une dernière chose : le P2P, ça arrange bien les FAI. Les majors ont voulu faire passer les gens au DDL ... forcément, les coûts ne sont pas les mêmes.

Blogotext en licence CC-BY-NC

Hé oui, je me réveille : depuis le 12/05/2011, Blogotext est diffusé sous licence CC-BY-NC. Adieu la terrible clause ND. Je ne peux que féliciter le Hollandais Volant. A quand la suppression de la clause NC ? 🙂

Nous utilisons Linux pour le fun

Billet d'origine : « We use Linux because it's fun » chez le Hollandais Volant

Si je me contente de dire "+ 1", vous ne m'en voudrez pas ?

La GNU GPL, ça pue, c'est pas assez libre !

Billet d'origine : Les licences : GPL vs LGPL chez Migwel.

Si je suis d'accord sur l'argument avancé (la liberté c'est de laisser le choix à ceux qui utilisent notre composant logiciel de faire du libre ou pas), je souhaite quand même atténuer les reproches faits à la GPL.

D'abord il faut rappeler le contexte de sa création : de ce que j'en sais, les débuts de l'informatique étaient placés sous le signe du libre échange. Tout s’échangeait. Puis arrive l'époque ou certains refusent de partager pour des intérêts économiques. RMS, mais d'autres devaient partager ses pensées, a réagit, comme d'habitude, à l’extrême, en imposant le partage. Ceux qui veulent partager doivent le faire à fond, sans compromis possible. Pour moi, la montée en puissance des logiciels privateurs justifiait l'emploi d'une telle licence.

Ensuite, il faut revenir dans le contexte actuel : a-t-on besoin d'une licence virale de nos jours ? Oui, oui et encore oui. Je pense que rien n'a changé en 22 ans et qu'on en est toujours au même point : les intérêts économiques avant tout ... mais avec des modèles économiques dépassés ... forcement ça ne passe pas. Je ne parle même pas du manque de reconnaissance.

Enfin, la liberté, c'est aussi la possibilité de faire un choix et de l'assumer. De ce fait, si vous n'aimez pas le principe de la GNU GPL, vous pouvez choisir une licence qui sera plus en accord avec vos principes éthiques et moraux : BSD, MIT, WTFPL, ....

J'espère qu'on s'est bien compris : je n'attaque pas ceux qui critique négativement la GNU GPL et je ne leur demande pas de se taire, je dis juste qu'il est vain d’espérer un changement de cette licence qui a été prévue comme cela à l'origine et qui trouve encore aujourd'hui une raison d'être dans nos sociétés.

Un des plus beaux jours de ma vie sera le jour où la GNU GPL perdra de sa valeur car plus nécessaire.

Sans rapport mais tant que j'y suis : je vois beaucoup de gens parler de la Do What The Fuck You Want To Public License et autres. Il faut faire attention aux licences dont la valeur n'a pas encore été reconnue sur le territoire national (dans mon cas : la France). Celle de la GNU GPL l'est.

L'élitisme c'est le maaaal

Billet d'origine : OMG, je viens de me faire clasher par ma boulangère ! chez Mange ta main.

Comme lui, je me confesse : oui, j'ai été coupable ! Mais je le suis encore. Et je continuerai à l'être ! Tout comme la GNU GPL, l'élitisme peut se justifier. Un exemple tout bête : si des élitistes qui m'ont un jour pris pour un con viennent me demander quelque chose dans mes domaines de compétence, qu'ils ne s'attendent pas à obtenir une réponse correcte : je ferais comme eux, à savoir : "tu ne connais pas ?", "non, tu n'emploies pas le bon terme", "tu ne sais pas ce qu'est le support NFS par Firewall IP de masquerading Ethernet en double filtrage coaxial sur ICMP ?? Putain de grosse lame" (source : tRoU dU cULz hiDEoUt) ... Chacun son tour ...

Par contre, pour le reste des gens, je continuerai à partager sans problème mes connaissances et sans les prendre pour des cons. Le seul intérêt du savoir et du monde des idées, c'est de les partager. C'est d'ailleurs la raison d'être de ce blog. Je ne vous connais pas et si ça se trouve, vous être un élitiste et je m'en moque tant que je ne le sais pas. Je me répète mais le savoir doit être partagé uniquement entre les gens qui comprennent la valeur de ce partage.

Commentaires ou pas ?

Le débat fait rage :
Au revoir les comms. chez Korben
Edito du 02/08/2011 chez Korben
No comments chez SebSauvage
Vous savez pas vous tenir ? chez le Hollandais Volant

Tout a été dit donc je ne rajouterai rien. Ha si, deux choses : les échanges entre individus sont capitaux pour se forger une opinion, apporter des corrections, ... Les commentaires permettent cet échange. Néanmoins, si cela doit se passer dans de mauvaises conditions, autant ne pas échanger. On en revient donc à un problème similaire à celui de l'élitisme évoqué ci-dessus. Si ça devait arriver ici, je serais sans pitié : adieu les commentaires et pour toujours.

Le reste

Je zappe les pseudo actualités à la con : Depardieu qui pisse dans un avion je m'en fout, il y a plus important dans le monde. Le risque de canicule, qu'on informe les gens ok. Qu'on ne parle que de ça, ça me soule : il y a d'autres sujets plus importants (au choix : Libye, Syrie, Botzaris36, vraie finance (pas juste me dire que tout va bien), ...).

Je m'exprime rarement sur l'actualité mais ce n'est pas pour ça que je m'en moque et que je reste passif, bien au contraire (j'avais écrit aux députés de ma région concernant HADOPI, LOPPSI, ACTA, j'avais organisé des discutions dans ma ville afin d'informer les gens sur ces mêmes lois, idem pour la monté de la société de surveillance ...). Si je n'écris rien sur ce blog, c'est que, d'une part, je trouve que d'autres ont déjà écris sur ces sujets mieux que je ne pourrais le faire. Et, d'autre part, j'aime prendre un peu de recul avec l'actualité, histoire, entre autres, de contrer les effets d'annonce qui servent de guides aux politiques.

OpenWRT : sécuriser l’accès SSH

Table des matières

Dans ce billet, je vais vous parler de plusieurs méthodes pour améliorer la sécurité de votre accès SSH à votre routeur sous OpenWRT. Un deuxième objectif sera d'éviter au maximum les attaques par bruteforce. Bien qu'elles soient sans espoir avec un mot de passe bien choisi, elles consomment un peu des ressources (processeur et bande passante) et ça m'énerve. Nous verrons quatre méthodes au total. Il est bien entendu qu'il est inutile de combiner toutes les méthodes. Néanmoins, certaines peuvent être combinées (ex. : 3 et 4 ou 1 et 2 ou ...). Évidemment, tout ceci est inutile si vous n'utilisez pas SSH en dehors de votre LAN.

Un changement du port d'écoute et une règle iptables

J'ai déjà présenté une règle iptables permettant de limiter l’impact d'une attaque par bruteforce sur le démon SSH dans ce billet : Adieu DG834G, bonjour WRT54GL et OpenWRT

Pour rappel, voici ce que j'écrivais :
Je change le port sur lequel écoute dropbear (démon SSH). Pour cela, il faut éditer le fichier /etc/config/dropbear en changeant la ligne « Port ».

Ensuite, j’ouvre le port, dans iptables, pour qu’il soit accessible depuis internet et je protège le service contre une attaque par brute force. Pour faire cela, il faut éditer le fichier /etc/firewall.user avec vi, par exemple, et ajouter :

iptables -A input_wan -p tcp --dport 7523 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --update --seconds 600 --hitcount 2 -j DROP
iptables -A input_wan -p tcp --dport 7523 -m state --state NEW -m recent --name ATTACKER_SSH --rsource --set
iptables -A input_wan -p tcp --dport 7523 -m state --state NEW -j ACCEPT

Notes :

  • 7523 est le port d'écoute choisi.
  • Ce code est inspiré de celui fourni sur le wiki officiel mais lui fonctionne, au moins 😉 .
  • Ce code nécessite que les packages iptables-mod-conntrack-extra et kmod-ipt-conntrack-extra soient installés. Ils ne le sont pas par défaut.

Explication rapide : L’attaquant sera donc bloqué pendant 10 minutes après 2 connexions (qui permettent chacune d’essayer 10 mots de passe). On ne peut pas plus réduire le nombre de connexions. Si vous mettez 1, vous ne devrez jamais vous tromper quand vous tapez le login. Car dans ce cas, vous devrez quitter la session et en recommencer une mais vous serez alors bloqué pendant 10 minutes. Évidemment, cela s’applique uniquement aux paquets venant d’internet, pas du LAN.

Malheureusement, il n'est pas toujours possible de changer le port d'écoute : certains réseaux vérifient les ports utilisés dans le trafic sortant, voir plus (reverse-proxy ...) et vous ne pourrez donc pas accéder à votre routeur depuis ces réseaux. Mais n'oubliez pas qu'il reste beaucoup de ports ouverts et qui ne sont que rarement contrôlés par de reverse proxy ou des règles qui matchent le contenu des paquets. À ce sujet, privilégiez les ports qui utilisent un protocole de chiffrement (ex : SSH, HTTPS, POPS, IMAPS, SMTPS, ports VPN, ports IPSEC, ...). De plus, Dropbear, le démon SSH utilisé par OpenWRT permet d'essayer 10 mots de passe par connexions. Ce qui fait qu'ici, un bot aura le droit d'essayer 20 mots de passe par session.

Bon, vous me direz que 20 essais toutes les 10 minutes, ce n'est rien comparé à un mot de passe de 12 caractères chiffres, lettre minuscules, majuscules et caractères spéciaux ne représentant pas une séquence connue (ex. : azertyuiop75) ni un mot du dictionnaire. Sachant que, d’après mes observations, les bot bloqués ne reviennent pas au bout de 10 minutes mais au bout de 24H, cela fait donc 20 essais de mot de passe par jour. Autant dire : rien. Et je ne parle pas des bots qui sont seulement capables de tester un mot de passe par connexion. Ceux-là essayent donc 2 mots de passe par jour. Néanmoins, comme je l'ai déjà dit ces tentatives, même vouées à l'échec, m'énervent.

Compiler dropbear pour n'autoriser que 3 essais de mot de passe par connexion

Édit du 25/08/2011 à 2h40 :
Attention : J'ai oublié de préciser que ce point vous concerne même si vous utilisez l'authentification à clé publique. En effet, même si vous n'avez pas besoin de limiter le nombre d'essais de mot de passe, il peut être intéressant de limiter la durée pendant laquelle l'authentification est possible, de limiter le nombre de d'utilisateurs non authentifiés simultanés ou bien encore de limiter la taille du binaire.
Fin de l'édit

Ici, les manières de procéder sont diverses. La plus adaptée serait d'utiliser le SDK d'OpenWRT puisque nous voulons compiler uniquement un seul paquet. Néanmoins, celui-ci n'est pas disponible pour Backfire 10.03. Certains internautes du forum officiel d'OpenWRT utilisent le SDK de la version Kamikaze au prix d'une petite bidouille d'opkg par la suite. Nous n'allons donc pas employer cette méthode mais nous allons utiliser buildroot, une série de scripts qui permet de compiler facilement un système embarqué avec Linux comme noyau et qui est utilisé par OpenWRT, pour compiler dropbear.

Pour rappel : le SDK ou l'image builder, sont des composants du buildroot. Ils peuvent donc être remplacés ou compilés par buildroot (voir make menuconfig).

Préparer votre GNU/Linux Debian Squeeze pour buildroot

Il faut installer un certain nombre de paquets :

# 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

Source : OpenWrt Buildroot – Installation. Le reste des paquets seront installés via le jeu des dépendances.

C'est l'heure d'aller se chercher un premier café ! 😉

Récupérer les sources

Nous allons récupérer les sources stables de la version Backfire 10.03 :

~$ svn co svn://svn.openwrt.org/openwrt/tags/backfire_10.03

S'assurer que toutes les dépendances sont satisfaites

~$ cd backfire_10.03
~/backfire_10.03$ make defconfig
~/backfire_10.03$ make prereq

Modifier le Makefile de dropbear afin d'accroitre la sécurité

Ouvrez le Makefile spécifique à dropbear (./package/dropbear). Dans la rubrique "Build/Configure", constatez que certains fichiers sources sont modifiés avant compilation. Il s'agit notamment du fichier options.h que l'auteur de dropbear nous conseille (via le fichier README des sources) d'ailleurs de consulter afin de personnaliser notre installation. C'est ce que j'ai fait et je vous livre ici les modifications utiles que j’ai trouvées. Signalons au passage la présence de nombreux commentaires, dans le code, qui aide à faire des choix. Rien ne vous empêche donc de vérifier que je n'ai rien oublié 😉 .

Voici donc les lignes que nous allons rajouter dans la rubrique "Build/Configure du Makefile" :

$(SED) 's,^#define AUTH_TIMEOUT 300,#define AUTH_TIMEOUT 60,g' $(PKG_BUILD_DIR)/sysoptions.h
$(SED) 's,^#define MAX_UNAUTH_PER_IP 5,#define MAX_UNAUTH_PER_IP 2,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define MAX_UNAUTH_CLIENTS 30,#define MAX_UNAUTH_CLIENTS 2,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define MAX_AUTH_TRIES 10,#define MAX_AUTH_TRIES 3,g' $(PKG_BUILD_DIR)/options.h

Explications simplifiées :

  • La première ligne passe le délai pour s'authentifier de 5 minutes à 1 minute. Il ne faut tout de même pas 5 minutes pour taper un mot de passe !
  • La deuxième et la troisième ligne réduisent le nombre de clients non authentifiés qui peuvent se connecter simultanément.
  • La dernière ligne passe le nombre d'essais de mot de passe de 10 à 3 pour une session.

Évidemment, ces options, et notamment celle pour le nombre de clients non authentifiés simultanés, doivent être adapter à votre situation (nombre d'utilisateurs, ...).

Modifier le Makefile de dropbear afin d'optimiser l'espace occupé par le programme

Tant que nous y sommes, nous allons désactiver les fonctions dont nous ne nous servirons pas afin que le binaire généré occupe moins d'espace sur la flash du routeur. Par la même occasion, nous augmentons la sécurité du démon (moins de code donc moins de bugs/failles possibles).

Sachez que le développeur de dropbear donne des conseils pour que dropbear occupe moins d'espace dans le fichier SMALL des sources. Je vous cite le contenu de ce fichier, ci-dessous, pour information :

Tips for a small system:

If you only want server functionality (for example), compile with
make PROGRAMS=dropbear
rather than just
make dropbear
so that client functionality in shared portions of Dropbear won't be included.
The same applies if you are compiling just a client.

---

The following are set in options.h:

- You can safely disable blowfish and twofish ciphers, and MD5 hmac, without
affecting interoperability

- If you're compiling statically, you can turn off host lookups

- You can disable either password or public-key authentication, though note
that the IETF draft states that pubkey authentication is required.

- Similarly with DSS and RSA, you can disable one of these if you know that

all clients will be able to support a particular one. The IETF draft
states that DSS is required, however you may prefer to use RSA.
DON'T disable either of these on systems where you aren't 100% sure about
who will be connecting and what clients they will be using.

- Disabling the MOTD code and SFTP-SERVER may save a small amount of codesize

- You can disable x11, tcp and agent forwarding as desired. None of these are

essential, although agent-forwarding is often useful even on firewall boxes.

---

If you are compiling statically, you may want to disable zlib, as it will use
a few tens of kB of binary-size (./configure --disable-zlib).

You can create a combined binary, see the file MULTI, which will put all
the functions into one binary, avoiding repeated code.

If you're compiling with gcc, you might want to look at gcc's options for
stripping unused code. The relevant vars to set before configure are:

LDFLAGS=-Wl,--gc-sections
CFLAGS="-ffunction-sections -fdata-sections"

You can also experiment with optimisation flags such as -Os, note that in some
cases these flags actually seem to increase size, so experiment before
deciding.

Of course using small C libraries such as uClibc and dietlibc can also help.

If you have any queries, mail me and I'll see if I can help.

Nous allons suivre le dernier conseil : utiliser les options de gcc pour dégager le code inutilisé. Pour cela, ajoutez les deux lignes données en haut de la rubrique Build/Compile du Makefile de dropbear. Comme cela :

define Build/Compile
	LDFLAGS=-Wl,--gc-sections
	CFLAGS="-ffunction-sections -fdata-sections"	
	$(MAKE) -C $(PKG_BUILD_DIR) \
		$(TARGET_CONFIGURE_OPTS) \
		LD="$(TARGET_CC)" \
		PROGRAMS="dropbear dbclient dropbearkey scp" \
		MULTI=1 SCPPROGRESS=1

	$(MAKE) -C $(PKG_BUILD_DIR) \
		$(TARGET_CONFIGURE_OPTS) \
		LD="$(TARGET_CC)" \
		PROGRAMS="dropbearconvert"

endef

Nous allons maintenant suivre les conseils précédents en rajoutant les lignes suivantes dans la rubrique "Build/Configure" du Makefile :

$(SED) 's,^#define INETD_MODE,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DO_MOTD,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define SFTPSERVER_PATH "/usr/libexec/sftp-server",/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define ENABLE_X11FWD,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_BLOWFISH,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_TWOFISH256,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_TWOFISH128,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_3DES,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_AES128,/* & */,g' $(PKG_BUILD_DIR)/options.h
$(SED) 's,^#define DROPBEAR_MD5_HMAC,/* & */,g' $(PKG_BUILD_DIR)/options.h

Explications :

  • La première ligne demande à dropbear de ne pas être lancé par un quelconque démon réseau mais de toujours se lancer en standalone. Le mode inetd est inutile sur OpenWRT qui ne possède pas ce genre de démon.
  • La deuxième ligne désactive le message du jour. Le fichier /etc/banner nous suffira pour afficher un message.
  • La troisième ligne désactive le support d'un serveur SFTP. Nous avons déjà SCP pour copier des fichiers de manière sécurisée.
  • La quatrième ligne désactive le X11 forwarding. Par défaut, il n'y a pas d'environnement graphique accessible via SSH sur OpenWRT et nous n'en voulons pas. Autant gagner de la place en désactivant cette fonctionnalité.
  • Les autres lignes désactivent les algorithmes de chiffrage/hachage les plus faibles (bien qu'ils ne soient pas "non sécurisés"). Seuls l'algorithme de chiffrement symétrique AES 256 et les fonctions de hachage SHA1_HMAC et SHA1_96_HMAC resteront.

L'auteur de dropbear nous conseille aussi de désactiver le port forwarding et l'agent forwarding. Dans mon cas, ceux-ci me seront utiles donc je ne les désactive pas. Enfin, il nous conseille de désactiver l'authentification par mot de passe ou celle par clé publique. Vu le lien entre désactivation de telnet et changement du mot de passe de root sous OpenWRT, je ne préfère pas désactiver l'authentification par mot de passe dans le code mais plutôt dans le fichier de configuration de dropbear, une fois que j'aura importer ma clé publique dans le routeur. J'ai également conservé les deux algorithmes liés à l'authentification par clé publique, RSA et DSA car il m'arrive d'utiliser l'un ou l'autre.

Les autres options possibles (désactiver la résolution des IP en nom de domaine et créer un binaire qui combine le serveur et le client) sont déjà activées par OpenWRT : c'est l'objet des deux premières lignes de la rubrique Build/Configure.

Compiler le nouveau dropbear

Avant de compiler quoi que ce soit, fermez puis rouvrez votre session. Si vous ne le faites pas, vous aurez des erreurs sans queue ni tête (CDPATH ...). Ceci n'est à faire que la première fois, à la suite de l'installation des paquets prérequis. Certainement un problème de variables d'environnement mais je n'ai pas plus d'informations.

Quelles que soient les modifications que vous effectuez sur le Makefile, pensez à incrémenter la variable "PKG_RELEASE" de celui-ci avant de lancer la compilation. C'est une bonne pratique à prendre et ça évite des erreurs.

Vous ne pouvez pas compiler un seul paquet sans avoir compilé le toolchain d'abord. Nous allons utiliser la commande suivante afin d'avoir une interface semi-graphique nous permettant de régler les options de la compilation :

~/backfire_10.03$ make menuconfig

Dans "Target system", nous choisirons "Broadcom BCM947xx/953xx" qui correspond à la déclinaison brcm47xx. Vous pouvez choisir la déclinaison brcm2.4 ("Broadcom BCM947xx/953xx [2.4]"). Votre choix n'affectera que très peu la suite de ce billet, tout au plus quelques chemin/noms de fichiers qui changeront.

À noter que les binaires des deux branches (brcm47xx et brcm2.4) sont compatibles. En tout cas, c'est ce que j'ai pu constater.

Nous ne toucherons à rien dans "Target profile". Ni dans "Target images" ni dans" Global build settings" ni dans "Advanced configuration options" ni dans "Image configuration". Nous ne nous occuperons pas non plus des options qui permettent de compiler les trucs spécifiques (SDK, toolchain, image builder). Et dans les rubriques qui restent, nous décocherons tout (touche "n") sauf dropbear. Cela dans le but d’alléger le téléchargement et la compilation des sources.

Ensuite, lançons la compilation avec la commande :

~/backfire_10.03$ make

Si une erreur survient, vous pourrez tentez de debugger la compilation en la relançant avec le paramètre "V=99", comme cela :

~/backfire_10.03$ make V=99

Si vous compilez sur un processeur multicoeur, vous pouvez exploiter au mieux la puissance de celui-ci en utilisant le parametre "-j <nombre de coeur + 1>". Exemple pour un processeur quad core :

~/backfire_10.03$ make -j 5

Le système va télécharger les sources du toolchain et le compiler. Puis il téléchargera les sources de dropbear, les modifiera et les compilera. Enfin, il fabriquera le package ipkg de dropbear ainsi que les images des firmwares au format squashfs.

C'est le moment d'aller se chercher un deuxième café voir plus 😉 .

À la fin de la compilation, vous retrouverez le package de dropbear dans le dossier ./bin/brcm47xx/package.

Si jamais vous effectué des modifications, vous n'aurez pas besoin de tout recompiler : il vous suffira d'incrémenter la variable "PKG_RELEASE" présente dans le Makefile de dropbear et de lancer la commande suivante :

~/backfire_10.03$ make package/dropbear/compile

Les options précédemment évoquées ("-j" et "V=99" restent réutilisables).

Remplacer le binaire sur votre routeur

Ici, plusieurs méthodes sont encore possibles. Nous en exposerons deux.

Utiliser opkg

Il suffit de transférer le package sur le routeur avec la commande :

~/backfire_10.03$ scp ./bin/brcm47xx/packages/dropbear_0.52-5_brcm47xx.ipk root@192.168.1.1:/tmp

Puis de se connecter en SSH sur le routeur et d'y installer le package :

root@OpenWrt:~# opkg install /tmp/dropbear_0.52-5_brcm47xx.ipk

Vous n'avez plus qu'à relancer le serveur :

root@OpenWrt:~# /etc/init.d/dropbear restart

Cela devrait suffire mais, par prudence, je préfère rebooter le routeur.

Remplacer directement le binaire

Le package ipkg n'est qu'un fichier compressé avec gzip comme nous en informe la commande file :

file ./bin/brcm47xx/packages/dropbear_0.52-5_brcm47xx.ipk
./bin/brcm47xx/packages/dropbear_0.52-5_brcm47xx.ipk: gzip compressed data, from Unix, last modified: Sat Aug 13 15:34:30 2011

Il suffit donc de le décompresser :

~/backfire_10.03$ mkdir dropbear_uncompress && cd dropbear_uncompress
~/backfire_10.03/dropbear_uncompress$ tar -xf ../bin/brcm47xx/packages/dropbear_0.52-5_brcm47xx.ipk

Puis de décompresser le fichier data.tar.gz :

~/backfire_10.03/dropbear_uncompress$ tar -xf data.tar.gz

Votre binaire se trouve donc dans le dossier ~/backfire_10.03/dropbear_uncompress/usr/sbin. Il vous suffit de le transférer en utilisant SCP :

~/backfire_10.03/dropbear_uncompress$ scp ./usr/sbin/dropbear root@192.168.1.1:/tmp

Il ne vous reste plus qu'à remplacer le binaire en vous connectant par ssh :

root@OpenWrt:~# mv /tmp/dropbear /usr/sbin/dropbear
root@OpenWrt:~# chmod ugo+x /usr/sbin/dropbear

La deuxième ligne sert à rendre le binaire exécutable pour tout le monde. C'est les droits qui sont définis sur le fichier d'origine.

Vous n'avez plus qu'à relancer le serveur :

root@OpenWrt:~# /etc/init.d/dropbear restart

Cela devrait suffire mais, par prudence, je préfère rebooter le routeur.

Si vous venez de réussir votre première compilation croisée en suivant ces explications, félicitations 😀 .

Intégrer notre dropbear modifié dans une image de firmware au format squashfs (= créer un firmware personnalisé)

Cela permet de ne pas avoir à réinstaller votre version modifiée de dropbear (en supposant que vous ayez gardé le binaire que vous avez compilé) lorsque vous réinstallez le firmware suite à une erreur trop importante. Nous évoquerons ce point dans un prochain billet. Néanmoins, pour ceux qui veulent avoir un aperçu : Fonera 2 : Personnaliser, compiler, régénérer OpenWRT sur KubuntuBlog.

Néanmoins, la recompilation de dropbear n'est toujours pas suffisante. Combinée à la première solution, elle permet de réduire à 3 le nombre d'essais de mot de passe par connexion. Donc, 6 essais par jour pour les meilleurs bots (et toujours 2mdp/jour pour les plus mauvais). C'est toujours mieux que 20 mais ces 6 essais consomment toujours des ressources inutiles et m'énervent toujours.

Utiliser le port knocking

Présentation du concept

Encore un concept logiciel qui, à l’instar des sémaphores/jetons, prouve qu'on n’invente rien en informatique : on s'inspire de la réalité. Qui n'a jamais joué à l'espion avec un toc-toc secret pour rentrer dans le QG durant son enfance ? 😀 Comment ça je suis seul ? 😮 Menteurs !

Si vous ne savez pas ce qu'est le port knocking, voir : port knocking sur Wikipedia en.

Le port knocking est une technique que je connais depuis pas mal de temps mais que je n'avais jamais mis en pratique. Par contre, ce que je ne savais pas, c'est que le concept avait évolué pour être plus sécurisé : on a maintenant le Single Packet Authorization qui permet de transmettre la séquence de manière chiffrée. Cela empêche une attaque de l'homme du milieu qu'il est possible de faire avec un port knocking classique. A savoir aussi, une adaptation du port knocking peut également servir à dissimuler un point d’accès WiFi beaucoup plus efficacement que par le simple fait de cacher le SSID. Pour plus d'informations à ce sujet, voir : Sécuriser un réseau WiFi avec Wknock (Laurent Oudot - Blackhat 2005) - secuobs.com.

Bien que l'auteur de knockd s'en défendent, je vois le port knocking comme une sécurité par l'obscurité : on masque les ports en espérant que personne ne voit la porte d'entrée derrière le voile. C'est pour cela qu'il ne faut pas se reposer uniquement sur un logiciel de port knocking. Mais ces logiciels peuvent être utiles pour rajouter une couche de protection (et donc de failles (rappelez-vous : un logiciel sans bugs/failles est un logiciel insuffisamment testé)).

Quoi qu'il en soit, seuls les paquets wknock et knockd sont disponibles en package pré-compilés pour OpenWRT. Nous ne verrons donc pas de Single Packet Authorization à moins que quelqu'un compile le paquet pour OpenWRT, bien entendu. Pour ceux qui se le demande, knockd est évidemment sous licence libre (GNU GPL).

Édit du 25/08/2011 à 2h35 :
Attention : knockd a tendance à faire planter mon routeur lors de son démarrage. Cela arrive environ 3 fois sur 4. Cela peut être énervant donc je préfère vous prévenir. Je ne me suis pas penché sur l'origine de ce problème. Mais ne vous inquiétez pas, si vous utilisez la déclinaison brcm47xx, le watchdog se chargera de redémarrer le système pour arrêter le plantage. Mais cela prend un peu de temps (par défaut : 1 minute + le temps du boot).
Fin de l'édit

Installation

Vous devriez être habitué maintenant :

opkg update && opkg install knockd

Configuration de knockd

La configuration s'effectue depuis le fichier /etc/knockd.conf. Voici le contenu que je vous propose :

[options]
	UseSyslog
	interface	= eth0.1
 
[opencloseSSH]
	sequence		= 2222:tcp,3333:udp,4444:tcp
	seq_timeout		= 2
	tcpflags		= syn,ack
	command			= /usr/sbin/iptables -t filter -I INPUT -i eth0.1 -s %IP% -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT
	cmd_timeout		= 5
	stop_command		= /usr/sbin/iptables -t filter -D INPUT -i eth0.1 -s %IP% -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags SYN,RST,ACK SYN -j ACCEPT

Explications :

  • UseSyslog permet d'envoyer le journal (les tentatives) au démon syslog. Cela permet donc de grouper le journal de knockd avec les autres journaux du système, ce qui les rend plus faciles à lire et à exporter. Si vous préférez écrire le journal de knockd dans un autre fichier, utilisez la directive "logfile". À noter que rien ne vous empêche d'utiliser les deux méthodes d'enregistrement du journal en même temps.
  • interface permet de spécifier l'interface sur laquelle knockd doit écouter. Par défaut, il tente d'écouter sur toutes les interfaces et bloque sur eth0 avec le message d'erreur suivant : "could not get IP address for eth0". Ce qui est normal puisque eth0 ne peut pas être utilisé directement mais par le biais d'eth0.1 ou de br-lan puisqu'elle fait partie d'un bridge.
  • [opencloseSSH] permet de définir un service. Mettez le nom que vous voulez.Évidemment, vous pouvez définir plusieurs services, avec des séquences différentes.
  • sequence permet de définir les ports auxquels nous frapperons et dans quel ordre nous les frapperons. Comme vous le constatez, vous pouvez mixer des ports tcp et udp. Vous pouvez également mettre le nombre de ports que vous souhaitez. Je vous conseille vivement de mettre une combinaison plus robuste que celle de cet exemple.
  • seq_timeout définit le délai après lequel la séquence est abandonnée si elle n’a pas été menée à terme. Vous devriez la régler en fonction de l'activité réseau de votre routeur. En effet, s’il y a trop d'activité, les paquets du knock pourraient être dispersés et traiter trop tard.
  • tcpflags permet de spécifier à knockd de ne prêter attention qu'aux paquets marqués avec les drapeaux définis.
  • command est la commande qui sera lancée lors de la réussite du knock. Ici, elle ouvre le port SSH, seulement pour l'IP ayant réussi le knock. Si votre routeur à une IP fixe sur l’interface WAN, vous pouvez rendre la règle plus spécifique en ajoutant le paramètre "-d <ip_wan>".
  • cmd_timeout est le temps après lequel le knock n'est plus considéré comme étant valide. Ici, il faut juste spécifier assez de temps pour lancer une connexion sur le port ouvert par le knock.
  • stop_command est, bien entendu, la commande qui sera exécutée dès que le knock ne sera plus valide. Ici, elle ferme le port.

Note : j'ai honteusement pompé et adapté ce fichier de configuration depuis le man knockd.

Configuration d'iptables

Regardons la règle qui nous ouvre le port SSH : elle accepte une nouvelle connexion dans l'état NEW, en provenance d'une machine bien définie, à destination du port tcp/22 du routeur à condition que le paquet provienne de l'interface WAN. Cela signifie que les paquets suivants seront ignorés et donc la connexion perdue. Évidemment, nous considérons que la politique par défaut de la chaine INPUT est DROP. De plus, après le timeout, knockd refermera cette porte d'entrée.

Il faut donc ajouter une règle dans la chaine INPUT qui autorise les connexions établies et à destination du port tcp/22 du routeur :

iptables -t filter -I INPUT -i eth0.1 -p tcp -m state --state ESTABLISHED -m tcp --dport 22 -j ACCEPT

Même combat si vous filtrer les sorties (ce qui est une bonne pratique) : il faudra créer, dans la chaine OUTPUT, une règle qui accepte les connexions établies provenant du port tcp/22 du routeur et qui sont à destination de l'interface WAN :

iptables -t filter -I OUTPUT -o eth0.1 -p tcp -m state --state ESTABLISHED -m tcp --sport 22 -j ACCEPT

Je suis au courant que mes règles ne respectent pas les chaînes introduites par OpenWRT. Mais, n'utilisant plus ces chaines, je vous mets les chaines par défaut plutôt que de vous imposer les miennes. Libre à vous de les remplacer pour convenir à votre configuration.

Script d'init

Nous allons créer un script d'init (sous /etc/init.d). Ces scripts sont toujours pratiques pour relancer rapidement un démon (/etc/init.d/knockd restart est quand même plus pratique que les commandes kill `pidof knockd|sed "s/$$//g"` + knockd -d & ou équivalents). OpenWRT n'en intègre pas pour l'instant pour knockd. Néanmoins, nous ne créerons pas de lien symbolique vers ce script dans le répertoire /etc/rc.d/ afin que knockd ne soit pas lancé deux fois de suite (voir ci-dessous).

Voilà le script que je vous propose (/etc/init.d/knockd) :

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

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

DAEMON=/usr/sbin/knockd
NAME=knockd
DESC="Port knocking"
 
start() {

	echo "Starting $DESC: $NAME"
	logger Starting $DESC: $NAME
	`$DAEMON -d &`

}
 
stop() {
	echo "Stopping $NAME"
	logger Stopping $NAME
	kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1

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

	start
}

J'ai pompé et adapté ce script sur celui fourni par/pour dnscache.

Si vous avez configurer knockd pour utiliser syslogd, alors les commandes logger, qui, pour rappel, permettent d'enregistrer un message dans les logs du système, ne sont pas utiles puisque knockd écrira de lui-même des messages lors de ses démarrages/arrêts.

Il faudra penser à rendre ce script exécutable :

chmod ugo+x /etc/init.d/knockd

Démarrage automatique

Tout comme dnscache, knockd est inefficace après une déconnexion qui surviendrait sur l'interface WAN. Nous allons donc créer un script pour hotplugd. Pour ceux qui ne comprennent pas, voir le billet sus-linké.

C'est pour cela que l'on ne devait pas faire de lien symbolique vers /etc/init.d/knockd dans /etc/rc.d toute à l'heure : hotplud lancera knockd automatiquement au démarrage de la machine, pas besoin de le lancer une deuxième fois par erreur (voir le billet sus-linké pour des explications détaillées).

Voici donc le script pour hotplugd que je vous propose (/etc/hotplug.d/iface/30-dknock) :

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

then
	KNOCKD_RUNNING=`ps  | grep knockd | grep -v grep`

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

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

	esac
fi

Ouvrir le port ssh sur un client GNU/linux Debian

Il faut installer le logiciel knock :

# apt-get install knockd

Puis, lorsque vous voudrez vous connecter en SSH à votre routeur, il faudra exécuter la commande :

$ knock <séquence> && ssh root@OpenWRT

Par exemple, pour l'exemple configuré ci-dessus, il faudrait exécuter :

$ knock 2222 3333:udp 4444 && ssh root@OpenWRT

Pour aller plus loin

C'est ici que je m'arrête : je pense que la configuration actuelle de knockd couplée à l'utilisation d'une authentification par clé publique/privée suffira à protéger mon accès ssh. De plus knockd empêchera les attaques par bruteforce. Et si un jour la séquence est découverte, vous en serez informé dans les logs (= vous verrez les tentatives de connexions frauduleuses au démon SSH) et vous pourrez la changer.

Mais si vous voulez plus de sécurité, vous pouvez utiliser la fonctionnalité one time sequence de knockd. Il s'agit d'un fichier qui contient autant de séquences que vous voulez. Chaque fois qu'une séquence est validée, elle n'est plus acceptée. Ainsi, une séquence n'est valable qu'une seule fois (sauf exceptions). Voir l'exemple dans le man knockd. Pour vous simplifier l'utilisation de cette fonctionnalité, je vous conseille l'utilisation des knockd-utils (GNU GPL). Rien ne vous empêche dès lors d'imaginer une cron qui génère régulièrement un fichier de séquence sur l'ordinateur depuis lequel vous souhaitez accéder à votre routeur puis qui vous en stocke un exemplaire dans votre home et qui en upload une copie, via scp, sur votre routeur et relance le démon knockd pour qu'il prenne en compte ce fichier.

Rien ne vous empêche également de porter, sur OpenWRT, un démon qui fait de l'encrypted port knocking tels que fwknop (GNU GPL) ou cryptknock (flou sur la licence mais sources disponibles).

Authentification par clé publique/clé privée

C'est une fonctionnalité de base de SSH et elle permet d'éviter de la manière la plus simple du monde le problème du bruteforçage de votre mot de passe. On n'utilise plus un mot de passe mais une clé privée et une clé publique. Cette méthode permet, via les agent ssh de s'authentifier en toute sécurité sans
pour autant saisir un mot de passe à longueur de journée. Elle permet également l'automatisation de tâches (puisque la connexion ne requiert plus de mot de passe). On peut même faire de l'administration à travers plusieurs machines (voir : ssh agent forwarding).

Je ne vous expliquerai pas comment mettre en place une telle authentification puisque les gars d'openWRT l'ont déjà fait : Dropbear Public Key Authentication - OpenWRT Wiki. Si vous êtes un peu perdu, je vous conseille cette lecture : La connexion sécurisée à distance avec SSH - Site du Zéro.

Je préciserai juste que vous pouvez très bien utiliser des clés RSA d'une longueur supérieure à 1024 bits (ex. : 2048 bits). Il suffit d'utiliser un paramètre supplémentaire lors de la génération :

ssh-keygen -t rsa -b 2048

Les clés DSA doivent en revanche, avoir une longueur strictement égale à 1024 bits pour respecter le FIPS 186-2.

Si vous générer votre clé depuis puttygen, n'oubliez pas de copier le début (ex. : "ssh-rsa") sinon cela ne fonctionnera pas.

ÉDIT du 16/08/2011 à 14h50 :
Je précise également que si vous créez des comptes invités/non-root/sans droits d'administration, les clés publiques permettant de se connecter avec ces comptes devront se trouver dans le fichier ~/.ssh/authorized_keys de chacun. Exemple : vous créez un compte "toto" dont le home directory est /home/toto. La clé publique de toto devra donc se trouver dans le fichier /home/toto/.ssh/authorized_keys pour que l'authentification par clé publique soit acceptée. Source : Dropbear PublicKey Authentication for multiuser setup sur forum.openwrt.org.

Fin de l'édit

Ressources

Voici les sites sur lesquels j'ai honteusement appris, pompé, adapté mais que je n'ai pas encore cité dans ce billet :

Table des matières

Comme vous le savez si vous suivez ce blog, j'ai installé un résolveur DNS sur mon WRT54GL équipé d'OpenWRT. Néanmoins, je rencontre un souci.

Problème

Dés qu'une déconnexion d'internet survient, dnscache n'est plus en mesure de résoudre les noms de domaine : il tourne encore, mais ne répond plus aux requêtes. Bien sûr, ce comportement est normal durant la coupure mais plus dès que la connexion a été rétablie. Mon routeur obtient son adresse IP WAN auprès de mon modem via le protocole DHCP.

Si vous êtes sur votre LAN quand la déconnexion survient, pas de problèmes : il suffit de se connecter au routeur via SSH et de lancer la commande suivante pour que dnscache reprenne son service :

/etc/init.d/dnscache restart

C'est déjà très ennuyeux de faire cette manipulation à chaque fois, même si on n'a pas non plus une déconnexion du net tous les jours. Mais imaginez maintenant que vous ne soyez pas sur votre LAN et que votre FAI vous attribue une IP dynamique... Hé oui, le plantage de dnscache entraine les scripts de dynamic DNS dans sa chute. En effet, ceux-ci utilisent une résolution DNS pour comparer l'IP attribuée actuellement à l'interface WAN et celle enregistrée dans le nom de domaine afin de la mettre à jour éventuellement. Cela provoque un blocage total : l'IP n'étant plus à jour dans le nom de domaine, vous ne pouvez plus vous connecter à votre routeur depuis l'extérieur.

Chercher une solution à ce problème est sur ma TODO list depuis un moment ... Vous connaissez la suite. Quoi qu'il en soit, je me suis enfin attaqué à ce problème et voici la solution que je vous propose.

Recherche d'une solution

Vous pensez à une cron qui relancerait dnscache à intervalle régulier ? Ce n'est pas une bonne idée : outre les ressources que cela consommerait, cela provoquerait la perte des associations nom de domaine <=> IP enregistré en mémoire et obligerait donc dnscache à refaire les résolutions des noms de domaine que vous avez pourtant déjà demandés. Vous perdrez ainsi un peu de réactivité.

Vous pensez à une cron qui lancerait un script qui vérifierait (avec nslookup ou dig) que le serveur ne répond plus avant de le relancer ? On progresse : vous avez éliminé le problème le plus important. Mais il reste encore le problème des ressources consommé inutilement par chaque vérification.

En fait, ce qu'il nous faudrait, c'est quelque chose qui relance le résolveur dès qu'une déconnexion est détectée. Ha ! On tient une piste. Sur OpenWRT, comme sur d'autres OS, il existe un démon qui est capable d'effectuer des actions dès qu'il capte un événement matériel (un bouton est pressé, un périphérique USB est branché, ...). Il se nomme hotplugd et il est également capable de lancer une action quand une interface réseau est activée (ifpup) ou désactivée (ifdown). "Et alors ?" vous demandez vous. La déconnexion du net provoquera un changement d'IP de l'interface WAN du routeur. Celui-ci est assimilé à une désactivation puis à une activation de la carte réseau. C'est d'ailleurs avec cette méthode qu'est lancé le script pour le dynamic dns (ddns) ou bien encore ntpclient.

Mise en place d'une solution

Vous l'avez compris, il suffit de créer un script qui relance le résolveur dns avec la commande /etc/init.d/dnscache restart dès que le statut de l'interface WAN change.

Deux méthodes sont possibles :

  • On lance la commande /etc/init.d/dnscache restart dès que le statut de l'interface passe à "activée".
  • On lance la commande /etc/init.d/dnscache stop dès que le statut de l'interface WAN devient "désactivée" puis on lance la commande /etc/init.d/dnscache start dès que l'interface WAN est réactivée

Il n'y a probablement aucune différence entre ces deux méthodes. Mais pour ma part, j'ai choisi la deuxième méthode.

Il suffit de placer le script suivant dans le dossier /etc/hotplug.d/iface/ :

#!/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

Ce script est un mélange entre celui proposé par/pour ntpclient et celui proposé par/pour le script ddns.

Lecture : si l'interface ayant provoqué l'appel à ce script est bien l'interface WAN, alors on vérifie que le processus dnscache est bien présent sur la machine. Si l'interface vient de s'activer et que la chaine $DNS_RUNNING est vide (sous-entendu que le processus dnscache n'est pas présent sur le routeur), alors on lance le résolveur DNS. Si l'interface vient d'être désactivée, et que la chaine $DNS_RUNNING n'est pas vide (sous-entendu le processus tourne), alors on stoppe le résolveur DNS.

Quel nom donner à ce script ? Cela dépend de votre configuration. En effet, le nom du script détermine l'ordre dans lequel il sera appelé par hotplugd. Il est nécessaire de relancer le résolveur avant qu'un programme dépendant de lui ne soit relancé. Dans mon cas, ntpclient et ddns ont besoin de lui. ntpclient est relancé vers la fin ("20-ntpclient") et ddns est relancé en dernier ("25-ddns"). C'est pour cela que j'ai appelé mon script "15-dnsd".

Attention à ne pas appeler votre script "15-dnscache" par exemple. Sinon, $DNS_RUNNING contiendra toujours quelque chose puisque la commande "grep dnscache" retournera toujours au moins un élément : votre script. Ainsi, les conditions ne fonctionneront pas et dnscache ne sera pas relancé.

ÉDIT du 11/08/2011 à 23h17 : Le fait d'avoir créé un script pour que le démon hotplug démarre et arrête dnscache en fonction des déconnexions survenant sur l'interface WAN provoque le fait que dnscache sera lancé par hotplug au démarrage du routeur. Mais, étant donné qu'un lien est toujours présent dans le dossier /etc/rc.d, dnscache pourrait être lancé une deuxième fois. En effet, notre script hotplug vérifie que le démon n'est pas déjà lancé mais le script d'init ne le vérifie pas. Il suffit donc que dnscache soit démarré par hotplug puis par init pour risquer de voir apparaître des problèmes. Pour l'instant, je n'ai eu aucun problème mais il vaut mieux prévenir que guérir. Plusieurs solutions sont possibles, la plus simple étant :

/etc/init.d/dnscache disable

Ainsi, dnscache ne sera lancé que par hotplugd.

Fin de l'édit

ÉDIT du 13/08/2011 à 19h30 : Si vous voulez modifier ce script et que vous souhaitez le tester sans provoquer une déconnexion physique de l'interface WAN, vous pouvez simuler l'action de hotplugd de la manière suivante :

~# ACTION=ifdown
~# INTERFACE=wan
~# export ACTION
~# export INTERFACE
~# /bin/sh /etc/hotplug.d/iface/15-dnsd
~# ACTION=ifup
~# /bin/sh /etc/hotplug.d/iface/15-dnsd

Fin de l'édit

Bonus : faire en sorte que dnscache inscrive ses démarrages et ses arrêts dans le journal système

Certains démons (ntpclient par exemple) écrivent des informations dans le journal du système (accessible via la commande "logread" ou depuis l'interface web LuCI ("Status -> Journal système")) afin d'indiquer leur lancement/arrêt. Cela est pratique en cas de problème. dnscache ne fait pas ceci : il affiche un message uniquement lors de son premier lancement par le système. Nous allons remédier à cela.

Pour écrire un message dans le journal système, il suffit d'utiliser la commande "logger". Exemple :

root@OpenWRT:~# logger test de l\'écriture dans le journal système
root@OpenWRT:~# logread
[...]
Aug  8 09:54:04 OpenWRT user.notice root: test de l'écriture dans le journal système

Il suffit donc de modifier le script de démarrage de dnscache (/etc/init.d/dnscache) pour faire inscrire un message dans le journal système.
À la fin de la fonction start(), il suffit de rajouter :

logger starting dnscache

Et à la fin de la fonction stop(), il suffit de rajouter :

logger stopping dnscache

Cette modification m'a été inspirée par le script de démarrage/arrêt de ntpclient.

Enjoy 8)

Agrégateur RSS

Exit les 30 onglets actualisés dès l'ouverture de Firefox : maintenant je suis (oui, oui, du verbe "suivre" ;)) mes sites web favoris grâce à la magie des flux RSS.

Avant que vous me demandiez si j’habitais dans une grotte depuis de nombreuses années, je précise que je connaissais les flux RSS (et même comment en générer un en PHP (en code procédural et en code objet s'il vous plaît 8) Comment ça il n'y a pas de quoi se vanter ? Oui, bon c'est vrai ...)) depuis pas mal de temps mais je n'avais pas encore trouvé (ou voulu trouver) le temps de chercher un lecteur de flux RSS (ou agrégateur).

C'est aujourd'hui chose faite et je souhaite vous faire un petit retour d'expérience qui vaut ce qu'il vaut.

Pour rappel, il existe plusieurs types d’agrégateurs :

  • Les logiciels dédiés (Liferea, Akregator, ...)
  • Les extensions pour les navigateurs (nous y reviendrons)
  • Les applications web "publiques" (Google Reader, Netvibes, ...)
  • Les applications web "privées" auto-hébergées (Tiny Tiny RSS, ...)
  • Certains clients de messagerie (Thunderbird, ...)
  • ... Liste non exhaustive ...

À chacun de choisir ce qui lui convient. Personnellement, je n'ai pas besoin de synchroniser mes flux entre plusieurs machines et le temps de vérification de l'ensemble des flux ne me dérange pas. Donc les applications web ne sont pas faites pour moi. Ensuite, je ne veux pas d'un énième programme pour lire des flux RSS. Ceci est en contradiction avec l'état d'esprit UNIX que j'affectionne d'habitude : un programme fait une seule chose mais la fait bien. Mais je ne me vois pas faire la navette entre un lecteur RSS et le navigateur (pour voir les commentaires, pour voir l'article complet selon les flux ...). Exit donc les logiciels dédiés et les clients de messagerie.

Mon lecteur de flux sera donc une extension pour mon navigateur actuel, Firefox. Voici les extensions que j'ai testées et mon avis les concernant :

Sage 1.4.12 : Première extension que j'ai essayé et j'en retiens deux soucis. D'une part, dès que l'on clique sur un flux, un résumé des dernières entrées du flux s'affiche. D'autre part, les flux ne sont pas vérifiés périodiquement de manière automatique.

Simple RSS Reader 1.3.1 : Ici, l'interface manque d'ergonomie et ne convient pas à ce que je recherche. De plus, les fonctionnalités me semblent être en recul. Mais ce deuxième point est sans importance vu le nom de l'extension ("simple") : elle peut très bien trouver son public.

Wizz RSS News Reader 4.0.1.0 : Un nag screen est affiché en échange d'une donation, il est impossible de mettre les flux à jour manuellement et certaines nouvelles entrées d'un flux surveillé ne sont pas toujours signalées (= le nom du flux ne se colore pas en rouge foncé). Tout cela s'ajoute à un flou concernant la licence.

NewsFox 1.0.8 : L'extension qui me convient le mieux. Pas de flou sur la licence (MPL 1.1/GPL 2.0/LGPL 2.1), les flux sont actualisés au démarrage de l'extension puis de manière régulière, l’interface est ergonomique et intuitive. Un simple bouton dans la barre d'outils permet de la lancer. C'est aussi l'extension qui est la plus configurable après Wizz RSS. Seule ombre au tableau : comme les autres extensions suscitées, celle-ci reste bloquée quand elle tente d'actualiser un flux et que celui-ci n'est pas accessible. Mais, contrairement aux autres extensions, une case à cocher présente dans les options du flux, " "Rafraîchir tous les flux" vérifie si ce flux a été mis à jour", permet de ne pas actualiser le flux durant la période de panne. Après avoir coché cette case, il suffit d'actualiser les flux manuellement. C'est toujours ça de pris même si c'est assez énervant. Pas de risque d'oublier de réactiver le flux et donc de ne plus être informé : le mode automatique continuera à checker le flux.

NewsFox répondant à mes besoins, j'ai arrêté là ma recherche. D'autres extensions doivent exister et peut-être mieux répondre à vos besoins.

Voilà pour ce petit retour d'expérience.