DÉMARRAGE
Pour commencer ce TP, lancez la machine virtuelle dans virtualbox. Lors
de l’apparition du bureau,
L’architecture construite correspond à la topologie suivante :
Dans ce TP nous allons uniquement nous intéresser au réseau local formé
par les équipements ws1, ws2, ws3, ws4, switch1, switch2 et inner_gw. A
l’apparition des interfaces de conteneurs, sélectionnez la fenêtre
correspondant aux conteneurs ws1, ws2, ws3 et ws4 et vérifiez en utilisant
la commande ifconfig que les adresses IP associées aux conteneurs sont
bien les suivantes :
tom@ws1:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:c0:a8:01:01
inet addr:192.168.1.1 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:63 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:7838 (7.8 KB) TX bytes:0 (0.0 B)
Nous allons pour les exemples qui suivent supposer que pour les
commutateurs :
l’interface connectée au réseau intermédiaire est eth1,
l’interface connectée à ws1 sur switch1 et à ws3 sur switch2 est
eth0
l’interface connectée à ws2 sur switch1 et à ws4 sur switch2 est
eth2.
Tapez ensuite les commandes suivantes (la commande arptables indique
une erreur, cette erreur est normale et n'empêche pas de continuer le TP):
student@Labtainer-VM:~$ sudo modprobe 8021q
student@Labtainer-VM:~$ sudo modprobe br_netfilter
student@Labtainer-VM:~$ sudo modprobe ebtables
student@Labtainer-VM:~$ sudo arptables
Si vous ne voulez pas réaliser la partie vlan, à partir du répertoire
utilisateur sur switch1 et switch2 exécutez les commandes suivantes :
ubuntu@switch1:~$ ./create_vlans.sh
ubuntu@switch2:~$ ./create_vlans.sh
Si vous ne voulez pas réaliser la partie filtrage MAC, à partir du répertoire
utilisateur sur switch1 et switch2 exécutez les commandes suivantes :
ubuntu@switch1:~$ ./filter_mac.sh
ubuntu@switch2:~$ ./filter_mac.sh
VLANS (OPTIONNEL, DURÉE 30MN)
Pour commencer nous allons construire une topologie à base de vlans
permettant de placer ws1 et ws3 dans le même vlan et ws2 et ws4 dans
un deuxième vlan.
Les deux commutateurs sont connectés par un réseau intermédiaire
commun. Afin de permettre à switch2 de savoir à quel vlan a été associé
une trame reçue par switch1 et réciproquement on va utiliser le protocole
802.1Q entre les deux switchs.
On commence par déclarer deux vlans associés à l’interface eth1 au
travers de la commande vconfig. Cette commande va définir deux vlans.
Nous choisissons le numéro 2 pour le premier vlan et le numéro 5 pour le
second. Ces identifiants (2 et 5) seront les valeurs d’identifiants de vlan
utilisées dans les étiquettes 802.1Q échangées entre les deux
commutateurs.
ubuntu@switch1:~$ sudo vconfig add eth1 2
ubuntu@switch1:~$ sudo vconfig add eth1 5
Ces deux commandes vont par ailleurs créer deux sous interfaces de
l’interface eth1 correspondant aux deux vlans. La
commande ifconfig permet d’activer ces interfaces qui sont éteintes par
défaut. Les interfaces eth1.2 et eth1.5 correspondent aux deux sous-
interfaces que nous venons de créer.
ubuntu@switch1:~$ sudo ifconfig eth1.2 up
ubuntu@switch1:~$ sudo ifconfig eth1.5 up
On réalise la même opération sur le commutateur switch2. Attention, les
correspondances entre interfaces peuvent être différentes sur les deux
commutateurs.
ubuntu@switch2:~$ sudo vconfig add eth1 2
ubuntu@switch2:~$ sudo vconfig add eth1 5
ubuntu@switch2:~$ sudo ifconfig eth1.2 up
ubuntu@switch2:~$ sudo ifconfig eth1.5 up
Pour le moment nos commutateurs ne commutent rien. Pour s’en
persuader il suffit de lancer un ping de ws1 vers ws3. On constate
qu’aucune réponse n’est reçue.
tom@ws1:~$ ping –c 2 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
--- 192.168.1.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1030ms
Afin d’activer la commutation, nous allons définir deux processus de
commutation : l’un pour le vlan 2 que nous appelons vlan2 et l’un pour le
vlan 5 que nous appelons assez logiquement vlan5 . Ces deux processus
de commutation sont créés au travers de la commande brctl .
ubuntu@switch1:~$ sudo brctl addbr vlan2
ubuntu@switch1:~$ sudo brctl addbr vlan5
Nous faisons cette opération sur les deux commutateurs :
ubuntu@switch2:~$ sudo brctl addbr vlan2
ubuntu@switch2:~$ sudo brctl addbr vlan5
Nous définissons maintenant quelles interfaces vont être commutées par
chaque processus. Sur le commutateur switch1 on associe les
interfaces eth0 et eth1.2 à vlan2 et les interfaces eth2 et eth1.5 à vlan5 .
Pensez à adapter les identifiants des interfaces en fonction de votre
configuration.
ubuntu@switch1:~$ sudo brctl addif vlan2 eth0
ubuntu@switch1:~$ sudo brctl addif vlan5 eth2
ubuntu@switch1:~$ sudo brctl addif vlan2 eth1.2
ubuntu@switch1:~$ sudo brctl addif vlan5 eth1.5
On fait le même travail sur switch2 :
ubuntu@switch2:~$ sudo brctl addif vlan2 eth0
ubuntu@switch2:~$ sudo brctl addif vlan5 eth2
ubuntu@switch2:~$ sudo brctl addif vlan2 eth1.2
ubuntu@switch2:~$ sudo brctl addif vlan5 eth1.5
Chaque processus de commutation apparaît au niveau du système comme
une interface virtuelle. Afin que le processus fonctionne il convient
d’activer chacun. Ceci peut se faire comme nous l’avons vu plus tôt au
travers de la commande ifconfig :
ubuntu@switch1:~$ sudo ifconfig vlan2 up
ubuntu@switch1:~$ sudo ifconfig vlan5 up
Ceci est réalisé sur les deux commutateurs :
ubuntu@switch2:~$ sudo ifconfig vlan2 up
ubuntu@switch2:~$ sudo ifconfig vlan5 up
On peut maintenant vérifier la configuration des vlans sur switch1 et
switch2:
On peut vérifier si tout ceci fonctionne en tentant des communications
entre équipements du même vlan et en vérifiant avec un analyseur de
protocole ( tcpdump ) que rien n’est reçu par les membres de l’autre vlan:
Sur ws1 :
tom@ws1:~$ ping -c 1 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.090 ms
--- 192.168.1.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.090/0.090/0.090/0.000 ms
Sur ws2 :
mary@ws2:~$ ping -c 1 192.168.2.2
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_seq=1 ttl=64 time=0.148 ms
--- 192.168.2.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.148/0.148/0.148/0.000 ms
Sur le commutateur switch1:
On peut observer le trafic 802.1Q sur l’interface eth1 . Pour cela on lance
un ping sur ws1 vers ws3:
tom@ws1:~$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.081 ms
Et on lance une capture de trame sur l’interface eth1 de switch1 :
ubuntu@switch1:~$ sudo tcpdump -e -n -i eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
12:35:40.939062 02:42:c0:a8:01:01 > 02:42:c0:a8:03:01, ethertype 802.1Q
(0x8100), length 102: vlan 2, p 0, ethertype IPv4, 192.168.1.1 >
192.168.1.2:
ICMP echo request, id 308, seq 83, length 64
12:35:40.939096 02:42:c0:a8:03:01 > 02:42:c0:a8:01:01, ethertype 802.1Q
(0x8100), length 102: vlan 2, p 0, ethertype IPv4, 192.168.1.2 >
192.168.1.1:
ICMP echo reply, id 308, seq 83, length 64
Chaque ligne correspond ici à la capture d’une trame. Dans celles-ci on
remarque la valeur du champ ethertype ( 0x8100 ) définissant qu’il s’agit ici
de trames de type IEEE 802.1Q c'est-à-dire portant une étiquette. La
valeur brute de cette étiquette ne nous est pas donnée mais le logiciel
nous indique que le vlan d’appartenance a l’identifiant 2 . Ceci est logique
puisque nous observons ici une communication entre ws1 et ws3, tous
deux membres du vlan 2.
Si on répète cette opération sur l’interface eth0 , on peut constater que le
trafic capturé alors ne comporte pas d’étiquette mais suit le format IEEE
802.1D. L’étiquette est introduite par le processus de
commutation vlan2 sur switch1. Cette étiquette est utilisée par switch2
pour déterminer le vlan d’origine de la trame et ainsi limiter sa diffusion
aux membres du vlan 2 (c'est-à-dire ws3). Avant l’émission de la trame
vers ws3, celle-ci est remise dans le format 802.1D.
Afin de vérifier que l’isolation fonctionne correctement on lance une
capture de trame sur ws2 puis sur ws3 on lance un ping en broadcast. Ces
paquets sont diffusés dans une trame dont l’adresse de destination est
l’adresse MAC de broadcast.
mary@ws2:~$ sudo tcpdump -n -e ip
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
alice@ws3:~$ ping -b 192.168.1.255
WARNING: pinging broadcast address
PING 192.168.1.255 (192.168.1.255) 56(84) bytes of data.
EBTABLES (OPTIONNEL, DURÉE 30MN)
INTRODUCTION
Avant de commencer, nous allons configurer inner_gw afin qu’elle serve
de passerelle entre les réseaux au niveau IP. Ceci nous permettra de
mettre en oeuvre l’attaque. Pour cela définissez les vlans sur inner_gw de
la même façon que nous l’avions fait sur les commutateurs switch1 et
switch2 :
admin@inner_gw:~$ sudo vconfig add eth1 2
admin@inner_gw:~$ sudo vconfig add eth1 5
admin@inner_gw:~$ sudo ifconfig eth1.2 up
admin@inner_gw:~$ sudo ifconfig eth1.5 up
admin@inner_gw:~$ sudo ifconfig eth1.2 192.168.1.253 netmask 255.255.255.0
admin@inner_gw:~$ sudo ifconfig eth1.5 192.168.2.253 netmask 255.255.255.0
On a par ailleurs préconfiguré ws1, ws2, ws3 et ws4 afin que les routes par
défaut soient cohérentes avec cette configuration. Ainsi sur ws1 et ws3:
tom@ws1:~$ netstat -rn
Kernel IP routing table
EBTABLES
Dans cette partie nous allons étudier l’outil ebtables qui sous linux permet
de contrôler le trafic au niveau 2 et voir comment il peut être utilisé afin
de mettre en oeuvre la politique définie dans la vidéo.
Comme bon nombre de mécanismes de filtrage intégrés au noyau
linux, ebtables utilise le concept de chaine. Une chaine est une politique
de filtrage que l’on peut associer à différents points de passage des unités
de donnée dans la pile protocolaire existant sous linux. Une chaine
comprend généralement un certain nombre de règles, chaque règle
décrivant le lien entre un ensemble de conditions portant sur l’unité de
donnée et une ou plusieurs actions. Une chaine est généralement associée
à une action par défaut. Dans le cas d’ebtables, plusieurs chaines sont
prédéfinies pour le filtrage. La chaine INPUT est utilisée pour traiter les
trames à destination du système filtrant. La chaine OUTPUT est utilisée pour
traiter les trames ayant pour origine le système. Enfin la
chaine FORWARD est utilisée pour traiter les trames reçues par le système
mais dont il n’est pas le destinataire. L’action par défaut pour ces trois
chaines et l’autorisation. La figure 1 ci dessous donne le positionnement
de ces chaines par rapport à des communications traitées par un
équipement réseau.
Les règles utilisées par ebtables peuvent porter des conditions sur :
Les interfaces d’entrée et sortie. Ces conditions s’expriment au
travers des options –i pour l’interface d’entrée et –o pour l’interface
de sortie.
Les valeurs des champs des trames :
o Les adresses MAC sources et destination. Ces conditions
s’expriment au travers des options –s pour la source et –
d pour la destination. Il est possible de faire suivre l’adresse
d’un masque sous la forme adresse/masque.
o Le champ longueur/protocole. Ces conditions s’expriment au
travers de l’option –p .
Comme dans tous les systèmes de filtrage inspirés d’iptables, les
conditions peuvent être niées en utilisant le caractère ‘!’ devant la valeur
d’une condition. Ainsi la condition -p ! 0x0800 défini une valeur de champ
type différente de la valeur hexadécimale 0800.
IMPLÉMENTATION DE LA POLITIQUE DU COURS
La politique vue dans le cours est la suivante :
Afin de traiter de manière identique les trames à destination du
commutateur (chaine INPUT ) et celles commutées par celui-ci
(chaine FORWARD ), nous allons utiliser une chaine tierce afin de ne pas
répéter les mêmes règles de filtrage deux fois. Nous appelons celle-
ci MAC_CHECK . Elle est créée au travers de la commande suivante qui utilise
l’option –N afin de créer une nouvelle chaine.
ubuntu@switch1:~$ sudo ebtables -N MAC_CHECK
ubuntu@switch2:~$ sudo ebtables -N MAC_CHECK
Nous allons maintenant définir une action par défaut pour cette politique.
L’option -P indique une modification de l’action par défaut pour la chaine
qui suit. Cette action est donnée dans le troisième paramètre. Elle peut
être DROP pour le rejet ou ACCEPT pour l’autorisation.
ubuntu@switch1:~$ sudo ebtables -P MAC_CHECK DROP
ubuntu@switch2:~$ sudo ebtables -P MAC_CHECK DROP
Nous définissons ensuite une règle pour que cette nouvelle chaine soit
utilisée pour toutes les trames reçues.
ubuntu@switch1:~$ sudo ebtables –A FORWARD –j MAC_CHECK
ubuntu@switch1:~$ sudo ebtables –A INPUT –j MAC_CHECK
ubuntu@switch2:~$ sudo ebtables –A FORWARD –j MAC_CHECK
ubuntu@switch2:~$ sudo ebtables –A INPUT –j MAC_CHECK
L’option –j permet de faire en sorte que la chaine MAC_CHECK soit «
appelée » pour chaque trame depuis les chaines FORWARD et INPUT .
Nous allons maintenant définir les règles faisant partie de la
chaine MAC_CHECK . Nous désirons tout d’abord que les trames en
provenance de A et V (c'est-à-dire reçues par l’interface eth2 et eth0) et
qui possèdent une adresse MAC correcte soient autorisées. Ceci est
exprimé au travers des options –i spécifiant l’interface de réception et –
s spécifiant l’adresse source. L’option –j ACCEPT indique l’action. Comme
on peut le constater tout type de condition non utilisé implique que le
champ correspondant peut prendre n’importe quelle valeur.
ubuntu@switch1:~$ sudo ebtables -A MAC_CHECK -i eth2 -s 02:42:c0:a8:02:01 -
j ACCEPT
ubuntu@switch1:~$ sudo ebtables -A MAC_CHECK -i eth0 -s 02:42:c0:a8:01:01 -
j ACCEPT
L’action par défaut de MAC_CHECK est l’interdiction ce qui signifie que pour
le moment une trame qui est destinée à A serait bloquée si elle est reçue
au travers de eth1. Nous allons donc définir une règle afin d’autoriser ce
type de trame explicitement.
ubuntu@switch1:~$ sudo ebtables -A MAC_CHECK -i eth1.2 -j ACCEPT
ubuntu@switch1:~$ sudo ebtables -A MAC_CHECK -i eth1.5 -j ACCEPT
On peut construire une politique similaire pour switch2 :
ubuntu@switch2:~$ sudo ebtables -A MAC_CHECK -i eth0 -s 02:42:c0:a8:03:01 -
j ACCEPT
ubuntu@switch2:~$ sudo ebtables -A MAC_CHECK -i eth2 -s 02:42:c0:a8:04:01 -
j ACCEPT
ubuntu@switch2:~$ sudo ebtables -A MAC_CHECK -i eth1.2 -j ACCEPT
ubuntu@switch2:~$ sudo ebtables -A MAC_CHECK -i eth1.5 -j ACCEPT
TEST DE LA POLITIQUE DE FILTRAGE
Pour tester la politique, vérifions d’abord que les équipements peuvent
toujours communiquer entre eux s’ils utilisent une adresse MAC légitime.
tom@ws1:~$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.081 ms
Nous pouvons également tenter une usurpation d’adresse MAC. Pour cela
sur inner_gw on lance une capture de trame :
admin@inner_gw:~$ sudo tcpdump –i eth1 -n -e
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
Puis on tente une usurpation sur ws1 par exemple, les trames sont
envoyées à destination de inner_gw :
tom@ws1:~$ sudo macof –n 2 –e 02:42:c0:a8:05:01
4a:6c:4f:4e:9d:40 2:42:c0:a8:5:1 0.0.0.0.34218 > 0.0.0.0.54954: S
55931254:55931254(0) win 512
7b:24:c:3:7f:ba 2:42:c0:a8:5:1 0.0.0.0.14469 > 0.0.0.0.30760: S
872411776:872411776(0) win 512
On peut alors vérifier que les trames sont bien bloquées par switch1.