<?xml version="1.0" encoding="utf-8"?>
<entry title="Capturer les paquets qui passent sur le réseau">
<date>2008-12-17</date>
<update_date>2009-03-27</update_date>
<content>
<p>Lire les
<wikipedia name="Paquet (réseau)">paquets</wikipedia> qui passent sur
le réseau est une activité indispensable pour l'étudiant qui apprend
les réseaux informatiques, pour l'administrateur système qui débogue
un problème, pour le chercheur qui rassemble des statistiques ou
simplement pour le curieux qui veut s'instruire. Mais avant de pouvoir les
lire et les analyser, il faut les capturer. Quels sont les outils
disponibles ?</p>
<p>Tout le monde connait et utilise <wikipedia>tcpdump</wikipedia>,
qui permet à la fois de capturer et de décoder les paquets. Pour un
coup d'&#x153;il rapide, c'est parfait. Mais pour des études plus
lourdes, il est souvent recommandé de séparer la <emphasis>capture</emphasis> des données
(qui doit pouvoir tourner longtemps, sans trop charger la machine) de
leur <emphasis>analyse</emphasis> (souvent très consommatrice en ressources et qui peut
parfaitement être faite hors-ligne). Cet article se focalise sur les
outils de capture, l'analyse étant faite ailleurs, avec un programme
d'exploration comme <wikipedia>Wireshark</wikipedia> ou bien avec un
programme qu'on a développé soi-même, <link local="libpcap-python">par
exemple en Python</link>.</p>
<p>Un bon logiciel de capture doit pouvoir :
<enum>
<item>Tourner longtemps, tout en écrivant dans des fichiers, de
préférence en sachant passer d'un fichier à l'autre lorsque les
fichiers de capture deviennent trop gros, ou bien à l'issue d'un
certain délai.</item>
<item>Pouvoir filtrer les événements intéressants, de façon à ne pas
stocker n'importe quoi sur le disque. À cette fin, tous les logiciels
de capture disposent d'un <wikipedia name="Langage dédié">mini-langage</wikipedia> permettant de dire quels sont
les « événements intéressants ». La puissance expressive de ce langage
est un des principaux critères qui distinguent ces logiciels.</item>
<item>Ne pas trop charger la machine (c'est une autre raison pour
laquelle le filtrage est important mais attention, il peut lui-même
consommer beaucoup de ressources), au cas où elle fasse tourner des
services de production, et afin d'éviter de perdre des paquets (ce que
font les logiciels de capture lorsqu'ils n'arrivent plus à
suivre).</item>
</enum>
Presque tous les logiciels de capture enregistrement au format
« pcap », celui de la <wikipedia name="Pcap">libpcap</wikipedia>.</p>
<p>Voyons les logiciels possibles. L'ancêtre
<wikipedia>tcpdump</wikipedia>, très connu de tous les administrateurs
réseaux, reste parfaitement utilisable pour
cette tâche. Son option <computer>-w</computer> permet d'enregistrer
les événements, qui pourront ensuite être lus par tout logiciel
capable de lire du pcap (y compris tcpdump lui-même, avec l'option
<computer>-r</computer>).
<code>
% tcpdump -i eth2 -w mydata.pcap
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 96 bytes
[Control-C]
41 packets captured
41 packets received by filter
0 packets dropped by kernel
</code>
Et <computer>mydata.pcap</computer> peut être analysé ensuite à
loisir. tcpdump dispose de nombreuses options qui peuvent être utiles
pour la capture comme <computer>-c</computer> (s'arrêter après un
nombre donné de paquets) ou <computer>-C</computer> (donne une taille
maximale au fichier), même si elles sont moins perfectionnées que
celles des logiciels récents.</p>
<p>tcpdump dispose d'un langage de filtrage, nommé
<wikipedia name="Filtre BPF">BPF</wikipedia> et qui permet d'exprimer des choses simples
comme « uniquement les paquets venant de
<computer>192.0.2.3</computer> » ou « uniquement les paquets à
destination du port 80 » ou encore « uniquement les paquets à
destination de <computer>2001:db8:1::deca:fbad</computer>,
<emphasis>et</emphasis> venant du port 53 ». Voici cette dernière :
<code>
% tcpdump -i eth2 -w mydata.pcap \
            dst host 2001:db8:1::deca:fbad and \
            src port 53
</code>
</p>
<p>L'analyseur Wireshark a des mécanismes de décodage des paquets bien
plus riches que ceux de tcpdump. Il vient avec un programme en ligne
de commande, <computer>tshark</computer> qui peut être utilisé pour la
capture :
<code> 
% tshark -i eth2  -w mydata.pcap 
Capturing on eth2
340 
[Control-C]
</code>
Notez l'affichage en temps réel du nombre de paquets capturés, bien
pratique. Ses options de capture sont plus perfectionnées que celles
de tcpdump, par exemple <computer>-a</computer> permet de stopper
celle-ci après qu'un temps donné se soit écoulé. En mode « plusieurs
fichiers », les noms des fichiers sont plus parlants qu'avec tcpdump, etc.</p>
<p>tshark dispose d'un langage de filtrage plus
perfectionné, documenté dans <foreign><link
url="http://www.wireshark.org/docs/dfref/">Display Filter
Reference</link></foreign>. Par exemple, si on regarde les requêtes
<wikipedia name="Domain Name System">DNS</wikipedia>, tshark peut
filtrer avec des règles comme « <link
url="http://www.wireshark.org/docs/dfref/d/dns.html">uniquement les
réponses</link> ». Mais attention, il ne s'agit que de filtre
d'affichage, le langage des filtres de capture est bien plus
sommaire, c'est le même que celui de tcpdump (on peut trouver plein
d'exemples <link url="http://wiki.wireshark.org/CaptureFilters">sur le
site de Wireshark</link>). La raison de cette limitation est
probablement que la capture doit aller vite, sans nécessiter de copier
des paquets depuis le <wikipedia name="Noyau de système d'exploitation">noyau</wikipedia> et que le langage
BPF, lui, peut tourner entièrement dans le noyau.</p>
<p>Pour des options de capture encore plus riches, on peut regarder
<link url="http://packages.debian.org/pcaputils">pcapdump</link>. Il
fait partie d'un groupe de programmes utilisant pcap, développés
spécialement pour <wikipedia>Debian</wikipedia>, mais qui peuvent être
compilés sur d'autres systèmes. Par exemple, sur
<wikipedia>Gentoo</wikipedia>, il faut installer la bibliothèque <link url="http://judy.sourceforge.net/">Judy</link>
(<computer>emerge judy</computer>) puis simplement utiliser
<unix>make</unix> pour compiler. Ensuite, on copie les exécutables
(dans <computer>src/</computer>) à la main.</p>
<p>Les forces de pcapdump, un logiciel spécialisé dans la capture,
sont notamment ses capacités de tourner en <wikipedia
name="Daemon">démon</wikipedia> (l'option n'est pas évidente à
trouver, c'est <computer>-P</computer>, par exemple <computer>pcapdump
-P /var/run/pcapdump.opid -C $(pwd)/dns.pcapdump</computer>), de
changer de fichier sur plusieurs critères, de nommer les fichiers de
capture selon un modèle qu'on choisit, d'échantilloner en
n'enregistrant qu'un paquer sur N, etc. Il peut aussi lire ces options
dans un fichier de configuration, dont voici un exemple qui lit les
paquets DNS (port 53) et change de fichier tous les jours :
<code>
device=eth0
bpf="udp and port 53"
interval=86400
snaplen=512
promisc=0
filefmt=/var/tmp/pcapdump/eth0.%Y%m%d.%H%M.%S.pcap
mode=0600
owner=smith
group=root
</code></p>
<p>Si on veut des filtres de capture très sophistiqués (tous les
logiciels précédents se limitent au langage <wikipedia name="Filtre BPF">BPF</wikipedia>), il faut les
programmer soi-même ou bien utiliser un logiciel spécialisé comme
<link url="https://www.dns-oarc.net/tools/dnscap">dnscap</link>. Ce
programme dispose de filtres de capture spécifiques au <wikipedia
name="Domain Name System">DNS</wikipedia>, par exemple on peut
sélectionner uniquement les réponses et seulement celles qui sont
négatives (<computer>NXDOMAIN</computer>, ce domaine n'existe
pas).</p>
<p>dnscap n'a pas de documentation en ligne, tout est dans la page de
manuel incluse dans la distribution. Sa compilation n'est pas toujours
évidente. Sur <wikipedia>Gentoo</wikipedia> ou
<wikipedia>Debian</wikipedia>, il faut ajouter dans le
<computer>Makefile</computer> :
<code>
PORTLIBS= /usr/lib/libresolv.a
BINDLIB=-lbind9
</code>
Voici un exemple d'utilisation de dnscap, pour ne capturer que les
paquets de réponses (<computer>-sr</computer>), et seulement si la
réponse est négative (nom de domaine inexistant,
<computer>-ex</computer>) et juste si la question concernait le
domaine <computer>sources.org</computer> :
<code>
% dnscap -x 'sources\.org' -i eth0 -sr -g -ex 
</code>
Comme pcapdump, il permet de changer automatiquement de fichier de
capture en cours de route (par exemple avec <computer>-t
86400</computer> pour tourner tous les jours), ce qui le rend
utilisable pour des études sur le long terme.</p>
<p>Contrairement aux filtres BPF, le filtrage fait par dnscap est
effectué dans l'espace utilisateur, pas dans le
<wikipedia name="Noyau de système d'exploitation">noyau</wikipedia>. Il a donc fallu copier le paquet dans
ledit espace et effectuer des opérations parfois complexes avant de
décider de le garder ou pas. Les capacités de capture peuvent donc
s'en ressentir.</p>
<p>Une fois les paquets capturés, il existe plusieurs programmes tout
faits pour afficher des informations sur ces captures ou pour les
modifier. Par exemple, <wikipedia>Wireshark</wikipedia> est livré avec
deux utilitaires en ligne de commande très
pratiques. <computer>editcap</computer> permet de sélectionner une
partie d'une capture, en indiquant les numéros d'ordre des paquets
qu'on veut garder :
<code>
% editcap -r large.pcap small.pcap 1-1000
Add_Selected: 1-1000
Inclusive ... 1, 1000
</code>
gardera les mille premiers paquets du fichier
<computer>large.pcap</computer>. <computer>capinfos</computer> permet
d'obtenir des informations sur un fichier de trace :
<code>
% capinfos small.pcap 
...
File encapsulation: Ethernet
Number of packets: 1000 
File size: 210439 bytes
Data size: 371542 bytes
Capture duration: 23.338821 seconds
Start time: Mon Mar  2 21:41:57 2009
End time: Mon Mar  2 21:42:21 2009
...
</code></p>
<p>Et si on développe un programme soi-même ? C'est assez facile, dans
plusieurs langages de programmation. On peut ainsi choisir les
critères de capture à volonté mais il faut prendre garde aux
performances : beaucoup de paquets peuvent arriver en très peu de
temps.</p>
<p>En langage <wikipedia name="C (langage)">C</wikipedia>, <wikipedia
name="Pcap">libpcap</wikipedia>, maintenue par les responsables de
tcpdump, est une solution très répandue, très bien documentée, et qui marche bien. Écrire un programme de capture est assez simple.</p>
<p>Voici un exemple du squelette d'un tel programme (montrant la
capture mais pas l'écriture sur disque<!-- TODO: la tester -->), <file
name="sniff-only.c"/>. Il se compile, par exemple, avec :
<code>
% gcc -Wall -o sniff -lpcap sniff-only.c
</code>
</p>
<p>Un bon article d'introduction à la libpcap, et à la définition de filtres de capture est <foreign><link url="http://recursos.aldabaknocking.com/libpcapHakin9LuisMartinGarcia.pdf">Programming with Libpcap - Sniffing the network from our own application</link></foreign>.</p>
<p>Pour la programmation en C, une alternative à pcap est <link
url="https://www.dns-oarc.net/tools/ncap">ncap</link>, que je n'ai pas
testé. Il semble que son format de stockage soit incompatible avec pcap.</p>
<p>Il existe d'autres programmes de capture que je n'ai pas testés :
<enum>
<item><link url="http://gitorious.org/grok">Grok</link></item>
<item><link url="http://www.wireshark.org/docs/man-pages/dumpcap.html">dumpcap</link> qui, comme tshark, fait partie de Wireshark.</item>
</enum></p>
</content>
</entry>
