Tcpdump

From aldeid
Jump to navigation Jump to search
This article needs to be translated
This article has been copied from the old wiki and is in french. It needs to be translated into english. If you wish to participate, please send a mail to (click to reveal email)

Tcpdump

Description

Tcpdump est un sniffeur de paquets réseau, en ligne de commandes. Cet outil est apprécié pour sa rapidité ; les nombreuses informations qu'il faut trier conduisent à utiliser le filtre BPF. Il existe une version graphique, appelée Wireshark.

Installation

Sous Windows

Le plus simple est d'installer la version prévue pour Windows : Windump. Néanmoins, il est possible d'installer tcpdump, en environnement d'émulation Cygwin, avec les librairies libpcap. L'installation par ce biais n'est cependant pas triviale.

Sous Debian

A partir des packages

# apt-get install tcpdump

A partir des sources

Installation préalable de flex et bison
# apt-get install flex bison
Installation préalable de libpcap 0.9.8

Voir libpcap

Installation de tcpdump 3.9.8
# cd /usr/local/src
# wget http://www.tcpdump.org/release/tcpdump-3.9.8.tar.gz
# tar xzvf tcpdump-3.9.8.tar.gz
# cd tcpdump-3.9.8
# ./configure
# make && make install

Utilisation

Syntaxe

La syntaxe de base est la suivante :

Usage: tcpdump [-aAdDeflLnNOpqRStuUvxX] [-c count] [ -C file_size ]
               [ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]
               [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]
               [ -W filecount ] [ -y datalinktype ] [ -Z user ]
               [ expression ]

Le détail des paramètres est détaillé dans les paragraphes qui suivent.

Utilisation de base

Options les plus utilisées

-c {n}
       Sortie après {n} paquets capturés.

-F {file}
       Utilisation d'un fichier externe pour la spécification des filtres.

-i {int}
       Utilise l'interface {int}. Pour connaître la liste des interfaces :
       tcpdump –D.

-l
       Affiche les entrées sur la sortie standard. Ce paramètre n'empêche
       pas l'écriture dans un fichier (paramètre –w). Par exemple
       tcpdump –l | tee test.txt

-n
       Permet de ne pas convertir les adresses et les numéros de ports.
       Ainsi, l'adresse "82.240.150.190" ne sera pas résolue en "aldeid.com"
       et le port "80" ne sera pas résolu en "www".

-S
       Affichage des numéros de séquence en absolu (et non en relatif).
       Par défaut, l'affichage de tcpdump est relatif.

-v(v)
       Mode (très) verbeux.

-X
       Affichage supplémentaire des trames en héxadécimal.
Note
Il est possible d’envoyer le résultat de tcpdump à un autre programme, tcpdumpx (disponible à l’adresse suivante : ftp://ftp.porcupine.org/pub/debugging/ack-corruption.tar.gz), afin de détailler l’affichage héxadécimal. L’exmple suivant illustre cette utilisation.
# tcpdump -lnx -s 1500 | ./tcpdumpx

 :58:30.459994 178.147.72.193.2898 > 127.0.0.1.80: tcp 30 [ttl 1]

   IP_HDR=20 IP_OPT=0 TCP_HDR=20 TCP_OPT=0 DATA=30 FLAGS=PUSH ACK 

   IP_HDR   45  00  00  46  1d  16  00  00  01  06 
           vhl tos len len id  id  off off ttl pro 
   IP_HDR   22  47  b2  93  48  c1  7f  00  00  01 
           sum sum src src src src dst dst dst dst 
   TCP_HDR  0b  52  00  50  4f  ee  06  a7  3a  d1 
           src src dst dst seq seq seq seq ack ack 
   TCP_HDR  bb  00  50  18  02  00  4c  9d  00  00 
           ack ack off flg win win sum sum urp urp 
   DATA     47  45  54  20  2f  63  67  69  2d  62 
            G   E   T       /   c   g   i   -   b  
   DATA     69  6e  2f  70  65  72  6c  2e  65  78 
            i   n   /   p   e   r   l   .   e   x  
   DATA     65  20  48  54  54  50  2f  31  2e  30 
            e       H   T   T   P   /   1   .   0  

Capture dans un fichier

Pour capturer des trames dans un fichier (test.cap), utilisez tcpdump comme suit :

# tcpdump –lnS –w test.cap

Interprétation d'un fichier de capture

Comme le montrent les exemples qui suivent, l'interprétation des trames réseau produites par tcpdump est relativement aisée.

Exemple 1

# tcpdump –S –vv –nX –r test.cap
…
09:09:49.865015 IP (tos 0x0, ttl  64, id 600, offset 0, flags [DF], proto: TCP (6)
, length: 429) 192.168.182.1.1213 > 192.168.182.128.80: P 3041339763:3041340152
(389) ack 1113674227 win 64240
       0x0000:  4500 01ad 0258 4000 4006 4920 c0a8 b601  E....X@[email protected].....
       0x0010:  c0a8 b680 04bd 0050 b547 2973 4261 51f3  .......P.G)sBaQ.
       0x0020:  5018 faf0 74e9 0000 4745 5420 2f20 4854  P...t...GET./.HT
       0x0030:  5450 2f31 2e31 0d0a 486f 7374 3a20 3139  TP/1.1..Host:.19
       0x0040:  322e 3136 382e 3138 322e 3132 380d 0a55  2.168.182.128..U
       0x0050:  7365                                     se
…

On y retrouve les princiaples informations relatives à IP (TOS, TTL, ID, etc.) et TCP (SPORT, DPORT, SEQ, ACK, etc.). Par ailleurs, le paramètre –X permet de faire apparaître un champ données riche en informations (requête http de type GET à destination de l’hôte 192.168.182.128).

Exemple 2

# tcpdump –S –vv –nX –r test.cap
…
09:09:50.272152 IP (tos 0x0, ttl  64, id 0, offset 0, flags [DF], proto: TCP (6),
length: 52) 192.168.182.128.80 > 192.168.182.1.1217: S, cksum 0x7129 (correct), 
1124979725:1124979725(0) ack 2466204173 win 5840 <mss 1460,nop,nop,sackOK,nop,
wscale 3>
       0x0000:  4500 0034 0000 4000 4006 4cf1 c0a8 b680  E..4..@[email protected].....
       0x0010:  c0a8 b601 0050 04c1 430d d40d 92ff 4a0d  .....P..C.....J.
       0x0020:  8012 16d0 7129 0000 0204 05b4 0101 0402  ....q)..........
       0x0030:  0103 0303                                ....
…

Tableau récapitulatif des exemples

Paramètre Exemple 1 Exemple 2
IP TOS (Type Of Service) 0x0 0x0
TTL (Time To Live) 64 64
IPID (id) 600 0
Offset 0 0
Flags Don't Fragment [DF] [DF]
Protocole (val. décimale) TCP (6) TCP (6)
Length (longueur totale paquet) 429 52
Source 192.168.182.1 192.168.182.128
Destination 192.168.182.128 192.168.182.1
TCP Port source 1213 80
Port destination (http) 80 1217
Flags TCP PA (push+ack) SA (syn+ack)
Numéro de séquence 3041339763 1124979725
Prochain numéro de séquence 3041340152 1124979725
Numéro d'acquittement 1113674227 2466204173
Données GET / http/1.1 … -
Taille de fenêtre 64240 5840
Somme de contrôle (Checksum) - 0x7129 (correct)
Options (vide) MNNSNW

Filtres BPF

Filtres de base

La syntaxe des filtres de base dans tcpdump s’utilise de la manière suivante :

proto[start:end]

où :

  • proto représente le protocole (par exemple ip ou tcp) ;
  • start représente le numéro de byte de début (le premier valant 0) ;
  • end représente le numéro de byte de fin.

Ainsi, tcp[13] fait référence au byte numéro 13 (douzième byte) d'un paquet TCP (les drapeaux TCP).

La notation ip[4:2] fait référence au paramètre "id" d'un paquet IP (voir structure des paquets IP et TCP).

Seuls les filtres les plus utilisés sont présentés ici.

host
   Permet de filtrer par nom de domaine.
   Exemple : tcpdump host google.com n'intercepte que les paquets à destination ou en provenance de google.com.
net
   Permet de ne capturer que les paquets concernant un réseau particulier.
   Exemple : tcpdump net 192.168 permet de filtrer les paquets émis ou destinés à une adresse IP commençant par 192.168.
   Exemple : tcpdump dst net 212.27 permet de filtrer les paquets du réseau 212.27.0.0.
 port
   Permet de n'intercepter que les paquets originaires ou à destination d'un port particulier.
   Exemple : tcpdump port 25 permet de surveiller les communications sur le port 25 (smtp).
   Remarque :
   Le filtre port n'autorise pas la spécification d'une plage. Si vous voulez filtrer le trafic sur la plage de ports
   source tcp/udp 20-80, utilisez le filtre avancé suivant :
     (tcp[0:2]>20 and tcp [0:2]<80) || (udp[0:2]>20 and udp[0:2]<80)
 src
   Le mot clé src peut précéder les filtres afin restreindre les captures à un traffic provenant d'un hôte, d'un réseau
   ou d'un port. S'applique à host, net, port.
 dst
   Le mot clé dst peut précéder les filtres afin restreindre les captures à un traffic à destination d'un hôte, d'un
   réseau ou d'un port. S'applique à host, net, port.
 Filtre par protocole
   Filtrage par protocole (tcp, udp, arp, udp, icmp, etc.)
   Exemple : tcpdump –eth1 arp permet de ne capturer que les trames du protocole ARP.
 not ou !
   Le mot clé spécifie le contraire de ce qui suit
   Exemple : tcpdump –i eth1 not ssh signifie que l'on n'affiche pas ce qui concerne ssh (peut être utile dans le cas où
   l'on a effectué la capture à partir d'un shell ssh)
 and ou &&
   Permet d'aditionner des filtres
   Exemple : tcpdump –i eth1 
 or ou ||
   Permet d'aditionner des filtres

Filtres avancés (IP)

Il existe également des filtres avancés. Ceux-ci permettent de créer des filtres personnalisés, à partir des en-têtes des protocoles.

Pour rappel, 1 byte = 8 bits. Dans les notations qui suivent, ip[8] représente par exemple le byte numéro 8 d'un paquet IP (c'est-à-dire le le 9ème byte car la numérotation des bytes commence à 0), soit TTL, dont la taille fait exactement 8 bits, soit 1 byte. Le premier byte commence à 0.

     0                   1                   2                   3
bits 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  0 |Version|  IHL  |      TOS      |          Long. totale         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 32 |        Identification         |Flags|     Position fragment   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 64 |       TTL     |    Protocole  |        Checksum en-tête       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 96 |                          Adresse source                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 |                       Adresse destination                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 |                             Options                           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192 |                             Données ...                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                        Rappel de l'en-tête IP

Par ailleurs, la valeur dans le filtre BPF est exprimée en numérique.

 Filtre TTL
   Par exemple, un filtre sur les paquets ayant un TTL de 64 s'écrit comme suit :
     tcpdump –r fichier.cap 'ip[8]=64'

Filtres avancés (TCP)

Les filtres avancés TCP vont généralement concerner la combinaison des drapeaux au byte 13 (voir le rappel de l'en-tête TCP ci-dessous).

     0                   1                   2                   3
bits 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  0 |          Port source          |       Port destination        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 32 |                         Numéro séquence                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 64 |                     Numéro accusé réception                   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 96 | Long. | Reserv|C|E|U|A|P|R|S|F|       Taille fenêtre          |
    |en-tête|       |W|C|R|C|S|S|Y|I|                               |
    |  TCP  |       |R|E|G|K|H|T|N|N|                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 |            Checksum           |       Pointeur urgence        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 |                    Options                |    Remplissage    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192 |                             Données ...                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                         Rappel de l'en-tête TCP

Pour ne faire apparaître par exemple que les paquets de type SYN, la valeur de tcp[13] sera de 2.

                            [  byte TCP #13 ]
                            +-+-+-+-+-+-+-+-+
                            |C|E|U|A|P|R|S|F|
                            |W|C|R|C|S|S|Y|I|
                            |R|E|G|K|H|T|N|N|
                            +-+-+-+-+-+-+-+-+
              Seulement SYN |0|0|0|0|0|0|1|0| => 2 en décimal
                            +-+-+-+-+-+-+-+-+
                    SYN/ACK |0|0|0|1|0|0|1|0| => 18 en décimal
                            +-+-+-+-+-+-+-+-+

Pour faire apparaître les paquets SYN ainsi que les paquets SYN/ACK, nous avons la possiblilité d'écrire :

# tcpdump -vv -r test.cap '(tcp[13] = 2) || (tcp[13] = 18)'

Nous verrons cependant dans le paragraphe qui suit que l'utilisation d'un masque est plus appropriée.

Les masques

Les exemples vus ci-dessus découpent les protocoles par bytes. Par exemple, tcp[13] désigne le byte numéro 13 d'un paquet TCP, c'est-à-dire les drapeaux CWR, ECE, URG, ACK, PSH, RST, SYN et FIN. Ces filtres s'appliquent facilement si le critère filtré a une taille équivalente à un ou plusieurs bytes pleins.

Dès lors que l'on souhaite appliquer un filtre sur un critère dont la taille ne vaut pas un byte plein, la méthode vue précédemment devient beaucoup moins triviale. Ainsi par exemple, ip[1] désigne le premier byte d'un paquet IP, c'est-à-dire la version et la longueur de l'en-tête IP (IHL). Si nous avons besoin de filtrer sur le critère IHL, nous pouvons utiliser les masques.

Le masque permet de spécifier bit par bit les parties du byte à conserver (1). Les valeurs sur lesquelles le masque vaut 0 pourront indifféremment prendre n'importe quelle valeur.

                                 [   byte IP #0  ]
                                 +-+-+-+-+-+-+-+-+
                                 |Version|  IHL  |
                                 +-+-+-+-+-+-+-+-+
          Exemple (ver=4, IHL=5) |0|1|0|0|0|1|0|1|
                                 +-+-+-+-+-+-+-+-+
                Masque (sur IHL) |0|0|0|0|1|1|1|1| ==> 15 en décimal
                                 +-+-+-+-+-+-+-+-+
                        Résultat |0|0|0|0|0|1|0|1| ==> 5 en décimal
                                 +-+-+-+-+-+-+-+-+
Note
La valeur de IHL est exprimée en nombre de blocs de 32 bits. Par exemple, un paquet IP sans données (en-tête) étant composé de 5 blocs de 32 bits, la taille de IHL vaudra 5 (en binaire 0101)

Le masque s'écrit ici comme suit :

$ tcpdump –r test.cap 'ip[0] & 15 = 5'

(le signe "=" peut être remplacé selon les besoins par "<", ">", "<=", ">=" ou "!=")

Si nous souhaitons faire apparaître les paquets contenant au moins le flag SYN, le masque a appliquer est calculé de la manière suivante :

                                 [ byte TCP #13  ]
                                 +-+-+-+-+-+-+-+-+
                                 |C|E|U|A|P|R|S|F|
                                 |W|C|R|C|S|S|Y|I|
                                 |R|E|G|K|H|T|N|N|
                                 +-+-+-+-+-+-+-+-+
          Exemple (SYN, SYN/ACK) |0|0|0|1|0|0|1|0|
                                 +-+-+-+-+-+-+-+-+
                    Masque (SYN) |0|0|0|0|0|0|1|0| ==> 2 en décimal
                                 +-+-+-+-+-+-+-+-+
                        Résultat |0|0|0|0|0|0|1|0| ==> 2 en décimal
                                 +-+-+-+-+-+-+-+-+
# tcpdump -vv -r test.cap 'tcp[13] = 2'
09:20:26.384722 IP (tos 0x0, ttl  64, id 3587, offset 0, flags [DF], proto: TCP(6), length:
52) 192.168.182.1.1147 > 192.168.182.133.4444: S, cksum 0xdc0b (correct),
1052856473:1052856473(0) win 65535 <mss 1460,nop,wscale 3,nop,nop,sackOK>

De même, pour obtenir les paquets accusant réception à une demande de connexion (SYN/ACK), la valeur de tcp[13] devra être égale à 18.

# tcpdump -vv -r test.cap 'tcp[13] = 18'
09:20:26.385074 IP (tos 0x0, ttl  64, id 0, offset 0, flags [DF], proto: TCP (6), length: 52)
192.168.182.133.4444 > 192.168.182.1.1147: S, cksum 0x9946 (correct), 1604308036:1604308036(0)
ack 1052856474 win 5840 <mss 1460,nop,nop,sackOK,nop,wscale 3>
Paquets non fragmentés

Dans cet exemple, nous souhaitons rechercher les paquets fragmentés. Pour cela, rappelons le contenu du byte IP #6 (Flags + début de offset).

                    bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     48 |Flags|     Position fragment   |
                        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                        [     byte #6   |     byte #7   ]

Un paquet non fragmenté a une valeur de byte IP #6 (surligné en noir) égale à "01000000" en binaire, soit 64 en décimal. Néanmoins, et bien que l’utilisation du filtre ip[6]=64 fonctionne, nous nous efforcerons de recourir aux filtres.

             Don't
            fragment
Reserv. ___    |    ___ More fragments
           \   |   /
            \  |  /
        bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         48 |0 1 0|0 0 0 0 0                |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             Flags      Position fragment


Le filtre à appliquer s’écrit ip[6] & 224 = 64. Il est expliqué ci-dessous.

                        [     byte #6   ]
                        +-+-+-+-+-+-+-+-+
                        |0 1 0|0 0 0 0 0| ...
                        +-+-+-+-+-+-+-+-+
                 masque |1 1 1|0 0 0 0 0| ... => 224 en décimal
                        +-+-+-+-+-+-+-+-+
                résulat |0 1 0|0 0 0 0 0| ... => 64 en décimal
                        +-+-+-+-+-+-+-+-+
Paquets fragmentés

Un paquet fragmenté (mais qui n'est pas le dernier) a une valeur de byte IP #6 (surligné en noir) qui commence par la chaîne binaire "001". En revanche, la suite de la chaîne correspondant au offset ne peut être définie (Pour rappel, le offset resprésente la position du paquet fragmenté dans le datagramme IP initial. Cette valeur vaut zéro pour le premier paquet fragmenté, mais a une valeur positive pour tous les autres fragments).

             Don't
            fragment
Reserv. ___    |    ___ More fragments
           \   |   /
            \  |  /
        bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         48 |0 0 1|? ? ? ? ?                |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             Flags      Position fragment

Le filtre à appliquer pour ne faire apparaître que les paquets fragmentés (à l’exception du dernier) s’écrit donc ip[6] & 224 = 32, et est expliqué ci-dessous :

                        [     byte #6   ]
                        +-+-+-+-+-+-+-+-+
                        |0 0 1|? ? ? ? ?| ...
                        +-+-+-+-+-+-+-+-+
                 masque |1 1 1|0 0 0 0 0| ... => 224 en décimal
                        +-+-+-+-+-+-+-+-+
                résulat |0 0 1|0 0 0 0 0| ... => 32 en décimal
                        +-+-+-+-+-+-+-+-+
Note
Nous pouvons également écrire le filtre de la manière suivante :
ip[6] & 32 != 0

Le dernier paquet fragmenté quant à lui, a les 3 premiers bits du byte IP #6 (surligné en noir) à 0.

             Don't
            fragment
Reserv. ___    |    ___ More fragments
           \   |   /
            \  |  /
        bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         48 |0 0 0|? ? ? ? ?                |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             Flags      Position fragment

Le filtre à appliquer est expliqué ci-dessous et s’écrit : ip[6]&224=0.

                        [     byte #6   ]
                        +-+-+-+-+-+-+-+-+
                        |0 0 0|? ? ? ? ?| ...
                        +-+-+-+-+-+-+-+-+
                 masque |1 1 1|0 0 0 0 0| ... => 224 en décimal
                        +-+-+-+-+-+-+-+-+
                résulat |0 0 0|0 0 0 0 0| ... => 0 en décimal
                        +-+-+-+-+-+-+-+-+