Depuis le temps que j’en parlais il fallait que je m’exécute!
Objectif du lab
L’objectif est de montrer l’étendue des fonctions IPv6 First Hop Security maintenant disponible sur nos switchs d’accès 2960-S et 3k. Je ne vais pas à nouveau m’étendre sur le côté indispensable de ces fonctions qu’IPv6 soit déployé ou non! Vous trouverez de nombreux détails ici, là et encore ici.
Description du lab
J’utilise un design classique recommandé dans les CVD (Cisco Validated Designs) à savoir un stack de 3750-X en pur L2 connecté sur un coeur L3 de cat6500 en sup2T via un Etherchannel. Le cat6k jouera le rôle de routeur et serveur officiel et mon 3k devra protéger le lien local d’attaques IPv6 sur l’accès. Vous m’excuserez d’avoir mélangé les topologies physiques et logiques sur le schéma suivant mais je pense que ça reste clair…
Matériel et IOS utilisés
- Un stack de 3750-X en 15.0(1)SE2 – c3750e-universalk9-tar.150-1.SE2.bin
- Un VSS de catalyst 6500-E avec sup2T en 15.0(1)SY1 – s2t54-adventerprisek9-mz.SPA.150-1.SY1.bin
Pour les postes de travail, les petits malins que vous êtes auront peut-être reconnu les MAC CISCO… Je me suis payé le luxe d’utiliser 2 ISR G2 (des 2951) pour jouer le rôle de hosts. Premièrement parce que c’est plus simple pour moi de trouver un routeur qu’un PC 🙂 mais aussi parce que ca va me permettre très simplement de changer les adresses MAC et d’avoir accès en CLI à toutes les fonctions réseau qui me permettront de simuler des attaques.
Configuration initiale
J’ai une configuration vraiment minimaliste sur mes équipements, sans aucune protection IPv6 bien évidemment: 6500-VSS-2T
ipv6 unicast-routing ! vlan 999 name TEST-IPV6-FHS ! interface Port-channel31 switchport switchport trunk allowed vlan 999,1000 switchport mode trunk ! interface Vlan999 description Gateway test IPv6 FHS no ip address ipv6 address 2001:DB8:0:1::1/64
3750-10GE-1
interface GigabitEthernet2/0/1 switchport access vlan 999 switchport mode access spanning-tree portfast ! interface GigabitEthernet3/0/1 switchport access vlan 999 switchport mode access spanning-tree portfast
Tests et résultats
IPv6 RA guard
La fonction RA guard permet de contrôler qui est autorisé à envoyer des Router Advertisements, ainsi que de s’assurer que le contenu des RA est conforme à ce qui est attendu. Le host “GOOD” s’autoconfigure avec le préfixe envoyé par le Catalyst 6500:
GOOD#sh ipv6 interface gigabitEthernet 0/2 | i subnet 2001:DB8:0:1:7281:5FF:FEF6:7DF2, subnet is 2001:DB8:0:1::/64 [EUI/CAL/PRE]
On envoie maintenant un préfixe depuis le host “BAD” et on s’assure d’avoir la préférence maximale au niveau route par défaut.
interface GigabitEthernet0/2 description IPV6 BAD ipv6 address BAD::1/64 ipv6 nd router-preference High
Et on voit que le host GOOD s’autoconfigure également avec le nouveau préfixe BAD::64
GOOD#sh ipv6 interface gigabitEthernet 0/2 | i subnet BAD::7281:5FF:FEF6:7DF2, subnet is BAD::/64 [EUI/CAL/PRE] 2001:DB8:0:1:7281:5FF:FEF6:7DF2, subnet is 2001:DB8:0:1::/64 [EUI/CAL/PRE]
Si on regarde les détails on voit que le host BAD, c’est-à-dire notre hacker, est même préféré car la priorité du RA est High alors que la priorité par défaut est Medium.
GOOD#show ipv6 routers Router FE80::213:5FFF:FED0:1000 on GigabitEthernet0/2, last update 0 min Hops 64, Lifetime 1800 sec, AddrFlag=0, OtherFlag=0, MTU=1500 HomeAgentFlag=0, Preference=Medium Reachable time 0 (unspecified), Retransmit time 0 (unspecified) Prefix 2001:DB8:0:1::/64 onlink autoconfig Valid lifetime 2592000, preferred lifetime 604800 Router FE80::7281:5FF:FEF6:7EA2 on GigabitEthernet0/2, last update 0 min Hops 64, Lifetime 1800 sec, AddrFlag=0, OtherFlag=0, MTU=1500 HomeAgentFlag=0, Preference=High Reachable time 0 (unspecified), Retransmit time 0 (unspecified) Prefix BAD::/64 onlink autoconfig Valid lifetime 2592000, preferred lifetime 604800
On configure maintenant sur notre stack de 3750-X la fonction IPv6 RA Guard pour empêcher les RA venant de tous les ports clients. On ne configure rien depuis le coeur: on connaît l’équipement derrière et autant ne pas s’embêter à complexifier les choses davantage.
interface GigabitEthernet2/0/1 switchport access vlan 999 switchport mode access ipv6 nd raguard spanning-tree portfast ! interface GigabitEthernet3/0/1 switchport access vlan 999 switchport mode access ipv6 nd raguard spanning-tree portfast
On peut voir le résultat sur notre host GOOD qui maintenant ne s’autoconfigure plus qu’avec les RA autorisés:
GOOD#sh ipv6 interface gi0/2 | i subnet 2001:DB8:0:1:7281:5FF:FEF6:7DF2, subnet is 2001:DB8:0:1::/64 [EUI/CAL/PRE]
On peut logguer l’activité RA Guard sur le switch:
3750-10GE-1#debug ipv6 snooping raguard IPv6 snooping - RA guard debugging is on
Et ensuite tout devient clair dans les logs:
*Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 RA received by RA guard on Gi3/0/1 from FE80::7281:5FF:FEF6:7EA2 *Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 option 1 : ND_OPT_SOURCE_LINKADDR *Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 option 3 : ND_OPT_PREFIX_INFORMATION *Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 option 5 : ND_OPT_MTU *Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 !Not a router port: all router messages disallowed *Mar 19 23:24:27.219: SISF[RAG]: Gi3/0/1 vlan 999 ! DROP ROUTER-ADVERT src FE80::7281:5FF:FEF6:7EA2 dst FF02::1 reason = 3
On a des options plus fines pour le RA guard. On va pouvoir autoriser uniquement certains préfixes, certains routeurs, certaines priorités etc. dans les messages RA. Dans la plupart des designs usuels on n’aura certainement pas besoin de ces options: on a un ou 2 ports avec des routeurs et on maîtrise ce qui se passe à ce niveau là (pas de rogue RA possibles). On peut toujours imaginer utiliser ce RA guard “sélectif” pour éviter des erreurs de configurations mais attention à ce que la solution ne soit pas pire que le problème que l’on cherche à résoudre.
IPv6 DHCP Guard
La fonction DHCPv6 guard permet de contrôler les ports sur lesquels des serveurs DHCPv6 sont connectés. Je configure maintenant mon hacker comme serveur DHCPv6
ipv6 dhcp pool POOL-DHCPV6 address prefix BAD:BAD:BAD:BAD::/64 dns-server BAD::BAD domain-name bad.bad ! interface GigabitEthernet0/2 ipv6 dhcp server POOL-DHCPV6
Mon host GOOD est lui configuré comme client DHCPv6 y compris pour l’autoconfiguration de ses adresses (stateful).
GOOD#sh ipv6 interface gi0/2 | i subnet BAD:BAD:BAD:BAD:F589:BA0F:6591:8758, subnet is BAD:BAD:BAD:BAD:F589:BA0F:6591:8758/128 2001:DB8:0:BAD:7281:5FF:FEF6:7DF2, subnet is 2001:DB8:0:BAD::/64 [EUI/CAL/PRE]
On applique simplement une commande pour interdire les messages provenant de serveurs DHCPv6 depuis les ports clients.
interface GigabitEthernet2/0/1 ipv6 dhcp guard ! interface GigabitEthernet3/0/1 ipv6 dhcp guard
Si l’on redémarre notre host GOOD, on voit qu’il n’apprend plus les adresses du serveur DHCPv6 clandestin.
GOOD#sh ipv6 interface gi0/2 | i subnet 2001:DB8:0:BAD:7281:5FF:FEF6:7DF2, subnet is 2001:DB8:0:BAD::/64 [EUI/CAL/PRE]
Là aussi on peut logguer l’activité:
3750-10GE-1#debug ipv6 snooping dhcp-guard IPv6 snooping - DHCP Guard debugging is on
Les logs sont clairs: on filtre les messages DHCPv6 “server” venant de l’interface Gi3/0/1 et on laisse passer les messages DHCPv6 “client” depuis l’interface Gi2/0/1:
*Mar 20 00:16:33.141: SISF[DHG]: Gi2/0/1 vlan 999 DHCP Guard setting sec level to GUARD *Mar 20 00:16:33.141: SISF[DHG]: Gi2/0/1 vlan 999 DHCP Client message for role dhcp client - Permit *Mar 20 00:16:33.141: SISF[DHG]: Gi3/0/1 vlan 999 DHCP Guard setting sec level to GUARD *Mar 20 00:16:33.141: SISF[DHG]: Gi3/0/1 vlan 999 DHCP Server message for role dhcp client - Deny
On ne configure rien sur notre upstream. On pourrait là aussi faire une configuration plus détaillée qui permettrait de filtrer en fonction du contenu du messages DHCPv6.
IPv6 Binding Identity Guard
La fonction IPv6 Binding Identity Guard va permettre de construire une table d’association entre adresses IPv6, adresses MAC et numéros de ports sur le switch, puis de contrôler que les messages NDP sont bien conformes à ce qui est dans cette table (que le host BAD ne tente pas de répondre à un message Neighbor Sollicitation qui ne lui aurait pas été destiné).
Au niveau configuration ici on a tenté de simplifier un maximum les choses en intégrant tout dans des commandes “IPv6 snooping”. Ces commandes IPv6 snooping permettent également d’implémenter RA Guard et DHCPv6 Guard. Les commandes vues plus haut ne sont donc pas forcément nécessaire si vous voulez déployer la totale: je m’explique…
On commence par définir une politique pour l’IPv6 snooping globale sur le switch qui s’appelle TEST-BINDING dans laquelle on va spécifier nos règles de sécurité:
- Les méthodes utilisées pour construire la table de binding (en snoopant les messages DHCP, NDP ou même en regardant les paquets circulant sur le réseau). Cela est fait respectivement avec les commandes “protocol dhcp”, “protocol ndp” et “data-glean”. Notez que par défaut le snooping DHCP et NDP est réalisé pour construire la table, vous ne verrez donc pas les commandes ci-dessous dans votre configuration.
- Le nombre d’adresses utilisées par port (commande “limit address-count”). Attention en IPv6 on a beaucoup plus facilement plus qu’une adresse par port. Faites attention donc si vous tenez absolument à vous assurer qu’il n’y a pas de switch connecté sur le port.
- Le tracking: les entrées dans le cache sont présentes pour une durée de 5 minutes. Ces entrées sont mises à jour continuellement et ce, selon la méthode utilisée pour construire la table de binding. Une fois le timer écoulé, c’est-à-dire si le host connecté à été inactif pendant ce temps, alors par défaut n’importe quel host peut récupérer l’adresse sur un autre port sans aucune vérification préalable. Avec l’option “tracking enable”, le switch va à la fin du timer demander à l’host s’il est toujours vivant (en lui envoyant un message Neighbor Sollicitation). Une réponse de l’host mettra alors à jour la table de binding.
- Le niveau de sécurité (security-level) qui peut être choisi parmi les suivants: “glean” va construire la table de binding mais ne va pas ensuite s’assurer que les échanges sont conformes à cette table. “inspect” va construire la table et ensuite filtrer les NS/NA qui ne correspondraient pas à la table construite. “guard”, qui est le niveau par défaut, va en plus ajouter le filtrage des messages RA et DHCP venant du port. Vous voyez donc ici qu’on peut implémenter RA/DHCPv6 guard simplement avec notre policy IPv6 snooping.
Ici un exemple de configuration (notez que la plupart de ces éléments sont configurés par défaut aussi n’espérez pas voir tout dans votre fichier de configuration):
ipv6 snooping policy TEST-BINDING device-role node protocol dhcp protocol ndp data-glean limit address-count 10 tracking enable security-level guard
J’applique ensuite ma politique IPv6 snooping sur les ports de mon switch:
interface GigabitEthernet2/0/1 ipv6 snooping attach-policy TEST-BINDING ...
Notez qu’il est possible de spécifier sur quels VLANs du port cette règle sera active. Par défaut tous les VLANs sont concernés. Maintenant jetons un coup d’oeil à notre table de binding:
3750-10GE-1#sh ipv6 neighbors binding Binding Table has 3 entries, 3 dynamic Codes: L - Local, S - Static, ND - Neighbor Discovery, DH - DHCP, PKT - Other Packet, API - API created Preflevel flags (prlvl): 0001:MAC and LLA match 0002:Orig trunk 0004:Orig access 0008:Orig trusted trunk 0010:Orig trusted access 0020:DHCP assigned 0040:Cga authenticated 0080:Cert authenticated 0100:Statically assigned IPv6 address Link-Layer addr Interface vlan prlvl age state Time left ND FE80::A8AA:AAFF:FEAA:AAAA AAAA.AAAA.AAAA Gi3/0/1 999 0005 23s REACHABLE 280 s ND FE80::2022:22FF:FE22:2222 2222.2222.2222 Gi2/0/1 999 0005 3mn REACHABLE 108 s ND 2001:DB8:0:1:A8AA:AAFF:FEAA:AAAA AAAA.AAAA.AAAA Gi3/0/1 999 0005 33s REACHABLE 276 s ND 2001:DB8:0:1:2022:22FF:FE22:2222 2222.2222.2222 Gi2/0/1 999 0005 2s REACHABLE 304 s
Ici on voit bien sur chaque port les adresses globales et lien-local des hosts connectés. Quand je vous disais d’être vigilant si vous teniez à appliquer une limite d’adresse IPv6 par port je pense que vous comprenez mieux pourquoi: 2 hosts mais déjà 4 adresses dans la table! 🙂 On voit la méthode utilisée pour construire les différentes entrées présentes ici (NDP – code ND). On voit aussi pour chaque entrée des informations complémentaires: 005 = 004 + 001 – ici les entrées sont sur des ports en mode “access” et les adresses lien-local sont conformes aux adresses MAC.
Maintenant je vais rajouter un host sur le switch sur le port Gi3/0/2 qui va tenter de se faire passer pour notre GOOD toujours connecté sur le port Gi3/0/1. Ce nouvel host va avoir la même adresse MAC et la même adresse IP. Je rappelle que l’ensemble des ports est protégé par notre policy TEST-BINDING.
Le switch détecte que des entrées similaires sont déjà présentes dans la base et va filtrer les messages NA
[10:28:17] VLAN 999, From Gi3/0/2 seclvl [guard], MAC AAAA.AAAA.AAAA: NDP::NA, 1 addresses advertised: IPv6 addr: 2001:DB8:0:1:A8AA:AAFF:FEAA:AAAA, Drop reason=More trusted entry exists
Mais attention, le switch à ce stade ne va pas filtrer le trafic!!! Il filtre exclusivement les messages de contrôle. Par exemple si je ping l’adresse lien-local de la passerelle par défaut, et que j’ai préalablement rempli ma neighbor table avec l’adresse MAC correspondante le trafic va passer:
BAD-2#ping FE80::21C:B0FF:FEB7:D7C0 Output Interface: GigabitEthernet0/2 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to FE80::21C:B0FF:FEB7:D7C0, timeout is 2 seconds: Packet sent with a source address of FE80::A8AA:AAFF:FEAA:AAAA%GigabitEthernet0/2 !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 0/0/4 ms
Rien n’empêche pour le moment notre méchant garçon d’envoyer des paquets sur le réseau avec sa mauvaise adresse IPv6… Et c’est là qu’entre en jeu la fonctionnalité IPv6 source guard (quelle transition!)
IPv6 Source Guard
Si les fonctions IPv6 snooping agissent sur le plan de contrôle, la fonction IPv6 source guard va agir sur le plan de données. On va vérifier que le trafic venant d’un port a des adresses sources conformes avec notre table de binding précédemment construite avec les commandes IPv6 snooping. Personnellement j’aurais même rajouté la commande directement dans notre politique de snooping. Mais on va voir qu’IPv6 source se met en oeuvre très simplement. Tout commence par implémenter une policy Source Guard globale qui n’a quasiment aucune option.
ipv6 source-guard policy TEST-SOURCEGUARD
On peut ajouter 2 options à notre politique (que je n’utilise pas ici):
- Possibilité d’autoriser tout le trafic lien-local avec la commande “permit link-local”
- Possibilité d’interdire tout le trafic provenant d’adresses global auto-configurées avec la commande “deny global-autoconf”
Ensuite on applique bêtement notre politique sur les ports du switch:
int Gi2/0/1 ipv6 source-guard attach-policy TEST-SOURCEGUARD ...
On peut ensuite voir l’impact directement:
BAD-2#ping FE80::21C:B0FF:FEB7:D7C0 Output Interface: GigabitEthernet0/2 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to FE80::21C:B0FF:FEB7:D7C0, timeout is 2 seconds: Packet sent with a source address of FE80::A8AA:AAFF:FEAA:AAAA%GigabitEthernet0/2 ..... Success rate is 0 percent (0/5)
On a maintenant un réseau pas trop mal sécurisé au niveau 2 pour IPv6!
Références
5 commentaires
Bonsoir
Est ce que je peux appliquer ces mécansimes dans un switch virtuel cisco nexus 1000v,car je travaille dans un environnement virtuel .
Bonsoir,
Non, aujourd’hui ces mécanismes ne sont pas supportés sur Nexus 1000v.
A bientot,
Jerome
Comment je peux les implémenter alors,y a t-il un produit open source ?? :s
A reblogué ceci sur Blog Cisco IPv6 and commented:
Ajoutez votre grain de sel personnel… (facultatif)