sysutils/conky

Tags: , , , ,
3 Comments »

Tout ça, c’est la faute à Guigui2. Et à Nils aussi.

Y’a quoi, 2/3 semaines, ces deux là me disent que ce serait tellement bieeeen si on avait conky dans pkgsrc et que patati le challeeenge et que patata tellement c’est beau tellement y’a des thèmes de ouf et j’en passe et des meilleures.

Et je regarde.

Et c’est l’engrenage.

Deux semaines plus tard donc, je viens d’importer sysutils/conky dans pkgsrc current avec le support des sensors usuels, CPU (SMP), load, mémoire, réseau, disque ainsi que batterie et température. Et ces deux derniers, c’étaient pas les plus simples.

En effet, si par exemple FreeBSD dispose de sysctl fort conviviaux du type hw.acpi.battery.time ou hw.acpi.battery.life, bin nous non. Nous on préfère se faire chier avec envsys(3) dont l’utilisation est expliquée de manière parfaite par ce commentaire trouvé dans sysutils/torsmo:

    /*
     * Using the envsys API is like pulling teeth without anesthetic.
     * so just popen envstat and parse the output instead.
     */

Ça résume assez bien la situation.
Mais comme je suis un peu sado-maso sur les bords, et que je souhaitais présenter un peu plus que le pourcentage de charge de la batterie, je me suis lancé dans l’écriture d’une petite fonction qui simplifie grandement l’accès aux ressources d’envsys. En gros ça donne ça:

#include <sys /envsys.h>
#include <prop /proplib.h>

#define _DEV_SYSMON "/dev/sysmon"

#define P_BOOL      0
#define P_UINT8     1
#define P_INT64     2
#define P_STRING    3

typedef struct Devquery {
    int         type;
    char        *dev;
    char        *key;
    char        *row;
} Devquery;

int             sysmon_fd;

int8_t envsys_get_val(Devquery, void *);

void
sysmon_open()
{
    sysmon_fd = open(_DEV_SYSMON, O_RDONLY);
}

void
sysmon_close()
{
    if (sysmon_fd > -1)
        close(sysmon_fd);
}

int8_t
envsys_get_val(Devquery dq, void *val)
{
    char *descr;
    const char *cval;
    prop_dictionary_t dict;
    prop_object_t device;
    prop_object_iterator_t iter;
    prop_object_t obj;
    bool rc = false;

    if (sysmon_fd < 0)
        return -1;

    if (prop_dictionary_recv_ioctl(sysmon_fd, ENVSYS_GETDICTIONARY, &dict)
        != 0)
        return -1;

    if ((device = prop_dictionary_get(dict, dq.dev)) == NULL)
        return -1;

    iter = prop_array_iterator(device);

    while((obj = prop_object_iterator_next(iter)))  {
        descr = (char *)prop_string_cstring_nocopy(prop_dictionary_get(obj,
                "description"));
        if (descr != NULL && *descr) {
            if(strcmp(descr, dq.key) == 0) {
                switch(dq.type) {
                case P_BOOL:
                    rc = prop_dictionary_get_bool(obj,
                        dq.row, (bool *)val);
                case P_UINT8:
                    rc = prop_dictionary_get_uint8(obj,
                        dq.row, (uint8_t *)val);
                    break;
                case P_INT64:
                    rc = prop_dictionary_get_int64(obj, dq.row,
                        (int64_t *)val);
                    break;
                case P_STRING:
                    rc = prop_dictionary_get_cstring_nocopy(obj,
                        dq.row, &cval);
                    val = (void *)cval;
                    break;
                }
            }
        }
    }

    prop_object_iterator_release(iter);
    prop_object_release(dict);

    if (rc == false) {
        val = NULL;
        return -1;
    }

    return 0;
}

On utilise la fonction de cette façon:

    Devquery dq_ac = { P_BOOL, "acpiacad0", "connected", "cur-value" };

    if (envsys_get_val(dq_ac, (void *)&connected) < 0)

Dans cet exemple, connected sera placé à 1 si l'élément acpiacad0 est connecté, 0 autrement.

Le package n'est pas encore parfait, mais il est désormais tout à fait utilisable. Upstream a été contacté et l'integration de mes patchs est en cours.

Mandatory screenshot:

Une brêve histoire de design

Tags: , , ,
1 Comment »

Tout commence la semaine dernière, un innocent freelance que nous faisons bosser sur un projet secret de domination des informations galactiques me montre son boulot et ne résiste pas à l’envie de me montrer des bouts de code. Je ne manque pas de remarquer que son éditeur de texte ne ressemble à rien de connu, mais brille par sa simplicité et son élégance. Il m’annonce fièrement qu’il travaille sous Sublime Text 2.
Curieux, je recherche l’outil en question et m’aperçois avec effroi que non seulement il n’est pas Libre, mais qu’en plus que son prix est exorbitant: 59$ pour *une* licence utilisateur, on se croirait revenu à l’âge d’or des shareware.
Mais il est sexy son truc. En particulier les couleurs. Bien choisies, harmonieuses. Sexy.

Je fais mon C sous emacs en console, il en a toujours été ainsi, j’ai mes habitudes de programmation sur cet éditeur, et si je préfère vim pour le scripting et l’édition de texte simple, emacs, depuis 15 ans maintenant, accompagne la totalité de mes projets en C.
Jusqu’à ce week-end, je ne m’étais jamais vraiment préoccupé de problématiques liées aux couleurs, aux thèmes où autres considérations futiles. Jusqu’à ce week-end.

D’abord, je comprend que mon terminal screené n’affiche pas plus de 8 couleurs, cela parce que l’option PKG_OPTIONS.screen+= ncurses n’est pas présente dans mon /etc/mk.conf, et que cela a pour conséquence que cette condition:

.if !empty(PKG_OPTIONS:Mncurses)
CURSES_DEFAULT= ncurses
CONFIGURE_ARGS+=        --enable-colors256
.endif

n’est pas remplie. Résultat, toute tentative d’utiliser un quelconque thème muni de couleurs un peu originales se solde par un vague pâté difforme à 8 couleurs.
L’utilisation du script 256colors2.pl me confirme qu’à l’issue de la recompilation de screen avec les bonnes options, on obtient bien de jolis dégradés:

Emacs refusait de m’annoncer plus de 8 couleurs à son tour, quand bien même le terminal qui l’héberge était désormais muni de super pouvoirs. Rien à faire, M-x list-colors-display ne m’affichait que 8 ignobles couleurs standard.
Deux choses à faire ici, ajouter un ~/.termcap décrivant un terminal de type xterm-256color, et ensuite, démarrer le monsieur de cette façon:

$ TERM=xterm-256color emacs

N’exportez pas cette variable dans votre ~/.profile, bien d’autres emmerdes vous attendraient au tournant. J’ai préféré un vilain alias.

Finalement, je me rend compte que les couleurs présentées par un emacs screené sont assez différentes d’un emacs non screené. De fil en aiguille, je tombe sur cette page sur laquelle on trouve ce fichier à placer dans votre ~/.emacs.d/term afin de retrouver des couleurs adéquates.

Après des heures de bataille, j’ai enfin pu bidouiller un des thèmes présents sur emacswiki pour obtenir ceci:

Je suis pas fâché du résultat.

Et comme j’aime bien partager, voici le thème et le init.el.

Ça va pas être possible avec vos baskets

Tags: , , ,
No Comments »

Dans ma boîte, l’équipe sécurité a publié voila quelques mois de cela un module pour nginx: un firewall applicatif du nom de naxsi.

Ce module, sous licence GPLv2, je viens de le publier dans pkgsrc current sous la forme d’une option de www/nginx. Je me propose de vous montrer ici comment sécuriser simplement votre serveur web / proxy inverse nginx grâce à naxsi.

Premièrement, si comme moi (et comme il se doit) vous utilisez une branche stable de pkgsrc, mettez simplement à jour www/nginx comme ceci:

$ cd /usr/pkgsrc/www/nginx
# cvs up -rHEAD -dP

Puis spécifiez à pkgsrc que vous souhaitez activer l’option naxsi pour le paquet nginx:

$ grep nginx /etc/mk.conf
PKG_OPTIONS.nginx+=     naxsi

Ceci fait, reconstruisez le paquet comme d’habitude:

$ cd /usr/pkgsrc/www/nginx
$ sudo make update clean

Dans la configuration de nginx, incluez les règles par défaut de naxsi de cette façon:

http {
    include       /usr/pkg/etc/nginx/mime.types;
    include       /usr/pkg/etc/nginx/naxsi_core.rules; # < --- ici
    default_type  application/octet-stream;

Comme vous pourrez le constater, le fichier /usr/pkg/etc/nginx/naxsi_core.rules contient un set de règles déjà très efficaces contre bon nombre d'attaques connues.
Reste alors à activer le filtrage sur une location et choisir quels types d'attaques vous souhaitez bloquer; par exemple:

        location / {
            SecRulesEnabled;
            CheckRule "$SQL >= 8" BLOCK;
            CheckRule "$RFI >= 8" BLOCK;
            CheckRule "$TRAVERSAL >= 4" BLOCK;
            CheckRule "$EVADE >= 4" BLOCK;
            CheckRule "$XSS >= 8" BLOCK;

Un redémarrage de nginx plus loin, on essayera par exemple d’accéder à une adresse louche:

$ wget -O- http://coruscant/?../../etc/passwd
--2012-04-22 10:21:01--  http://coruscant/?../../etc/passwd
Resolving coruscant... 192.168.1.2
Connecting to coruscant|192.168.1.2|:80... connected.
HTTP request sent, awaiting response... No data received.

Et de constater dans /var/log/nginx/error.log:

2012/04/22 10:21:01 [error] 25353#0: *15 NAXSI_FMT: ip=192.168.1.1&server=192.168.1.2&uri=/&total_processed=1&total_blocked=1&zone0=ARGS&id0=1200&var_name0=, client: 192.168.1.1, server: localhost, request: "GET /?../../etc/passwd HTTP/1.0", host: "192.168.1.2"

Moi j’trouve ça assez classe tout de même.

Toutes les infos relatives à la configuration de naxsi sont disponibles sur le Wiki de ce dernier.

pkgin 0.5.2.3

Tags: , ,
No Comments »

!@#!@# de bug.

Des mois que je cherchais au mauvais endroit, en effet, uniquement chez certains utilisateurs (évidemment), un pkgin up / fug proposait d’installer l’univers. Problème dans le moteur de dépendances me dis-je; que de temps perdu à décortiquer ce qui fonctionnait parfaitement, pour finalement tomber sur ceci:

static const struct Summary {
	const int	type;
	const char	*tbl_name;
	const char	*deps;
	const char	*conflicts;
	const char	*requires;
	const char	*provides;
	const char	*end;
} sumsw[] = {
	{
		LOCAL_SUMMARY,
		"LOCAL_PKG",
		"LOCAL_DEPS",
		"LOCAL_CONFLICTS",
		"LOCAL_REQUIRES",
		"LOCAL_PROVIDES",
		NULL
	},
	{
		REMOTE_SUMMARY,
		"REMOTE_PKG",
		"REMOTE_DEPS",
		"REMOTE_CONFLICTS",
		"REMOTE_REQUIRES",
		"REMOTE_PROVIDES",
		NULL
	},
};

[...]

	for (ptbl = __UNCONST(sum.tbl_name), i = 0;
		 i < nelms;
		 ptbl += ((strlen(ptbl) + 1) * sizeof(char)), i++) {

Il ne faut PAaaaaaaas coder avec de l'alcool dans le sang, il ne faut pas, parce qu'après, on se retrouve avec des bouts de trucs ni faits ni à faire qui supposent que les membres d'une structure seront forcément alignés, et des effets de bords qui n'ont rien à voir.

Bref, stacktic m'a proposé cette méthode, bien plus élégante:

static const struct Summary {
	const int	type;
	const char	*tbl_name;
	const char	*deps;
	const char	*conflicts;
	const char	*requires;
	const char	*provides;
	const char	*end;
} sumsw[] = {
	[LOCAL_SUMMARY] = {
		LOCAL_SUMMARY,
		"LOCAL_PKG",
		"LOCAL_DEPS",
		"LOCAL_CONFLICTS",
		"LOCAL_REQUIRES",
		"LOCAL_PROVIDES",
		NULL
	},
	[REMOTE_SUMMARY] = {
		REMOTE_SUMMARY,
		"REMOTE_PKG",
		"REMOTE_DEPS",
		"REMOTE_CONFLICTS",
		"REMOTE_REQUIRES",
		"REMOTE_PROVIDES",
		NULL
	},
};

[...]

	/* (REMOTE[LOCAL)_PKG is first -> skip */
	for (arr = &(sum.tbl_name) + 1; *arr != NULL; ++arr) {

Aaah, bah oui, tout de suite c’est moins dégueulasse hein.

0.5.2.3 est dans current, et le pullup request vient de partir.

meh.

pkgin@FOSDEM 2012

Tags: ,
1 Comment »

De retour du FOSDEM 2012; 2 jours exceptionnels, des amis, du prosélytisme, des rencontres, des échanges. D’excellents souvenirs et le rendez-vous est d’ores et déjà pris pour l’année prochaine. Merci à tous, et tout particulièrement aux lutins du jardin magique.
Le stand NetBSD que je tenais avec Nicolas, Marc, Nod et Vera était bien animé, bon nombre de visiteurs ont montré un fort intérêt pour le projet, ça fait plaisir :)

Voici la présentation traitant de pkgin que j’ai faite aux BSD devrooms.

mmmmm les bons spaghettis

Tags: , , , , ,
1 Comment »

Ça commence à sentir le vieux sac de lacets sur ma routing box.
Pour rappel, j’utilise un domU NetBSD hébergé quelque part pour différencier mon traffic sortant. Ce domU est controllé par un dom0 Debian Squeeze, et a ceci de particulier que sa route par défaut part vers la suède. Seuls quelques services répondent directement sur l’IP publique “réelle”, sur laquelle j’opère du SNAT et du DNAT.

Tout ceci manquait cruellement d’un soupçon d’IPv6. Ainsi, après m’être frotté à SixXs et son système de crédits aussi ingénieux que pénible, j’ai finalement opté pour Hurricane Electric qui a en plus le bon goût de posséder un endpoint à Paris.

Si la configuration d’un tunnel v4/v6 se réalise le plus simplement du monde depuis plus de 10 ans via des tunnels gif, l’opération n’est pas complètement triviale lorsque le endpoint se trouve être NATté et qu’en plus ce dernier utilise une route par défaut différente de l’IP publique officielle du dom0.

Ainsi, après avoir souscrit à un endpoint IPv6 chez HE, quelques opérations sont nécessaires au bon fonctionnement du routage. Nous considèrerons que l’ip du endpoint gif IPv4 chez Hurricane est 1.2.3.4 et que notre IPv4 publique, sur le dom0 donc, est 5.6.7.8.

La première chose à faire sur notre dom0 est de rediriger tout le traffic en provenance de HE vers notre domU, dont nous considèrerons que l’IPv4 privée est 192.168.0.1.

# iptables -t nat -A PREROUTING -i eth0 -s 1.2.3.4 -j DNAT --to-destination 192.168.0.1

Il faudra évidemment, si cela n’est pas déjà fait, appliquer du SNAT afin que votre domU puisse “sortir” et se présenter avec notre IPv4 publique au monde. Par exemple:

# iptables -t nat -A POSTROUTING -s 192.168.0.1/32 -o eth0 -j SNAT --to-source 5.6.7.8

C’est l’unique configuration à effectuer sur le dom0. Jusqu’ici tout va bien.

Sur notre domU NetBSD, nous créons l’interface de tunneling comme ceci:

# ifconfig gif0 create
# ifconfig gif0 tunnel 192.168.0.1 1.2.3.4
# ifconfig gif0 inet6 2001:470:1e31:b2c::2 2001:470:1e31:b2c::1 prefixlen 128

Notez que c’est bien l’IPv4 privée que nous utilisons pour monter le tunnel gif, le SNAT du dom0 s’occuppera de transformer cette IP au vol.
Cette seule configuration, compte tenu du routage particulier de notre domU, ne suffira pas au bon fonctionnement du tunnel. Deux opérations sont nécessaires:

  • Ajouter une route explicite vers le endpoint HE
  • Forcer la sortie vers l’interface réelle du dom0 lorsqu’on essaye de joindre une adresse IPv6

Execution:

# route add -host 1.2.3.4 192.168.0.254

Ici, 192.168.0.254 est l’adresse passerelle du dom0.

# grep he_tunnel /etc/pf.conf-ovpn
he_tunnel="1.2.3.4/32"
pass out quick route-to ($real_if $gateway) from any to $he_tunnel

$real_if représente l’interface xennet0, et $gateway l’adresse de notre passerelle coté dom0, à savoir 192.168.0.254.
Reste à appliquer une route par défaut pour les adresses IPv6:

route -n add -inet6 default 2001:470:1e31:b2c::1

Et nous y sommes. Enfin, il faut evidemment automatiser toutes ces manipulations afin de retrouver notre état fonctionnel à chaque reboot, cela est réalisé en créant le fichier /etc/ifconfig.gif0 avec ce contenu:

create
tunnel 192.168.0.1 1.2.3.4
inet6 2001:470:1e31:b2c::2 2001:470:1e31:b2c::1 prefixlen 128
!route add -host 1.2.3.4 192.168.0.254
!route -n add -inet6 default 2001:470:1e31:b2c::1

And voila, Danse petite tortue, danse !

WP Theme & Icons based on GlossyBlue by N.Design Studio
Banner from www.trynthlas.com
Entries RSS Comments RSS Log in
Performance Optimization WordPress Plugins by W3 EDGE