Tcpdump

De The Linux Craftsman
Aller à la navigation Aller à la recherche

Introduction

La commande tcpdump permet de voir le trafique qui circule sur une machine. Vous pouvez l'utiliser pour :

  • vous assurer que certain paquet arrive sur une machine (eg. ICMP)
  • voir les modifications sur les entêtes (eg. NAT, PAT, ...)
  • vérifier que le messages ont les bonnes entêtes (eg. header HTTP présent)
  • ...

tcpdump va littéralement dumper (afficher de manière brute) les entêtes et même le contenu des messages. Vous pouvez également rediriger la sortie dans un fichier pour faire une exploitation graphique grâce à Wireshark

Voici quelques options intéressantes de tcpdump :

Option Description
-nn Ne convertie pas les adresses IP, les protocoles et numéro de port en noms
-vv Sortie verbeuse pour avoir des détails sur les champs des paquets capturés
-i Permet de spécifier le nom d'une interface
-K Ne pas vérifier la somme de contrôle des paquets
-A Affiche le contenu des paquets en ASCII

Pour les exemples suivants, nous allons considérer le réseau ci-dessous :

                                     (NAT)
               192.168.100.0/24        |        192.168.20.0/24                 < RESEAU
  +--------+                      +----+---+                    +-----------+
  |   PC   +----------------------+Firewall+--------------------+Serveur Web|   < MACHINES
  +--------+                      +----+---+                    +-----------+
192.168.100.2          192.168.100.200 | 192.168.20.254         192.168.20.253  < IP
bridge100                       enp0s5 | enp0s6                 enp0s5          < INTERFACES

Réception d'un message ICMP

Depuis le serveur web, nous allons pinger le PC :

[root@web ~]# ping 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq=1 ttl=63 time=0.969 ms
64 bytes from 192.168.100.2: icmp_seq=2 ttl=63 time=1.83 ms
64 bytes from 192.168.100.2: icmp_seq=3 ttl=63 time=1.30 ms

Sur le PC :

[root@pc ~]# tcpdump -nn -vv -i bridge100 icmp
tcpdump: listening on bridge100, link-type EN10MB (Ethernet), snapshot length 524288 bytes

18:50:15.952573 IP (tos 0x0, ttl 63, id 20778, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.200 > 192.168.100.2: ICMP echo request, id 2, seq 1, length 64
18:50:15.952666 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84, bad cksum 0 (->f08d)!)
    192.168.100.2 > 192.168.100.200: ICMP echo reply, id 2, seq 1, length 64

On peut voir le premier paquet :

18:50:15.952573 IP (tos 0x0, ttl 63, id 20778, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.200 > 192.168.100.2: ICMP echo request, id 2, seq 1, length 64
Champ Valeur
source 192.168.100.200
destination 192.168.100.2
protocole ICMP
message echo request

Et la réponse :

18:50:15.952666 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84, bad cksum 0 (->f08d)!)
    192.168.100.2 > 192.168.100.200: ICMP echo reply, id 2, seq 1, length 64
Champ Valeur
source 192.168.100.2
destination 192.168.100.200
protocole ICMP
message echo reply

Vision du NAT

Même échange que précédemment mais vue du firewall :

  • Depuis l'interface WAN (enp0s5) :
[root@fw ~]# tcpdump -i enp0s5 -nn -vv icmp
dropped privs to tcpdump
tcpdump: listening on enp0s5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:57:14.097239 IP (tos 0x0, ttl 63, id 7787, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.200 > 192.168.100.2: ICMP echo request, id 3, seq 1, length 64
19:57:14.097436 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.2 > 192.168.100.200: ICMP echo reply, id 3, seq 1, length 64

Comme dans l'exemple précédent, on voit les même adresses IP source et destination avec les même messages.

  • Depuis l'interface DMZ (enp0s6) :
[root@fw ~]# tcpdump -i enp0s6 -nn -vv icmp
dropped privs to tcpdump
tcpdump: listening on enp0s6, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:59:49.945852 IP (tos 0x0, ttl 64, id 14013, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.20.253 > 192.168.100.2: ICMP echo request, id 4, seq 1, length 64
19:59:49.946053 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.100.2 > 192.168.20.253: ICMP echo reply, id 4, seq 1, length 64

En revanche, côté DMZ on voit bien les adresses privées (réseau 192.168.20.0/24)

Champ Valeur
source 192.168.20.253
destination 192.168.100.2
protocole ICMP
message echo request

Paquet HTTP

Dans ce cas nous allons observer, depuis le firewall, un échange HTTP lors d'une authentification de type Basic :

[root@fw- ~]# tcpdump -i enp0s6 -nn -vv tcp and  port 80
dropped privs to tcpdump
tcpdump: listening on enp0s6, link-type EN10MB (Ethernet), snapshot length 262144 bytes

20:15:35.260983 IP (tos 0x2,ECT(0), ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 433)
    192.168.100.2.52603 > 192.168.20.253.80: Flags [P.], cksum 0x08fb (correct), seq 1:382, ack 1, win 2058, options [nop,nop,TS val 2639168716 ecr 1471888403], length 381: HTTP, length: 381
	GET /secure/ HTTP/1.1
	Host: 192.168.100.200
	User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
	Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
	Accept-Encoding: gzip, deflate
	Connection: keep-alive
	Upgrade-Insecure-Requests: 1
/.../
20:15:35.262355 IP (tos 0x2,ECT(0), ttl 64, id 7701, offset 0, flags [DF], proto TCP (6), length 709)
    192.168.20.253.80 > 192.168.100.2.52603: Flags [P.], cksum 0x0321 (correct), seq 1:658, ack 382, win 507, options [nop,nop,TS val 1471888405 ecr 2639168716], length 657: HTTP, length: 657
	HTTP/1.1 401 Unauthorized
	Date: Mon, 25 Dec 2023 19:15:42 GMT
	Server: Apache/2.4.57 (Rocky Linux)
	WWW-Authenticate: Basic realm="Secure vraiment !"
	Content-Length: 381
	Keep-Alive: timeout=5, max=100
	Connection: Keep-Alive
	Content-Type: text/html; charset=iso-8859-1
	
	<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
	<html><head>
	<title>401 Unauthorized</title>
	</head><body>
	<h1>Unauthorized</h1>
	<p>This server could not verify that you
	are authorized to access the document
	requested.  Either you supplied the wrong
	credentials (e.g., bad password), or your
	browser doesn't understand how to supply
	the credentials required.</p>
	</body></html>
/.../
20:15:42.860058 IP (tos 0x2,ECT(0), ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 484)
    192.168.100.2.52606 > 192.168.20.253.80: Flags [P.], cksum 0xa478 (correct), seq 1:433, ack 1, win 2058, options [nop,nop,TS val 3792843510 ecr 1471896002], length 432: HTTP, length: 432
	GET /secure/ HTTP/1.1
	Host: 192.168.100.200
	User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
	Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
	Accept-Encoding: gzip, deflate
	Connection: keep-alive
	Upgrade-Insecure-Requests: 1
	Authorization: Basic YnJ1dGVmb3JjZTpwYXNzd29yZA==

L'échange est tronqué pour des raison de lisibilité mais on voit clairement l'échange entre le PC est le serveur web.

Pour résumer

  • le PC demande une ressource sécurisée au serveur web :
GET /secure/ HTTP/1.1
  • le serveur web précise que la ressource est sécurisé et demande une authentification en précisant le domaine (ici Secure vraiment !):
HTTP/1.1 401 Unauthorized
...
WWW-Authenticate: Basic realm="Secure vraiment !"
GET /secure/ HTTP/1.1
...
Authorization: Basic YnJ1dGVmb3JjZTpwYXNzd29yZA==

On peut facilement le retrouver en allant sur des site pour décoder le base64...