unix4fun

Aller au contenu | Aller au menu | Aller à la recherche

vendredi 7 octobre 2011

Mon Toy-project du moment ! Un FS sur le cloud !

Beh voilà, encore un peu d'auto-promotion. Et en fait j'ai un peu menti, ça fait plusieurs mois que je ne commit qu'un bout de code par-ci ou par-là.

Ma société a écrit une bibliothèque en open source pour travailler sur le cloud (différents protocoles supportés, mais je vous laisse découvrir ça). Bref, je me suis basé sur cette lib pour implémenter un filesystem en utilisant FUSE : dropletfs ; c'est lent (car le design est simpliste et pas optimisé), mais rigolo.

Toutes les features d'un FS posix ne sont pas présentes, loin de là (gérer les hardlinks est plutôt compliqué), mais pour un usage basique, ça 'juste marche'.

Une petite démo intéractive (nécessite le package ttyrec) : ici

vendredi 16 septembre 2011

SPLONK !

Si, comme moi, vous vous battez continuellement dans vos logs avec grep/sed/awk/cut/tail/paprika (cherchez pas c'est de l'humour), alors vous avez certainement deja entendu parlé de splunk. Pour faire très court, splunk, c'est un peu le Google des logs : c'est ultra pratique (et intuitif) si vous cherchez à faire une recherche dans 45 millions de logs.

Seulement voilà, splunk est payant, et même plutot cher si vous souhaitez l'intégrer dans un environnement de hosting par exemple. Alors le reflexe habituel quand on est un gros radin comme moi, c'est de trouver une alternative gratuite, mais jusqu'à présent, c'etait un peu l'age de pierre chez la concurrence (non je ne citerai personne).

Jusqu'à present :)

Tout a fait par hasard, je suis tombe sur un billet de ce monsieur en chemise a carreaux (kof). Et la.. ce fut l'illumination alors je souhaitais -sous la menace- vous faire partager cette découverte !

mercredi 13 juillet 2011

et dire qu'il y a des gens qui se vantent sans arrêt d'être des "hackers"...

Apprenez l'humilité et un descriptif comme:
"(The World's First (and Last?!) IPv6 Cat Feeder!)"

Qui est (selon moi) un super joli "hack" d'un mec un peu dingue et super poilu, en tout cas je trouve ca mortel (et assez incroyable)! congrats! :)

Enjoy the fun: http://www.newtonnet.co.uk/catfeeder/

jeudi 28 avril 2011

c'est quoi SCTP!?

Alors je suis en mode honey badger cette semaine et je "dig" pleins de trucs que je ne connais pas tres bien, je mattais comment marche SCTP, le soit disant "potentiel remplaçant de TCP et UDP" (oui je vous jure j ai lu ca qqes part, mais je sais plus ou...).

Si comme moi vous aviez juste une feuille de platane pour cacher votre nudité devant SCTP, voila une introduction a SCTP, de quoi avoir un short en lieu et place de la feuille de platane.

Je me demande si TCP/IP illustrated et cie sont mis a jour avec tout ces nouveaux protocoles, IPv6, SCTP etc... ou si il y a de nouvelles references aussi détaillées..

bref enjoy!

mardi 21 décembre 2010

Pour les addicts du sniffing réseau: Junkie

Un peu de proselytisme ne fait jamais de mal, alors voilà Junkie, un sniffer releasé en Open Source par la société SecurActive.

Pour l'instant il a été programmé pour tourner sur du Linux debian-like, donc...


Un extrait du README:


Compared to previously available tools junkie lies in between tcpdump and
wireshark. Unlike tcpdump, its purpose is to parse protocols of any depth;
unlike wireshark, through, junkie is designed to analyze traffic in real-time
and so cannot parse traffic as completely as wireshark does.

In addition, junkie's design encompasses extendability and speed:

- plug-in system + high-level extension language that eases the development and
  combination of new functionalities;
- threaded packet capture and analysis for handling of high bandwidth network;
- modular architecture to ease the addition of any protocol layer;
- based on libpcap for portability;
- well tested on professional settings.


Il manque un "IPv6 compliant" je pense, dans ce README.

Seuls les parseurs sont releasés en Open Source, mais c'est déjà bien sympa. Le design est fait de telle sorte qu'il est facile d'ajouter un plugin d'analyse pour un protocole particulier 1. Et pour ceux qui n'aiment pas le C, il y a possibilité d'exercer vos talents de codeurs Scheme (guile plus précisemment), car il est scriptable à l'aide de ce langage ! Ouh ouh !


Un petit exemple d'utilisation ? OK, c'est parti :


$ sudo ./src/junkie -i wlan0 -c config/start-repl.scm
2010-12-22 00:36:45: J-main: log.c/log_set_file: Opening log file.


OK, là on lui a dit de loguer sur stdout, d'écouter l'interface wireless wlan0, et de prendre le fichier de conf par défaut qui active le REPL. Donc, dans un autre terminal, je vais me connecter sur la machine, en tcp/29000 pour ajouter des settings sur la mouche comme disent nos amis anglais (ie. "on the fly"... ok c'est nul).


$ rlwrap telnet localhost 29000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
junkie> (set-iface-filter "wlan0" "icmp")
#t
junkie> (set-log-level 6)
#<unspecified>
junkie>


Les valeurs de retour affichées sont celles de guile, à savoir #t pour true, et #<unspecified> pour dire qu'il n'y a pas de code de retour. C'est un peu curieux au début, mais ceux qui ont utilisé ce langage ne seront pas dépaysés.

Là je lui ai demandé de prendre en compte le filtre BPF (tcpdump, vous connaissez, hein ?) "icmp" pour l'interface wlan0.

Hey ouais, c'est ça qui est cool, on peut écouter sur différentes interfaces avec des filtres différents. Bref, dans un autre terminal je tape :


$ ping free.fr -c1
PING free.fr (212.27.48.10) 56(84) bytes of data.
64 bytes from www.free.fr (212.27.48.10): icmp_seq=1 ttl=118 time=37.1 ms

--- free.fr ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 37.176/37.176/37.176/0.000 ms


Et si on repasse dans la console de log, on a :


Capture@0x23f0068: head_len=48, payload=60, dev_id=0, tv=1293009623s 788239us
Ethernet@0x2413ea8: head_len=14, payload=46, vlan_id=0, source=00:1b:2f:2e:e0:fa, dest=ff:ff:ff:ff:ff:ff, proto=2054

Capture@0x23f0068: head_len=48, payload=74, dev_id=0, tv=1293009880s 139307us
Ethernet@0x2413ea8: head_len=14, payload=60, vlan_id=0, source=00:1c:bf:9d:2e:21, dest=00:15:e9:f2:30:67, proto=2048
IPv4@0x2414e38: head_len=20, payload=40, version=4, addr=10.0.63.10->82.237.175.5, proto=6, ttl=64
TCP@0x23bcf08: head_len=40, payload=0, ports=42007->1234, flags=Syn, win=5840, ack=0, seq=902941316

Capture@0x23f0068: head_len=48, payload=98, dev_id=0, tv=1293009631s 741103us
Ethernet@0x2413ea8: head_len=14, payload=84, vlan_id=0, source=00:1c:bf:9d:2e:21, dest=00:15:e9:f2:30:67, proto=2048
IPv4@0x2414e38: head_len=20, payload=64, version=4, addr=10.0.63.10->212.27.48.10, proto=1, ttl=64
ICMP@0x23bb198: head_len=64, payload=0, type=EchoRequest, err=NONE

Capture@0x23f0068: head_len=48, payload=98, dev_id=0, tv=1293009631s 744391us
Ethernet@0x2413ea8: head_len=14, payload=84, vlan_id=0, source=00:15:e9:f2:30:67, dest=00:1c:bf:9d:2e:21, proto=2048
IPv4@0x2414e38: head_len=20, payload=64, version=4, addr=212.27.48.10->10.0.63.10 (hashed the other way), proto=1, ttl=122
ICMP@0x23bb198: head_len=64, payload=0, type=EchoReply, err=NONE

Un lecteur attentif verra qu'il n'y a pas que de l'ICMP qui a été logué (cf. les premières lignes). Il a raison ! Mais comme je l'ai dit plus haut, on a changé la config à chaud, donc Junkie a eu le temps de loguer quelques paquets avant de prendre en compte le filtre BPF.

Et voilà ! Bon, c'est un exemple parmi des tonnes hein, chacun peut y trouver son compte, là c'est vraiment pour expliquer le fonctionnement. Pour plus d'infos :

$ junkie -h

Ou bien pour des détails vraiment poussés, dans le REPL :


junkie> (help)
[...]
junkie> (help 'commande)



1 Tutorial de codage d'un parseur : parser implementation


jeudi 7 octobre 2010

Pwnage par libpcap

Yo. Dans ce post je vais expliquer comment je me suis battu pour faire un truc assez simple avec la libpcap sous linux.

Au début était un sniffer, je voulais écouter sur une interface à grands coups de SOCK_RAW + recvfrom(). À l'ancienne, quoi. L'idée était de ne pas utiliser de handler pcap (pcap_t *). Au bout d'un moment je me dis "tiens, ça serait sympa d'ajouter les filtres BPF comme dans tcpdump". Brillante idée, non ? Non, ok. Bref, le code de départ est le suivant :

// -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
// vim:sw=4 ts=4 sts=4 expandtab
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <poll.h>
#include <linux/types.h>
#include <errno.h>
#include <pcap.h>
#include <linux/filter.h>

#define FRAME_SIZE 65536

/* iface_setprom() sets "device" in promiscuous mode */
static int
iface_setprom(int sock_fd, const char *device)
{
    struct ifreq ifr;

    memset(&ifr, 0, sizeof ifr);
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", device);

    if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
        printf("[%s] ioctl: %s.\n", device, strerror(errno));
        return -1;
    }

    ifr.ifr_flags |= (IFF_PROMISC | IFF_UP);

    if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
        printf("[%s] ioctl: %s.\n", device, strerror(errno));
        return -1;
    }

    printf("[%s] enter in promiscuous mode\n", device);
    return 0;
}



À partir d'une chaîne de caractère entrée, par exemple "tcp and port 22", on veut obtenir une structure comprise par pcap_compile*(). Comme dit précédemment, je ne veux pas de pcap_t* à manipuler, je vais donc utiliser pcap_compile_nopcap() (non mentionné dans le man de pcap_compile sous linux, évidemment).

/* iface_setfilter() applies a LSF filter to the file descriptor */
static int
iface_setfilter(int sock_fd, const char * const device, const char * const filter)
{
    if (!filter || !*filter) {
        printf("[%s] no filter to install\n", device);
        return 0;
    }

    struct bpf_program bpf;
    memset(&bpf, 0, sizeof bpf);

    char errbuf[PCAP_ERRBUF_SIZE = "";

    if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
        printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
        return -1;
    }

    if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf)) {
        printf("[%s] setsockopt: %s (filter '%s')\n", device, strerror(errno), filter);
        return -1;
    }

    printf("[%s] filter '%s' successfully installed\n", device, filter);
    return 0;
}

/* iface_init() is the main device initialization function */
static int
iface_init(struct pollfd *fds, const char * const device, const char * const filter)
{
    printf("Initializing interface %s (filter '%s')\n", device, filter);

    fds->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (fds->fd == -1) {
        printf("[%s] socket: %s. Exiting...\n", device, strerror(errno));
        exit(EXIT_FAILURE);
    }

    fds->events = POLLIN | POLLPRI;

    if (0 != iface_setprom(fds->fd, device)) return -1;
    if (0 != iface_bind(fds->fd, device)) return -1;
    if (0 != iface_setfilter(fds->fd, device, filter)) return -1;

    return 0;
}

static void
frame_manager(const char * const device, struct pollfd *fd, struct timeval const *now)
{
    uint32_t i;

    if ((fd->revents & (POLLIN | POLLPRI)) == 0)
        return;

    unsigned char buf[1500] = "";
    ssize_t n = recvfrom(fd->fd, buf, sizeof buf, MSG_DONTWAIT, NULL, NULL);
    if (n < 0) {
        printf("[%s] recvfrom: %s (i=%d, fd=%d)\n", device, strerror(errno), i, fd->fd);
        return;
    }

    printf("[%d,%d] packet received\n", (int)now->tv_sec, (int)now->tv_usec);
}

int main(int ac, char **av)
{
    char *filter = "";
    char *device = "dummy0";

    if (ac > 1) {
        filter = av[1];
    }

    struct pollfd fd;
    (void)iface_init(&fd, device, filter);

    while (/*CONSTCOND*/ 1) {
        if (poll(&fd, 1, -1) > 0) {
            struct timeval now;
            gettimeofday(&now, NULL);
            frame_manager(device, &fd, &now);
        }
    }

    close(fd.fd);
    return EXIT_SUCCESS;
}



Tout d'abord, je monte une interface virtuelle pour éviter le bruit généré par les paquets circulants sur mes vraies interfaces :

$ sudo modprobe dummy
$ sudo ifconfig dummy0 mtu 1600 up



Maintenant, si je compile et j'exécute le code, et que je balance du ssh sur dummy0, j'ai ça :

$ cc -o cap cap.c -lpcap
$ sudo ./cap "tcp and port 22"
[...]



Et dans un autre terminal :

$ sudo tcpreplay -i dummy0 ssh.pcap



Mais aucun "packet received" ne s'affiche. Damned ! En inspectant un peu le code, on voit ça :

    if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf)) {



Ça a l'air bien comme ça, hein. Malheureusement, le 'struct bpf_program' n'est pas compris sous linux, qui, ne voulant pas faire comme ses potes *BSD attend un 'struct sock_fprog *' en avant dernier argument. Bon, ici je me dis "il doit bien y avoir une fonction qui fait la conversion, cherchons dans le source de libpcap". En jetant un coup d'oeil rapide, on tombe sur ça :

libpcap-0.9.8/pcap-linux.c:215 static int       fix_program(pcap_t *handle, struct sock_fprog *fcode);



Je suis content, mais visiblement je dois passer par un pcap_t. Du coup, je reprends le code en l'adaptant pour taper directement dans la structure interne du handler pcap, et j'écris la fonction suivante :

#define SLL_HDR_LEN 16
static int lcc = 0; // linux cooked capture

static int
fix_offset(struct bpf_insn *p)
{
    if (p->k >= SLL_HDR_LEN) {
        p->k -= SLL_HDR_LEN;
    } else if (p->k == 14) {
        p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
    } else {
        return -1;
    }
    return 0;
}

static int
fix_code(struct bpf_program *bpf, struct sock_fprog *fcode)
{
    size_t prog_size;
    register int i;
    register struct bpf_insn *p;
    struct bpf_insn *f;
    int len;

    len = bpf->bf_len;
    prog_size = sizeof(bpf->bf_insns) * len;
    f = malloc(prog_size);
    if (f == NULL) {
        printf("malloc: %s\n", strerror(errno));
        return -1;
    }
    memcpy(f, bpf->bf_insns, prog_size);
    fcode->len = len;
    fcode->filter = (struct sock_filter *)f;

    for (i = 0; i < len; ++i) {
        p = &f[i];
        switch (BPF_CLASS(p->code)) {

        case BPF_RET:
            if (BPF_MODE(p->code) == BPF_K) {
                if (p->k != 0)
                    p->k = 65535;
            }
            break;

        case BPF_LD:
        case BPF_LDX:
            switch (BPF_MODE(p->code)) {

            case BPF_ABS:
            case BPF_IND:
            case BPF_MSH:
                if (lcc) {
                    if (fix_offset(p) < 0) {
                        return 0;
                    }
                }
                break;
            }
            break;
        }
    }
    return 1;       /* success! */
}



Maintenant je réécris ma fonction iface_setfilter() pour convertir le code BPF :

static int
iface_setfilter(int sock_fd, const char * const device, const char * const filter)
{
    if (! filter || ! *filter) {
        printf("[%s] no filter to install\n", device);
        return 0;
    }

    struct bpf_program bpf;
    memset(&bpf, 0, sizeof bpf);

    if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
        printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
        return -1;
    }

    struct sock_fprog fcode;
    memset(&fcode, 0, sizeof fcode);
    int ret = fix_code(&bpf, &fcode);

    if (1 != ret) {
        printf("[%s] fix_code failed (rcode = %d) for filter '%s'\n", device, ret, filter);
        return -1;
    } else {
        printf("[%s] fix_code worked (rcode = %d) for filter '%s'\n", device, ret, filter);
    }

    if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof fcode)) {
        printf("[%s] setsockopt: %s (filter '%s')\n", device, strerror(errno), filter);
        return -1;
    }

    printf("[%s] filter '%s' successfully installed\n", device, filter);
    return 0;
}



Là, logiquement je me dis "Youpi les knakis¸ ça va marcher !". Mais si je reteste, toujours rien. Rien ne s'affiche. La blague est même que si j'invoque :

$ sudo ./cap "not port 80"



... et que je joue du traffic http (sur le port 80 bien sûr), mon outil logue qu'il a vu un paquet ! Par contre avec "port 80" il n'affiche rien. Bon je me suis pas mal gratté la tête ici, j'avoue. Du coup j'appelle mon copain strace à la rescousse, et je compare le raw des filtres passés à setsockopt() entre mon code et l'appel tcpdump :

$ sudo strace -s 256 -f -v ./cap "port 80" 2>&1 | grep ATTACH_FILTER
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\33\0\0\0\0\0\0\0\20\240\363\0\0\0\0\0", 16) = 0
^C
$ sudo strace -s 256 -f -v tcpdump -ni dummy0 port 80 2>&1 | grep ATTACH_FILTER
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\1\0\0\0\0\0\0\0h\303\315E(\177\0\0", 16) = 0
setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\30\0\0\0\0\0\0\0\360V1G(\177\0\0", 16) = 0
^C



Les outputs ne sont pas les mêmes. La génération du filtre est donc foireuse, je vérifie maintenant comme suit :

$ sudo tcpdump -nd port 80
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 10
(002) ldb      [20]
(003) jeq      #0x84            jt 6    jf 4
(004) jeq      #0x6             jt 6    jf 5
(005) jeq      #0x11            jt 6    jf 23
(006) ldh      [54]
(007) jeq      #0x50            jt 22   jf 8
(008) ldh      [56]
(009) jeq      #0x50            jt 22   jf 23
(010) jeq      #0x800           jt 11   jf 23
(011) ldb      [23]
(012) jeq      #0x84            jt 15   jf 13
(013) jeq      #0x6             jt 15   jf 14
(014) jeq      #0x11            jt 15   jf 23
(015) ldh      [20]
(016) jset     #0x1fff          jt 23   jf 17
(017) ldxb     4*([14]&0xf)
(018) ldh      [x + 14]
(019) jeq      #0x50            jt 22   jf 20
(020) ldh      [x + 16]
(021) jeq      #0x50            jt 22   jf 23
(022) ret      #96
(023) ret      #0



Et j'invoque

    if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
        printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
        return -1;
    }
    bpf_dump(&bpf, 0);



J'ai en sortie :

Initializing interface dummy0 (filter 'port 80')
[dummy0] enter in promiscuous mode
[dummy0] bind succeed: index 1634 <--> dummy0
(000) ldb      [0]
(001) and      #0xf0
(002) jeq      #0x60            jt 3    jf 11
(003) ldb      [6]
(004) jeq      #0x84            jt 7    jf 5
(005) jeq      #0x6             jt 7    jf 6
(006) jeq      #0x11            jt 7    jf 26
(007) ldh      [40]
(008) jeq      #0x50            jt 25   jf 9
(009) ldh      [42]
(010) jeq      #0x50            jt 25   jf 26
(011) ldb      [0]
(012) and      #0xf0
(013) jeq      #0x40            jt 14   jf 26
(014) ldb      [9]
(015) jeq      #0x84            jt 18   jf 16
(016) jeq      #0x6             jt 18   jf 17
(017) jeq      #0x11            jt 18   jf 26
(018) ldh      [6]
(019) jset     #0x1fff          jt 26   jf 20
(020) ldxb     4*([0]&0xf)
(021) ldh      [x + 0]
(022) jeq      #0x50            jt 25   jf 23
(023) ldh      [x + 2]
(024) jeq      #0x50            jt 25   jf 26
(025) ret      #65536
(026) ret      #0
[dummy0] fix_code worked (rcode = 1) for filter 'port 80'
[dummy0] filter 'port 80' successfully installed
^C



On voit bien que c'est différent au début. Le reste est plutôt cohérent

(016) jeq      #0x6             jt 18   jf 17  # 0x06 c'est l'IPPROTO_TCP (6)
(017) jeq      #0x11            jt 18   jf 26  # 0x11 = 17 = IPPROTO_UDP



Si on n'est dans aucun des deux cas, on saute en 26 (jf 26), soit la fin. Sinon, on regarde si le port vaut 80 (0x50) :

(022) jeq      #0x50            jt 25   jf 23
(023) ldh      [x + 2]
(024) jeq      #0x50            jt 25   jf 26



Le problème est vraiment le prologue. Et là je on me souffle à l'oreille que c'est peut-être le datalink type. Réaction: "bon dieu de !#@@!#@!# mais c'est bien sûr, ça doit être mon datalink (DLT) qui est moisi !" Si j'écris :

    if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_IEEE802, &bpf, filter, 1, 0)) {



J'obtiens en sortie :

$ cc -o cap cap.c -lpcap && sudo ./cap "port 80" 
Initializing interface dummy0 (filter 'port 80')
[dummy0] enter in promiscuous mode
[dummy0] bind succeed: index 1634 <--> dummy0
(000) ldh      [20]
(001) jeq      #0x86dd          jt 2    jf 10  # 0x86dd est l'ethertype IPv6
(002) ldb      [28]
(003) jeq      #0x84            jt 6    jf 4
(004) jeq      #0x6             jt 6    jf 5
(005) jeq      #0x11            jt 6    jf 23
(006) ldh      [62]
(007) jeq      #0x50            jt 22   jf 8
(008) ldh      [64]
(009) jeq      #0x50            jt 22   jf 23
(010) jeq      #0x800           jt 11   jf 23  # 0x800 est l'ethertype IPv4
[...]



Mais toujours rien n'est logué si je joue du http ! En remplaçant DLT_IEEE802 par DLT_EN10MB en revanche...

[...]
[dummy0] enter in promiscuous mode
[dummy0] bind succeed: index 1634 <--> dummy0
[dummy0] fix_code worked (rcode = 1) for filter 'port 80'
[dummy0] filter 'port 80' successfully installed
[1286457559,615193] packet received



Hallelujah ! Hosanna hosanna !

Enfin bon, c'est quand même moche d'écrire le DLT en dur dans le code, donc je l'ai récupéré via la libpcap (mais on est obligé de passer par un handler pcap_t *, ce que je ne voulais pas trop au début...)

    char errbuf[256] = "";
    pcap_t *p = pcap_open_live(device, FRAME_SIZE, 1, 0, errbuf);
    if (! p) {
        printf("[%s] pcap_open_live failed: %s\n", device, errbuf);
        return -1;
    }

    int dlt = pcap_datalink(p);
    pcap_close(p);

    if (-1 == pcap_compile_nopcap(FRAME_SIZE, dlt, &bpf, filter, 1, 0)) {
        printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
        return -1;
    }



En fait, comme on dispose du handler pcap_t, on peut même dégager pcap_compile_nopcap() et utiliser pcap_compile(), qui lui n'a même pas besoin d'un DLT en paramètre... Tout ça parce que j'ai voulu me passer de ce foutu handler, en somme. Bref le code est disponible ici

jeudi 31 décembre 2009

Vas-y, montre moi tes doigts ?!

Tu aimes Netfilter mais voilà, tu voudrais bien aussi faire... de l'OS fingerprinting ? C'est possible depuis la version 2.6.31, grâce au module xt_osf qui a été inclu officiellement. Donc voilà comment ça marche, un petit exemple :

  1. insmod ./xt_osf.ko
  2. ./nfnl_osf -f ./pf.os
  3. iptables -I INPUT -j ACCEPT -p tcp -m osf log 0 ttl 2

Tout d'abord un commentaire sur pf.os, c'est le fichier utilisé par packet filter, donc le fichier de définition de p0f, le tool de mister Zalewski. Ensuite on fait un test de connexion, et on voit dans les logs :

Windows 2000:SP4 : 192.168.028.131:2007 -> 192.168.028.124:22 hops=0

L'archive pour le programme userland (nfnl_osf) et les infos sont sur le bleurg de l'auteur du patch initial : http://ioremap.net/projects/osf

mercredi 30 septembre 2009

TCP/IP for dummies

Je ne sais pas pour vous, mais le réseau, je trouve ça assez intéressant. Comment fonctionnent les protocoles, leurs implémentations, etc. Alors voici un petit lien, présentant une implémentation de TCP/IP très légère, mais assez intéressante d'un point de vue didactique. Il s'agit de lwIP (light-weight IP), une stack TCP/IP ne faisant pas de copie de buffer afin de ne pas perdre trop en performances (mais avec une abstraction manquante, car chaque layer peut taper dans la couche sous-jacente), et où les principaux comportements attendus sont implémentés : silly window avoidance, demultiplexage, contrôle de checksum, retransmission rapide, calcul de RTT, contrôle de congestion, etc. La pile propose même une API BSD compliant :) Bon, il s'agit d'un PoC d'universitaire, hein, c'est pas ça qui va remplacer les piles des OS, mais encore une fois, ça se comprend vite et bien.

Ah, oui, le code (C, oeuf corse) tient en moins de 2600 lignes, et le code objet produit pèse 13.5 KiB.

PS : Dernière chose, il n'y a pas de support IPv6. Haaan, la grosse honte.

mercredi 2 septembre 2009

Piccolo-SAN!!!

On m'a pose une question ce matin et je me suis rappele que j'avais ecris un tools a la noix pour l'iSCSI, mais du coup j ai vite cherche 2-3 trucs divers sur "l'intarwebs" ( (c) unpote ) a propos des autres trucs sur les SANs, et j'ai trouve qqes autres trucs marrant a lire:

bref c'est pas nouveau, mais ca fait du bien a relire et ca me donne presque envie de bidouiller 2,3 ameliorations a mon bidule, si je le retrouve grbmlmblmb..

enjoy!

jeudi 27 août 2009

Oh oui, montre-moi ton gros paquet !

Je vais probablement enfoncer des portes ouvertes mais c'est pas grave. Récemment j'ai écouté le trafic d'une machine qui streamait du son via le protocole DAAP (le truc de iTunes) sous un linux (donc une approximation de DAAP en fait, car les specs ne sont pas releasées). Bref, le linux envoie de la musique sur un LAN via le soft rhythmbox. Ça passe par un LAN, et arrive au client. En faisant un coup de tcpdump sur le serveur, je m'aperçois que les datagrammes IP font régulièrement plus de 1500 bytes. Souvent 5 ou 7 KB. Curieux... Je me demande d'où ça vient. Qui plus est, le checksum TCP est incorrect. Vraiment chelou, ça.

$ ip link ls eth0
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:12:3f:71:57:a1 brd ff:ff:ff:ff:ff:ff

La MTU est bien à 1500. Si j'écoute sur le client, je vois bien des paquets fragmentés. Bizarre bizarre. Le switch ferait ça ? Je mirror les ports et j'écoute : paquets fragmentés. Boooon, après avoir cherché à droite à gauche, je tombe sur ces liens :

L'explication est que la fragmentation est réalisée par la carte réseau, hypothèse que j'avais exclue d'emblée, parce que ça me semblait overkill. Et pourtant ! Un patch avec des benches envoyés sur la ml netdev du noyau linux montre que ça améliore significativement les performances (dans le cas où le firmware permet de le faire, bien sûr), et ça semble intégré depuis le 2.6.18.

C'est tout. Je voulais juste poster ça pour éviter aux ignares comme moi de chercher pendant des plombes le pourquoi du comment. Enfin... encore faut-il qu'ils connaissent ce site. :-)

PS : pour le checksum erroné, c'est visiblement parce que la stack TCP/IP sait que le device va regragmenter, et donc invalider le checksum calculé (et en mettre un autre à la place). Donc pas la peine de se fatiguer à le calculer. C'est mon hypothèse, il faudrait que je regarde les sources.

mardi 30 juin 2009

de paquets pour jouer et des tools pour faker

Tel un agent du FB^WWW, tu as en ta possession des informations critiques à ne pas divulger sur tes machines scellées au niveau -42.

Cependant, pour tes analyses à postériori, tu dois mettre à disposition les traces des connexions que tu as relevé. Mais tu sais pertinemment que dans ces traces se trouvent des infos hautement sensibles.

Tu te tournes alors vers l'anonymisation des traces afin de transmettre tes journaux sans aucune anxièté. Et pour cela, tu as à ta disposition les outils

Limite, ca te fait kiffer alors tu joues de plus en plus et même tu te documentes

samedi 21 février 2009

Il etait une fois BGP... et BGP c'est drole!

Une histoire que j ai trouve interessante (subjectif) meme si elle est n'est pas "neuve", le cas est marrant a lire et a comprendre.

L'annonce BGP de Pakistan Telecom qui a annonce un subnet plus specifique de youtube en Fevrier 2008 sur une bonne partie de l' internet poilu avec des choses marrantes a comprendre comme:

comment hijacker proprement pour que (par exemple) Pakistan Telecom puisse rerouter correctement vers youtube si necessaire en evitant que son "path" vers youtube soit pollue par ses annonces illegitimes.

Update!!
un paper qui fourni des infos completes, merci au monsieur anonyme qui a laisse le commentaire
/Update!!

have fun! :)

mardi 13 janvier 2009

C'est dans les vieux pots...

Bon, pour le boulot, je dois coder pas mal de trucs relatifs aux réseaux. Et c'est suite à mes pérégrinations sur le web que je suis tombé sur ce lien. Un vieuuuux lien, de plus de 10 ans d'âge, mais mis à jour, et très intéressant. Il parle notamment des mesures de la qualité d'un réseau, des méthodes à employer, et renvoie vers plein d'autres documentations. Je me régale, personnellement.

Je mets le tag "code", parce que ça file plein d'idées de trucs à coder :-)

Youpla, c'est par ici

mercredi 26 novembre 2008

I had a dream!

Ca semble fortement sympathique et base sur des concepts assez sexy, c'est fait par des gens poilus, ca semble egalement assez fou au niveau de certains choix qui peuvent avoir l'air bizarre mais semblent murement reflechis..

A suivre: http://netifera.com/

lundi 10 novembre 2008

Comment c'est beau Anycast!

Je me suis pose des questions transcendentales ce matin a propos d'Anycast, alors j'ai matte Wikipedia et j'ai trouve une doc toute simple concernant Anycast qui a repondu a mes questions...

Si vous avez des questions a propos d'anycast...

mardi 4 novembre 2008

Fait *wizwiz* avec ton rezal

En étant tombé sur ce truc il y a déjà un ptit moment, je trouvais sympa le visuel. Le problème est que INAV ne gère pas le format netflow. Alors quand on a déjà son archi sous netflow, on peut être intéressé par nvis, dont vous remarquerez (ou pas) la ressemblance.

En creusant un ptit peu plus, on tombe sur la thèse d'un bonhomme qui en parle (entre autre) et nous renvoie sur le toolkit du projet.

Enfin, après vous avoir fait baver, sachez que les sources de ce truc sont introuvables, donc si quelqu'un les a vu passer !@#?

PS : pour ceux qui trouvent que netflow sent pas bon du genou, il y a ce cher sflow, jdis ca comme ca.

vendredi 17 octobre 2008

Détection rapide de protocole layer7

Alors dans le cadre de mon job je suis tombé sur un article qui m'intéresse. Peut-être que ça sera le cas pour toi aussi, ami lecteur. La problématique est la suivante : sur des gros liens (Gbps typiquement), comment reconnaître les applications utilisées ? Ça peut être pour un admin, qui cherche à identifier les flux qui circulent sur son réseau, ou autre.

La technique "de base" consiste à inspecter les payloads à la recherche d'une signature applicative (à la snort, ou qosmos en propriétaire et plus exhaustif). Le "hic", c'est que sur des liens chargés, ça rame sa mère. Ou alors faut se payer la super solution corporate pouic pouic de Qosmos à 50KEUR, avec une bécane de 32 procs, des cartes DAG (Endace) d'acquisition et tout le bousin.

Mais nous, chez Unix4fun, on est pauvres, et on pense à la plèble, alors on écarte cette solution. Durant ma visite du Web je suis donc tombé sur un article pas mal, qui explique comment en 4 ou 5 paquets TCP (hors établissement de la connexion, SYN, SYN/ACK, ACK), on peut taguer un flux comme étant telle ou telle application, avec un taux d'erreur acceptable (de l'ordre de 5%). L'idée est évidemment d'utiliser des mécanismes d'apprentissage statistique (chaînes de Markov, etc) ; mais avec ça on n'est pas avancé, le problème étant de mesurer et d'apprendre sur les bonnes métriques. Ici, on s'inquiète uniquement de la taille des payloads, et du "sens" du paquet (client -> serveur, ou serveur -> client), qui est un facteur discriminant supplémentaire, et indépendant du contexte (type de réseau, type d'appli, besoin de performance, etc).

Bref, c'est ma pause déjeuner au bureau, je vais pas m'attarder.

L'article Early Application Identification

La thèse sur le sujet (même auteur principal) : Classification temps réel d'applications sur l'Internet. Elle se lit vite, et la dernière partie est en français, pour madame Michu, mais sans les formules et un peu allégée.

mardi 12 août 2008

DNS vuln

Maintenant que notre soufflet s'est un peu degonfle concernant la "ouuUUuuUU-mechante-incroyable-youpi-fear-tout-ca" attaque DNS, y a un monsieur sympathique et qui documente toujours super bien ses posts, qui a fait ca.

allez hop on va lire et on se code un tools tranquillou!

mercredi 25 juin 2008

TCP on steroids et encore d'autres trucs

Si toi aussi tu fais du code reseau en ce moment et que tu cherches toute sortes d'idees, tips et ce genre de choses Il n'y a pas longtemps la grande, la celebre USENIX conference a eu lieu avec son lots d'idees a reflechir-o-pompaz.

Peut etre que tu trouvera ce trucs interessant:

http://www.usenix.org/events/usenix08/tech/full_papers/menon/menon_html/index.html

Sinon y a ca qui traine aussi...

enjoy!

mardi 13 mai 2008

Le gros débit du long bidon du débit d'eau de Bobby.

Alors eau et moi là, on bosse tous les deux sur de la capture de paquets, et suite à une n-ième et instructive conversation sur LSF/BPF/Prout/Whatever, je suis tombé sur un site intéressant, pour la comparaison de performances pour les gros, GROS trafics (de l'ordre du Gigabit).

On y trouve une comparaison entre FreeBSD et Linux, un patch (douteux ?) de libpcap, des benches quant au processeur utilisé (apparemment AMD Opteron > Intel Xeon), et même un .config tout fait. Il y a également des articles intéressants sur ce sujet, soumis à des confs.

Pour voir tout ça, il faut jeter un oeil par ici.

- page 1 de 2