Tcpdump
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.
# 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 +-+-+-+-+-+-+-+-+
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 +-+-+-+-+-+-+-+-+
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 +-+-+-+-+-+-+-+-+