L'Internet Rapide et Permanent - Le protocole SNMP

Le protocole SNMP

Christian Caleca

Vous disposez d'une connexion permanente et rapide… et maintenant, vous êtes perdu dans la technique…

Cette série « L'Internet Rapide et Permanent », que Christian Caleca nous a aimablement autorisés à reproduire, est là pour répondre à quelques-unes de ces questions. Cet article parlera du protocole SNMP.

N'hésitez pas à commenter cet article ! Commentez

- Titre : L'Internet Rapide et Permanent - Le protocole SNMP

- Auteur : Christian Caleca

- Parution : 3 octobre 2010

- Mise à jour : 28 mars 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2010 Christian Caleca. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Le principe

- II-A. Présentation générale

- II-A-1. Un agent sur chaque équipement

- II-A-2. Un « manager » sur la station d'administration

- II-B. Pratiquement…

- II-C. Organisation

- II-C-1. Conclusion provisoire

- III. Le protocole

- III-A. Les multiples versions

- III-B. Le protocole lui-même

- IV. Installation des services SNMP

- IV-A. Le pack « snmpd »

- IV-A-1. Contenu du pack

- IV-A-2. Première configuration

- IV-A-3. Vérification

- IV-B. Le pack « snmp »

- IV-B-1. Contenu

- IV-B-2. Vérification

- V. Les MIB

- V-A. C'est quoi une MIB ?

- V-B. Structure d'une MIB

- V-B-1. Illustration

- V-C. La « BRIDGE-MIB »

- V-D. Mais encore…

- V-D-1. Interro surprise 1

- V-E. Et en mode graphique ?

- VI. En savoir un peu plus

- VI-A. Les versions de SNMP

- VI-A-1. Les communautés et leurs privilèges

- VI-A-1-a. Les « view »

- VI-A-1-b. Les « group »

- VI-A-1-c. Les « access »

- VI-A-1-d. Le « com2sec »

- VI-A-1-e. Particularité Debian

- VI-B. C'est compris ?

- VI-B-1. Interro surprise 2

- VII. Analyse du protocole

- VII-A. snmpget

- VII-B. snmpwalk

- VII-C. snmpbulkwalk

- VIII. Exercice pratique

- VIII-A. Le problème

- VIII-B. Que dit SNMP ?

- VIII-B-1. dot1dTpFdbAddress

- VIII-B-2. dot1dTpFdbPort

- VIII-B-2-a. Le port 0

- VIII-B-2-b. Les ports 23 et 24

- VIII-C. Un début de solution

- VIII-C-1. Premier essai

- VIII-C-2. Deuxième essai

- VIII-C-3. Troisième essai

- VIII-C-3-a. L'adresse MAC

- VIII-C-3-b. La solution définitive (?)

- VIII-D. Pour finir

- IX. Les réponses

- IX-A. Interro surprise 1

- IX-B. Interro surprise 2

- X. Remerciements Developpez

I - Introduction

Comme son nom voudrait le faire croire, Simple Network Management Protocol est un protocole « simple » destiné à gérer des équipements informatiques, à distance ou non.

Ce n'est probablement pas un protocole primordial pour un petit réseau local, nous verrons tout de même qu'il peut rendre quelques services.

Il permet principalement de :

- visualiser une quantité pouvant être impressionnante d'informations concernant le matériel, les connexions réseau, leur état de charge ;

- modifier le paramétrage de certains composants ;

- alerter l'administrateur en cas d'évènements considérés comme graves ;

- et d'autres choses encore…

Le tout à distance, via le réseau. Bref, grâce à ce protocole, un administrateur peut avoir la maitrise de tout son réseau et de son parc informatique, sans quitter son bureau climatisé (les bureaux des administrateurs sont toujours climatisés, à cause du matériel informatique qui ne supporte pas bien la chaleur).

Miraculeux ? Pas vraiment. Simple ? Pas vraiment non plus.

SNMP est-il vraiment un protocole incontournable pour l'administrateur ? N'y a-t-il pas d'alternatives ?

La réponse est toute personnelle, n'engage que moi et j'en assume toute la responsabilité : l'administrateur doit pouvoir se passer de SNMP dans la plupart des cas, d'autres outils existent et qui rendent les services habituellement souhaités, souvent avec moins de risques de sécurité et plus de souplesse. Ces outils, comme l'excellent zabbix pour ne citer que lui, proposent des agents installables sur la plupart des OS connus, qui sont souvent aussi efficaces sinon plus, que les agents SNMP. Nous verrons d'ailleurs que la configuration d'un agent SNMP sur GNU/Linux n'est pas si simple.

SNMP trouve toutefois sa place dans de nombreux cas, à commencer par certaines « boites noires » qui proposent un agent SNMP et ne permettent pas d'y installer d'autres agents, comme les switchs, les points d'accès Wi-Fi et autres routeurs. Il est également relativement facile, pour peu que l'on ait assimilé un tant soit peu ce protocole, de développer un outil de supervision s'appuyant sur les agents SNMP, nous en verrons un tout petit exemple pour illustrer le propos.

Finalement, il n'est pas inutile de connaitre ce protocole si l'on a à faire de la supervision.

Ce chapitre n'est pas destiné aux administrateurs qui souhaitent maitriser ce protocole, mais plutôt aux curieux qui voudraient le découvrir et le mettre en œuvre dans des situations simples.

II - Le principe

II-A - Présentation générale

Une machine informatique, quelle que soit sa fonction, a généralement beaucoup de choses à dire. Elle le dit le plus souvent discrètement, si bien que peu de gens l'entendent.

La plupart de ses utilisateurs ne l'écoutent pas, sauf quand elle se met à hurler ou à faire la gueule, ce qui est tout de même assez rare. Elle hurle de diverses façons, une alarme sonore, par exemple, lorsqu'elle est en surchauffe, un écran bleu pour Windows, lorsque le noyau se plante irrémédiablement, elle fait la gueule, par exemple, lorsqu'elle refuse simplement de démarrer… Le reste du temps, elle chuchote divers indicateurs d'état, et certaines remarques, qu'elle consigne généralement dans les logs, sorte de journaux intimes, que, finalement, assez peu de gens consultent.

Les administrateurs sont les seuls à s'y intéresser. Vous serez peut-être surpris de voir à quel point votre machine vous parle. Dans Windows™, vous avez au moins quatre journaux, que vous pouvez rendre plus ou moins verbeux, mais c'est bien sûr sous GNU/Linux que vous découvrirez le mieux tout ce qu'une machine a à dire. L'objectif étant ici de parler de SNMP, nous n'entrerons pas plus dans ces détails. Sachez, si ce n'est pas encore le cas, que sous GNU/Linux, vous avez deux répertoires fortement intéressants :

- /var/log qui contient tous les journaux tenus par votre machine ;

- /proc qui est en fait un espace RAM dans lequel vous retrouverez une infinité de compteurs, d'indicateurs, de variables, drapeaux et d'autres choses encore.

Il y a enfin des informations dont le système ne se soucie pas obligatoirement, mais qui existent, remontées directement par le « firmware »(1), par exemple la température du processeur, la vitesse de rotation des ventilateurs.

Dans tout ceci, il y a une foule d'informations qui intéressent les administrateurs et dont ils aimeraient disposer à distance via le réseau. Il est clair que lorsque le parc contient plusieurs centaines de machines, c'est tout de même plus agréable de disposer de toutes les informations en temps réel et de façon centralisée.

De plus, l'administrateur peut apprécier de pouvoir régler tel ou tel paramètre sans avoir à se déplacer sur le site de la machine concernée.

SNMP est exactement conçu pour répondre à ces besoins.

II-A-1 - Un agent sur chaque équipement

Chaque équipement que l'on voudra « manager » à distance devra disposer d'un agent SNMP. Cet agent est un serveur, c'est-à-dire qu'il reste à l'écoute d'un port particulier : le port UDP 161.

La principale fonction de cet agent est de rester à l'écoute des éventuelles requêtes que l'administrateur lui enverra. Lorsqu'il recevra une requête, il y répondra, s'il y est autorisé. Plus exactement, il répondra si la requête est émise par une entité autorisée. Autrement dit, cet agent est là pour écouter des requêtes et y répondre.

L'agent devra éventuellement pouvoir agir sur l'environnement local, si l'administrateur souhaite modifier un paramètre.

Par ailleurs, l'agent SNMP pourra éventuellement émettre des alertes de sa propre initiative, s'il a été configuré pour cette besogne. Par exemple, il pourra émettre une alerte si le débit sur une interface réseau atteint une valeur considérée par l'administrateur comme critique. Il peut y avoir une multitude d'alertes possibles, suivant la complexité de l'agent. La température du processeur, le taux d'occupation des disques durs, le taux d'occupation CPU…

On pourra trouver des agents SNMP sur des hôtes (ordinateurs), mais aussi sur des routeurs, des ponts, des switches…

II-A-2 - Un « manager » sur la station d'administration

L'administrateur, sur sa machine d'administration, dispose d'un outil dit « manager ». C'est avant tout un client, dans la mesure où c'est lui qui envoie les requêtes aux divers agents SNMP du réseau. Il devra aussi disposer d'une fonction serveur, car il doit rester à l'écoute des alertes que les divers équipements sont susceptibles d'émettre à tout moment.

Un petit dessin… Tous les équipements disposent d'un agent SNMP, la station d'administration dispose du « manager » :

Dans un tel cas, l'administrateur peut, en théorie, observer le comportement de la totalité de son réseau depuis sa station d'administration. C'est vrai pour un LAN, c'est aussi vrai pour un WAN (entendez par là que l'équipement à administrer peut se trouver géographiquement très loin).

Les « boites noires » (routeurs, switches…) sont équipées éventuellement d'un agent SNMP (c'est une question de prix).

Pour les serveurs et les stations, il existe probablement un logiciel à installer, quel que soit le système (sérieux). Pour GNU/Linux : « NET-SNMP » (ou « UCD-SNMP »), Windows XP Professionnel et suivants (versions serveur a fortiori) permettent d'installer un agent SNMP.

Le Manager dispose d'un serveur qui reste à l'écoute, sur le port UDP 162, des éventuels signaux d'alarme (traps). Certains logiciels de supervision utilisant SNMP sont célèbres dans le monde du logiciel propriétaire (commercial, privateur, etc.), qui n'ont pas d'équivalent dans le monde du logiciel libre.

En revanche, il reste parfaitement possible d'exploiter SNMP dans le bon vieux mode de la ligne de commande, avec des outils plus « eye candy » comme MRTG, RRDTool, CACTI ou même Zabbix (qui peut faire d'autres choses aussi, avec un agent spécifique), ou avec des scripts qui feront exactement ce que l'on désire, si besoin est.

II-B - Pratiquement…

Juste pour donner un exemple, voyons ce que ça donne, si, depuis une machine GNU/Linux, nous interrogeons l'agent SNMP d'une station Windows XP (ou Vista, ou 7).

Nous réalisons ceci avec un outil dont GNU/Linux a le secret, et que nous verrons plus loin. Sa particularité est de produire une sortie strictement illisible pour le non-initié. Il s'agit de snmpwalk.

Le but n'est pas ici de tout comprendre, mais juste de donner une idée des informations que l'on peut obtenir. La sortie faisant 1577 lignes, nous n'en verrons que quelques-unes.

# Quelques infos sur la machine et son OS :
SNMPv2-MIB::sysDescr.0 = STRING: Hardware: x86 Family 15 Model 2 Stepping 4
AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1
(Build 2600 Uniprocessor Free)
...
# Le type de carte réseau :
IF-MIB::ifDescr.2 = STRING: D-Link DFE-528TX PCI Adapter
- Miniport d'ordonnancement de paquets
...
#Quelques infos sur la configuration IP :
IP-MIB::ipAdEntAddr.127.0.0.1 = IpAddress: 127.0.0.1
IP-MIB::ipAdEntAddr.192.168.0.10 = IpAddress: 192.168.0.10
IP-MIB::ipAdEntIfIndex.127.0.0.1 = INTEGER: 1
IP-MIB::ipAdEntIfIndex.192.168.0.10 = INTEGER: 2
IP-MIB::ipAdEntNetMask.127.0.0.1 = IpAddress: 255.0.0.0
IP-MIB::ipAdEntNetMask.192.168.0.10 = IpAddress: 255.255.255.0
...
RFC1213-MIB::ipRouteNextHop.0.0.0.0 = IpAddress: 192.168.0.250
...
#Les ressources de mémoire de masse :
HOST-RESOURCES-MIB::hrStorageDescr.2 = STRING: C:\ Label:  Serial Number d803c0ad
HOST-RESOURCES-MIB::hrStorageDescr.3 = STRING: D:\
HOST-RESOURCES-MIB::hrStorageDescr.4 = STRING: E:\ Label:DATA  Serial Number 10822ea3
HOST-RESOURCES-MIB::hrStorageDescr.5 = STRING: F:\
HOST-RESOURCES-MIB::hrStorageDescr.6 = STRING: G:\ Label:ZIP-100  Serial Number 1de00d03
...
# Les imprimantes installées :
HOST-RESOURCES-MIB::hrDeviceDescr.1 = STRING: HP DeskJet 600
HOST-RESOURCES-MIB::hrDeviceDescr.2 = STRING: HP DeskJet 550C
...
# Les services en cours d'exécution :
HOST-RESOURCES-MIB::hrSWRunName.1516 = STRING: « rundll32.exe"
HOST-RESOURCES-MIB::hrSWRunName.1520 = STRING: « OLFSNT40.EXE"
HOST-RESOURCES-MIB::hrSWRunName.1820 = STRING: « NAVAPW32.EXE"
HOST-RESOURCES-MIB::hrSWRunName.1836 = STRING: « spampal.exe"
HOST-RESOURCES-MIB::hrSWRunName.2016 = STRING: « rundll32.exe"
HOST-RESOURCES-MIB::hrSWRunName.2128 = STRING: « msimn.exe"
...
# Les applications installées !!!
HOST-RESOURCES-MIB::hrSWInstalledName.9 = STRING: « Ethereal 0.9.8"
HOST-RESOURCES-MIB::hrSWInstalledName.10 = STRING: « Exodus Jabber Client (remove only)"
HOST-RESOURCES-MIB::hrSWInstalledName.11 = STRING: « FileZilla (remove only)"
...
HOST-RESOURCES-MIB::hrSWInstalledName.79 = STRING: « SpamPal: BadWords plugin"
HOST-RESOURCES-MIB::hrSWInstalledName.80 = STRING: « SpamPal"
...
# Ainsi que leur date d'installation...
HOST-RESOURCES-MIB::hrSWInstalledDate.9 = STRING: 2002-12-17,10:29:48.0
HOST-RESOURCES-MIB::hrSWInstalledDate.10 = STRING: 2002-12-5,15:53:18.0
HOST-RESOURCES-MIB::hrSWInstalledDate.11 = STRING: 2003-1-9,10:50:28.0
...
HOST-RESOURCES-MIB::hrSWInstalledDate.79 = STRING: 2003-7-2,17:48:24.0
HOST-RESOURCES-MIB::hrSWInstalledDate.80 = STRING: 2003-6-30,17:38:58.0
...

Encore une fois, ce ne sont que des morceaux choisis, il y en a 1577 lignes et toutes ne sont pas si facilement compréhensibles. Nous verrons par la suite que snmpwalk peut être utilisé de façon plus fine.

Comme vous pouvez vaguement le deviner, SNMP peut se révéler être plutôt du genre indiscret. C'est un outil pour les administrateurs et les informations bonnes pour les administrateurs doivent souvent rester confidentielles.

II-C - Organisation

Nous aurons largement l'occasion d'approfondir l'étude de la façon dont les données sont organisées et donc, la façon dont on peut retrouver plus ou moins simplement l'information que l'on cherche ou que l'on désire mettre à jour via SNMP.

Contentons-nous pour l'instant d'admettre que l'ensemble des informations que peut fournir un objet (serveur, switch, routeur, imprimante, point d'accès Wi-Fi…) est classé de manière arborescente, par thème et sous-thème.

Juste histoire de nous mettre l'eau à la bouche, voyons comment il est possible d'interroger un agent SNMP pour lui demander le descriptif de l'hôte qui l'héberge.

La question, c'est (nous n'expliquerons pas tout de suite la formule magique) :

$ snmpget -On -c public -v 2c 172.16.252.2 .1.3.6.1.2.1.1.1.0

La réponse est ici :

.1.3.6.1.2.1.1.1.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))

Pour seule explication, vous avez droit pour l'instant à ceci : nous avons interrogé un switch « manageable » qui dispose de l'adresse IP 172.16.252.2, pour obtenir sa description. Nous savons maintenant qu'il s'agit d'un modèle Hewlett Packard ProCurve de la série 2650, modèle J4899B.

Nous aurions pu poser la question de manière légèrement différente :

$ snmpget -Ot -c public -v 2c 172.16.252.2 .1.3.6.1.2.1.1.1.0

Nous aurions alors obtenu comme réponse :

SNMPv2-MIB::sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))

Pas vraiment plus clair, mais qui fait apparaitre SNMPv2-MIB::sysDescr.0 en lieu et place de .1.3.6.1.2.1.1.1.0.

Avec un peu d'effort, nous pouvons même poser la question d'une troisième façon :

$ snmpget -Of -c public -v 2c 172.16.252.2 .1.3.6.1.2.1.1.1.0

Ce qui nous vaudra comme réponse :

.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))

C'est-à-dire que nous avons ici .iso.org.dod.Internet.mgmt.mib-2.system.sysDescr.0 plutôt que .1.3.6.1.2.1.1.1.0. C'est plus long et ça veut dire exactement la même chose, mais avec du texte.

II-C-1 - Conclusion provisoire

Les trois « machins » :

- .1.3.6.1.2.1.1.1.0 ;

- SNMPv2-MIB::sysDescr.0 ;

- .iso.org.dod.Internet.mgmt.mib-2.system.sysDescr.0.

veulent dire la même chose et sont parfaitement équivalents. Nous verrons que la représentation numérique est toujours utilisable, alors que les représentations en mode texte ne le seront pas toujours, il nous faudra éventuellement une sorte de dictionnaire.

Pour ceux qui ont roulé leur bosse dans divers domaines de l'informatique (programmation orientée objet, DOM, etc.), cette façon de faire leur rappellera des méthodes habituelles de classement arborescent.

Il y a dans ces réponses un mot d'apparence anodine, mais d'importance fondamentale pourtant : la MIB. Aucun rapport avec les protozoaires. Ici, MIB veut dire « Management Information Base ». Disons que c'est le fameux dictionnaire.

Nous pouvons donc conclure que les informations que peuvent échanger un agent SNMP et son manager, sachant que nous sommes sur un réseau apte à interconnecter des nœuds hétérogènes :

- sont classées dans une structure arborescente ;

- que la structure de cet arbre doit être normalisée ;

- que la structure des informations elles-mêmes doit également être normalisée ;

- que des dictionnaires doivent exister, pour différentes fonctions que nous verrons par la suite.

Sur tout nœud de réseau équipé d'un agent SNMP, il sera possible de trouver les informations nécessaires à une bonne supervision.

III - Le protocole

III-A - Les multiples versions

Commençons par le plus désagréable. SNMP existe au moins dans les versions 1, 2c, 2 et 3. Comme pour tout protocole, les références sont des RFC. Si vous aimez ce genre de lecture :

Version

année

RFC

Titre

Statut

v1

1990

1155

Structure and Identification of Management Information for TCP/IP-based Internets

standard

1156

Management Information Base for network management of TCP/IP-based Internets

historique

1157

Simple Network Management Protocol (SNMP)

historique

v2c (classic)

1993

1441

Introduction to version 2 of the Internet-standard Network Management Framework

historique, proposé comme standard

1442

Structure of Management Information for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1902

1443

Textual Conventions for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1903

1444

Conformance Statements for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1904

1445

Administrative Model for version 2 of the Simple Network Management Protocol (SNMPv2)

historique

1446

Security Protocols for version 2 of the Simple Network Management Protocol (SNMPv2)

historique

1447

Party MIB for version 2 of the Simple Network Management Protocol (SNMPv2)

historique

1448

Protocol Operations for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1905

1449

Transport Mappings for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1906

1450

Management Information Base for version 2 of the Simple Network Management Protocol (SNMPv2)

standard proposé, remplacé par RFC-1907

1451

Manager-to-Manager Management Information Base

historique

1452

Coexistence between version 1 and version 2 of the Internet-standard Network Management Framework

standard proposé, remplacé par RFC-1908

v2

1996

1901

Introduction to Community-based SNMPv2

historique, proposé comme expérimental

1902

Structure of Management Information for Version 2 of the Simple Network Management Protocol (SNMPv2)

standard, remplacé par RFC-2578

1903

Textual Conventions for Version 2 of the Simple Network Management Protocol (SNMPv2)

standard, remplacé par RFC-2579

1904

Conformance Statements for Version 2 of the Simple Network Management Protocol (SNMPv2)

standard, remplacé par RFC-2580

1905

Protocol Operations for Version 2 of the Simple Network Management Protocol (SNMPv2)  (3416)

standard, remplacé par RFC-3416

1906

Transport Mappings for Version 2 of the Simple Network Management Protocol (SNMPv2)  (3417)

standard, remplacé par RFC-3417

1907

Management Information Base for Version 2 of the Simple Network Management Protocol (SNMPv2) (3418)

standard, remplacé par RFC-3418

1908

Coexistence between Version 1 and Version 2 of the Internet-standard Network Management Framework  (2576)

standard, remplacé par RFC-2576

v3

1999

2571

An Architecture for Describing SNMP Management Frameworks

standard, remplacé par RFC-3411

2572

Message Processing and Dispatching for the Simple Network Management Protocol (SNMP)

standard, remplacé par RFC-3412

2573

SNMP Applications

standard, remplacé par RFC-3413

2574

User-based Security Model (USM) for version 3 of the Simple Network Management Protocol (SNMPv3)

standard, remplacé par RFC-3414

2575

View-based Access Control Model (VACM) for the Simple Network Management Protocol (SNMP)

standard, remplacé par RFC-3415

v2 et v3

2000

2576

Coexistence between Version 1, Version 2, and Version 3 of the Internet-standard Network Management Framework

standard proposé

2002

3411

An Architecture for Describing Simple Network Management Protocol (SNMP) Management Frameworks

standard

3412

Message Processing and Dispatching for the Simple Network Management Protocol (SNMP)

standard

3413

Simple Network Management Protocol (SNMP) Applications

standard

3414

User-based Security Model (USM) for version 3 of the Simple Network Management Protocol (SNMPv3)

standard

3415

View-based Access Control Model (VACM) for the Simple Network Management Protocol(SNMP)

standard

3416

Version 2 of the Protocol Operations for the Simple Network Management Protocol (SNMP)

standard

3417

Transport Mappings for the Simple Network Management Protocol (SNMP)

standard

3418

Management Information Base (MIB) for the Simple Network Management Protocol (SNMP)

standard

plus quelques standards proposés, mais non encore entérinés à ce jour (juillet 2010)

D'une manière générale, reportez-vous au site rfc-editor pour retrouver les RFC, avec les informations sur leur statut (expérimental, obsolète, actif…).

Comme vous le voyez, il règne la plus grande confusion dans la définition des versions 2 et 3 de SNMP.

La version 2, commencée à être définie en 1996, ne se voit réellement finalisée qu'en décembre 2002, après que la version 3 a été définie. Ladite version 3, trop récente, n'est pas encore largement utilisée, si bien que c'est la version 1 qui se retrouve être supportée par tous, avec ses (graves) défauts, comme nous le verrons plus loin, ainsi que la v2c assez généralement supportée. La version 3, la seule qui intègre quelques notions de sécurité, commence tout de même à être supportée sur des équipements récents (ceci est écrit en juillet 2010).

Pour que SNMP fonctionne, il n'y a pas qu'un protocole d'échange à définir. Il y a aussi une standardisation des informations que ce protocole peut transporter. C'est un protocole Internet, il doit être utilisable sur des plateformes hétérogènes (matériel comme système d'exploitation).

C'est pour cette raison que l'on parlera de MIB (Management Information Base) et de SMI (Structure of Management Information)

Dans ce qui suit, nous nous appuierons principalement sur SNMP v1 ou v2c.

III-B - Le protocole lui-même

SNMP tire son « S » du fait qu'il s'appuie sur UDP d'une part, et qu'il ne propose qu'un nombre très restreint de commandes.

Les commandes sont les suivantes (version 1) :

Commande

Action

get-request

Le Manager SNMP demande une information à un agent SNMP

get-next-request

Le Manager SNMP demande l'information suivante à l'agent SNMP

set-request

Le Manager SNMP met à jour une information sur un agent SNMP

get-reponse

L'agent SNMP répond à un get-request ou à un set-request

trap

L'agent SNMP envoie une alarme au Manager

Jusque là, c'est on ne peut plus simple. L'agent utilise le port 161 et le manager, le port 162. Graphiquement, ça donne ceci :

Les commandes get-request, get-next-request et set-request sont toutes émises par le manager à destination d'un agent et attendent toutes une réponse get-response de la part de l'agent.

La commande trap est une alerte. Elle est toujours émise par l'agent à destination du manager, et n'attend pas de réponse.

Comme vous le voyez, jusque-là, c'est extrêmement simple. Rassurez-vous, ça va nettement se compliquer avec la MIB et la SMI.

IV - Installation des services SNMP

Sur des « boites noires », l'agent SNMP est présent ou non, il faut s'en préoccuper au moment de l'achat. Les switches administrables, par exemple, en disposent généralement. En revanche, sur un système de type GNU/Linux, l'agent SNMP doit être installé et correctement configuré si l'on en a besoin. Ceci est également vrai sur les OS Microsoft où le service NMP doit également être installé, configuré et activé.

Nous allons utiliser une Ubuntu 10.4 (Lucid Lynx) pour la démonstration. Il existe deux paquets fondamentaux :

- snmp qui va installer les outils clients, nous nous en servirons tout au long de l'exposé ;

- snmpd qui va installer l'agent SNMP. Nous l'installons surtout pour comprendre comment fonctionne le principe des communautés avec les versions 1 et 2c de SNMP, et constater que sa configuration n'est pas si simple, ce qui laisse le champ libre à des outils comme Zabbix, qui propose son propre agent, indépendant de SNMP.

aptitude install snmp snmpd

IV-A - Le pack « snmpd »

$ aptitude show snmpd
Paquet : snmpd
État: installé
Automatiquement installé: non
Version : 5.4.2.1~dfsg0ubuntu1-0ubuntu2.1
Priorité : optionnel
Section : net
Responsable : Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Taille décompressée : 1 257k
Dépend: libc6 (>= 2.4), libsnmp15 (>= 5.4.2.1~dfsg), libwrap0 (>= 7.6-4~), debconf (>= 0.5) | debconf-2.0, adduser, debconf, lsb-base (>= 3.2-13)
Est en conflit: snmp (< 3.6-3), snmptraplogd
Remplace: snmptraplogd
Description : SNMP (Simple Network Management Protocol) agents
The Simple Network Management Protocol (SNMP) provides a framework for the exchange of management information between agents (servers) and clients.

The Net-SNMP agent is a daemon which listens for incoming SNMP requests from clients and provides responses.
Site : http://net-snmp.sourceforge.net/

IV-A-1 - Contenu du pack

$ dpkg -L snmpd
/.
...
/usr/sbin
/usr/sbin/snmpd
/usr/sbin/snmptrapd
...
/,etc
/,etc/default
/,etc/default/snmpd
/,etc/snmp
/etc/snmp/snmpd.conf
/etc/snmp/snmptrapd.conf
/,etc/init.d
/etc/init.d/snmpd

Peu d'exécutables (les « daemons » snmpd et snmptrapd) et quelques fichiers de configuration qui proposent par défaut, à l'habitude des distributions GNU/Linux, un usage très restreint de SNMP.

IV-A-2 - Première configuration

Le gros travail va être de se plonger dans /etc/snmp/snmpd.conf. Il est encore un peu tôt pour étudier les arcanes de ce fichier, aussi nous contenterons-nous pour l'instant d'une recette. Voici les modifications à apporter :

####
# First, map the community name (COMMUNITY) into a security name
# (local and mynetwork, depending on where the request is coming
# from):

#       sec.name  source          community
#com2sec paranoid  default         public
com2sec readonly  default         public
#com2sec readwrite default         private

# Third, create a view for us to let the groups have rights to:

#           incl/excl subtree                          mask
view all    included  .1
view system included  .1.3.6.1.2.1.1
#view system included  .iso.org.dod.internet.mgmt.mib-2.system

Il suffit de relancer le service snmpd :

/etc/init.d/snmpd restart

et notre serveur devrait être en mesure de servir toutes les informations qu'il connaît, à condition de les lui demander localement (127.0.0.1, question de sécurité).

IV-A-3 - Vérification

Avons-nous un service UDP à l'écoute sur le port 161 ?

# netstat -laupn
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat       PID/Program name
udp        0      0 127.0.0.1:161           0.0.0.0:*                           1717/snmpd
udp        0      0 0.0.0.0:68              0.0.0.0:*                           620/dhclient
udp        0      0 0.0.0.0:49122           0.0.0.0:*                           599/avahi-daemon: r
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           599/avahi-daemon: r

Il y a bien un processus à l'écoute d'UDP sur le port 161, uniquement sur l'interface locale.

Le fait que notre snmpd n'écoute que sur l'interface locale, sur Debian et dérivées, vient du fichier /,etc/default/snmpd, mais ceci est encore une autre histoire, que nous raconterons plus tard.

IV-B - Le pack « snmp »

$ aptitude show snmp
Paquet : snmp
État: installé
Automatiquement installé: non
Version : 5.4.2.1~dfsg0ubuntu1-0ubuntu2.1
Priorité : optionnel
Section : net
Responsable : Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Taille décompressée : 1 475k
Dépend: libc6 (>= 2.4), libsnmp15 (>= 5.4.2.1~dfsg), libssl0.9.8 (>= 0.9.8k-1)
Recommande: perl-modules
Description : SNMP (Simple Network Management Protocol) applications
The Simple Network Management Protocol (SNMP) provides a framework for the exchange of management information between
agents (servers) and clients.

The Net-SNMP applications are a collection of command line clients for issuing SNMP requests to agents.
Site : http://net-snmp.sourceforge.net/

IV-B-1 - Contenu

Il n'y a rien de spécial à configurer ici. Nous disposons principalement d'une quantité impressionnante d'outils destinés à interroger un serveur SNMP :

$ dpkg -L snmp
/.
...
/usr/bin
/usr/bin/snmpbulkget
/usr/bin/snmpbulkwalk
/usr/bin/snmpconf
/usr/bin/snmpdelta
/usr/bin/snmpdf
/usr/bin/snmpget
/usr/bin/snmpgetnext
/usr/bin/snmpnetstat
/usr/bin/snmpset
/usr/bin/snmpstatus
/usr/bin/snmptable
/usr/bin/snmptest
/usr/bin/snmptranslate
/usr/bin/snmptrap
/usr/bin/snmpusm
/usr/bin/snmpvacm
/usr/bin/snmpwalk
/usr/bin/encode_keychange
/usr/bin/fixproc
/usr/bin/traptoemail
/usr/share/man/man1/snmpinform.1.gz
/usr/bin/snmpinform

Beaucoup d'utilitaires, pas de fichiers de configuration et de la documentation (enlevée dans la liste pour plus de lisibilité). Avec ces outils, il est possible d'interroger tout agent SNMP accessible par le réseau.

IV-B-2 - Vérification

Pas question d'entrer déjà dans les détails. Ici aussi une simple recette permettra d'espérer que tout ceci fonctionne :

~$ snmpwalk -c public -v 1 localhost

devrait dérouler une longue liste de choses pour le moment incompréhensibles. Notez qu'il n'est nul besoin de privilèges root pour extraire ces informations.

SNMPv2-MIB::sysDescr.0 = STRING: Linux lucid0 2.6.32-23-generic #37-Ubuntu SMP Fri Jun 11 08:03:28 UTC 2010 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (9217) 0:01:32.17
SNMPv2-MIB::sysContact.0 = STRING: Root <root@localhost> (configure /etc/snmp/snmpd.local.conf)
SNMPv2-MIB::sysName.0 = STRING: lucid0
SNMPv2-MIB::sysLocation.0 = STRING: Unknown (configure /etc/snmp/snmpd.local.conf)
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORID.1 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.2 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.5 = OID: TCP-MIB::tcpMIB
SNMPv2-MIB::sysORID.6 = OID: IP-MIB::ip
SNMPv2-MIB::sysORID.7 = OID: UDP-MIB::udpMIB
SNMPv2-MIB::sysORID.8 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
SNMPv2-MIB::sysORDescr.1 = STRING: The SNMP Management Architecture MIB.
SNMPv2-MIB::sysORDescr.2 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.3 = STRING: The management information definitions for the SNMP User-based Security Model.
SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for SNMPv2 entities
SNMPv2-MIB::sysORDescr.5 = STRING: The MIB module for managing TCP implementations
SNMPv2-MIB::sysORDescr.6 = STRING: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB::sysORDescr.7 = STRING: The MIB module for managing UDP implementations
SNMPv2-MIB::sysORDescr.8 = STRING: View-based Access Control Model for SNMP.
SNMPv2-MIB::sysORUpTime.1 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.2 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.3 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.4 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.5 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.6 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.7 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORUpTime.8 = Timeticks: (0) 0:00:00.00
IF-MIB::ifNumber.0 = INTEGER: 2
IF-MIB::ifIndex.1 = INTEGER: 1
IF-MIB::ifIndex.2 = INTEGER: 2
IF-MIB::ifDescr.1 = STRING: lo
IF-MIB::ifDescr.2 = STRING: eth0
IF-MIB::ifType.1 = INTEGER: softwareLoopback(24)
IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6)
IF-MIB::ifMtu.1 = INTEGER: 16436
IF-MIB::ifMtu.2 = INTEGER: 1500
...

Notez également l'impression d'impuissance que procure la lecture de cette liste d'informations… Espérons que par la suite, tout ceci nous paraitra un peu plus clair.

Tout ceci est surtout destiné à vérifier que l'on peut disposer d'outils d'interrogation d'un agent SNMP. Il devient urgent de comprendre comment les informations que SNMP peut fournir sont classées et comment l'on peut retrouver celles qui nous intéressent. Juste histoire d'effrayer le lecteur, sachez qu'un simple switch de type HP Procurve J4899B peut renvoyer plus de 20 000 lignes d'informations, toutes aussi difficilement compréhensibles à première vue.

V - Les MIB

V-A - C'est quoi une MIB ?

Il s'agit donc la base d'informations de gestion. Il y a, nous commençons à bien le comprendre :

- des informations à consulter ;

- des paramètres à modifier ;

- des alarmes à émettre…

Tout ceci, en principe, de façon indépendante du matériel et du logiciel. Il faut donc que SNMP permette de retrouver ces informations et d'agir sur les paramètres de façon indépendante du matériel, comme du logiciel.

Une MIB se présente comme une base de données normalisée, qui permettra de lire et d'écrire sur les équipements distants, de façon également normalisée. Ce sera à l'agent lui-même de faire l'interface entre les informations récupérables sur la plateforme où il est installé et le jargon utilisé par SNMP.

V-B - Structure d'une MIB

Elle est extrêmement simple pour un informaticien, et donc assez compliquée pour un cerveau humain « normal ».

Elle est organisée hiérarchiquement, de la même façon que l'arborescence des domaines Internet.

Elle peut contenir des scalaires (valeurs uniques) ou des tableaux de scalaires.

Non seulement la structure est normalisée, mais également les appellations des diverses rubriques. Ces appellations ne servent à rien, si ce n'est à rendre les choses plus lisibles (ce qui peut éventuellement prêter à rire). En réalité, chaque niveau de la hiérarchie est repéré par un index numérique et SNMP n'utilise que cette façon de faire. Une MIB est une branche, qui vient se greffer sur l'arbre général. Nous en avons juste à côté une vue très simplifiée, qu'il nous sera possible de contempler avec plus de détails par la suite avec l'outil snmptranslate.

Tout constructeur d'un matériel spécifique peut développer une MIB pour ce matériel, cette MIB devra prendre sa place dans l'arbre, sans piétiner celle des voisins, et c'est le rôle de l'IETF ou de l'IANA d'attribuer un point de branchement pour le matériel de ce constructeur.

Une MIB n'étant finalement qu'une branche, elle peut nécessiter l'usage de d'autres MIB pour se rattacher à l'arbre. Prenons un exemple. HP peut développer une MIB générique à tous ses matériels qui viendrait se greffer sur la branche private.enterprise, puis des MIB spécifiques à chaque matériel qui viendraient elles-mêmes se développer dans la MIB générique de HP.

V-B-1 - Illustration

Sur l'arborescence en illustration, nous constatons que le sommet est représenté par un point originel, puisque chaque embranchement dispose d'un nom (iso, org, Internet…) et aussi d'un numéro (1, 3, 6, 1…).

Intéressons-nous au chemin qui mène à sysDescr soit :

- .iso.org.dod.Internet.mgmt.mib-2.system.sysDescr en mode texte ;

- .1.3.6.1.2.1.1.1 en mode numérique.

Reprenons notre switch et interrogeons-le de diverses manières, à propos de ce chemin :

~$ snmpwalk -Of -c public -v 1 172.16.252.2 .1.3.6.1.2.1.1.1

- snmpwalk signifie que l'on désire parcourir un arbre SNMP ;

- -Of signifie que l'on désire afficher l'arborescence « full-text » ;

- -c public signifie que l'on se place dans la communauté « public », ceci prendra tout son sens un peu plus tard ;

- -v 1 signifie que l'on utilise la version 1 du protocole SNMP ;

- vient ensuite l'adresse IP de l'agent que l'on désire interroger ;

- vient enfin, en mode numérique, le point d'embranchement à partir duquel nous désirons parcourir l'arbre.

Nous obtenons la réponse :

.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))

Une chaine de caractères qui identifie le type de matériel (system descriptor). Le chemin qui mène à cette information est noté en mode « full-text », comme il a été demandé.

L'outil snmpwalk s'avère d'une grande puissance, pour peu qu'on arrive à le dompter un tant soit peu. Réutilisons-le en remontant d'un niveau dans le point de départ :

~$ snmpwalk -Of -c public -v 1 172.16.252.2 .1.3.6.1.2.1.1

(nous avons enlevé le dernier .1 dans la définition du point de départ) :

.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))
.iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0 = OID: .iso.org.dod.internet.private.enterprises.11.2.3.7.11.44
.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance = Timeticks: (1071094654) 123 days, 23:15:46.54
.iso.org.dod.internet.mgmt.mib-2.system.sysContact.0 = STRING: sysop
.iso.org.dod.internet.mgmt.mib-2.system.sysName.0 = STRING: ProCurve Switch 2650-1
.iso.org.dod.internet.mgmt.mib-2.system.sysLocation.0 = STRING:
.iso.org.dod.internet.mgmt.mib-2.system.sysServices.0 = INTEGER: 74

Notez que la réponse aligne tout ce que l'agent sait dire à partir de .iso.org.dod.Internet.mgmt.mib-2.system.

Bien entendu, une interrogation de la forme :

snmpwalk -Of -c public -v 1 172.16.252.2 .iso.org.dod.internet.mgmt.mib-2.system

fait parfaitement le travail. Mais nous aurions pu tout aussi bien poser la question de façon beaucoup plus compacte :

~$ snmpwalk -Of -c public -v 1 172.16.252.2 system

.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))
.iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0 = OID: .iso.org.dod.internet.private.enterprises.11.2.3.7.11.44
.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance = Timeticks: (1071132769) 123 days, 23:22:07.69
.iso.org.dod.internet.mgmt.mib-2.system.sysContact.0 = STRING: sysop
.iso.org.dod.internet.mgmt.mib-2.system.sysName.0 = STRING: ProCurve Switch 2650-1
.iso.org.dod.internet.mgmt.mib-2.system.sysLocation.0 = STRING:
.iso.org.dod.internet.mgmt.mib-2.system.sysServices.0 = INTEGER: 74

Nous donnons ici le chemin non plus absolu, mais relatif au nœud system (pas de point initial), et le système s'y retrouve. Ceci sous-entend que chaque nœud doit disposer d'un nom unique dans l'arbre tout entier.

D'autres formats de sortie sont possibles :

- -On affiche le résultat avec l'identifiant en mode numérique ;

- -OS « print MIB module-id plus last element » :

~$ snmpwalk -OS -c public -v 1 172.16.252.2 sysName
SNMPv2-MIB::sysName.0 = STRING: ProCurve Switch 2650-1

Ce qui laisse imaginer que si l'on pose la question :

~$ snmpwalk -On -c public -v 1 172.16.252.2 SNMPv2-MIB::sysDescr

la réponse devrait être favorable et de la forme :

.1.3.6.1.2.1.1.1.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))

ce qui est bien le cas.

V-C - La « BRIDGE-MIB »

Un switch est tout de même un objet un peu particulier et ce que nous avons vu jusqu'ici va atteindre ses limites.

Ainsi, au bout de la branche .1.3.6.1.2.1.17.1.2, nous devons normalement trouver le nombre de ports dont dispose le switch (il faut être un initié pour le savoir). Le bout de la branche devant obligatoirement se terminer par un 0, nous l'avons remarqué lors des démonstrations précédentes, posons la question avec cette fois-ci un snmpget, qui ne sait extraire qu'une seule information, et qui doit donc être obligatoirement posée en indiquant le bout de la branche :

$ snmpget -Of -c public -v 2c 172.16.252.2 .1.3.6.1.2.1.17.1.2.0
.iso.org.dod.internet.mgmt.mib-2.17.1.2.0 = INTEGER: 50

Il y a bien 50 ports sur notre switch HP :

- 48 ports 10/100 Mb/s ;

- 2 ports 10/100/1000 Mb/s.

Mais cette réponse apporte, en prime, une bonne et une mauvaise nouvelle.

La bonne nouvelle, c'est que notre switch comprend bien la question, puisqu'il donne une réponse.

La mauvaise, c'est que notre commande snmpget ne sait pas traduire la totalité du chemin en mode « full-text », comme il a été pourtant demandé (option -Of). En effet, sa réponse est :

.iso.org.dod.internet.mgmt.mib-2.17.1.2.0 = INTEGER: 50

autrement dit, il manque des pages dans le dictionnaire, snmpget sait traduire dans la suite .1.3.6.1.2.1.17.1.2.0 la seule partie .1.3.6.1.2.1 et pas la suite 17.1.2, c'est pourquoi cette suite reste numérique dans la réponse. La bonne nouvelle dans la mauvaise nouvelle, c'est qu'il reste possible d'interroger un agent SNMP sur une information, même si l'on ne dispose pas des pages manquantes relatives à la définition de cette information, du moment que l'on connait le chemin numérique pour y accéder.

Nous allons tout de même demander à notre snmpget d'intégrer ces pages qui manquent (cette MIB(2)), que nous avons récupérées grâce au paquet snmp-mibs-downloader que nous avons installé avec un aptitude install des familles et qui nous a mis tout ça dans /usr/share/mibs :

snmpget -m +/usr/share/mibs/ietf/BRIDGE-MIB -Of -c public -v 2c 172.16.252.2 .1.3.6.1.2.1.17.1.2.0
.iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dBase.dot1dBaseNumPorts.0 = INTEGER: 50 ports

Voici une réponse nettement plus compréhensible, la suite .1.3.6.1.2.1.17.1.2.0 est cette fois-ci complètement interprétée…

Inversement, nous pouvons opérer ainsi :

snmpget -m /usr/share/mibs/ietf/BRIDGE-MIB -On -c public -v 2c 172.16.252.2 .iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dBase.dot1dBaseNumPorts.0
.1.3.6.1.2.1.17.1.2.0 = INTEGER: 50 ports

Nous avons posé la question en indiquant le chemin en mode texte en demandant la réponse au format numérique. Mais aurions-nous pu faire cela sans l'aide de la BRIDGE-MIB ?

$ snmpget -On -c public -v 2c 172.16.252.2 .iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dBase.dot1dBaseNumPorts.0
.iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dBase.dot1dBaseNumPorts.0: Unknown Object Identifier (Sub-id not found: mib-2 -> dot1dBridge)

Bien sûr que non, sans son aide, snmpget ne sait pas traduire le chemin exprimé en langage « humain ».

Dernière vérification pour la route, nous posons la même question, cette fois-ci à un switch de marque D-Link :

$ snmpget -Of -c public -v 2c 172.16.252.4 .1.3.6.1.2.1.1.1.0
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: DGS-3024 Gigabit Ethernet Switch

il s'agit d'un switch DGS-3024, modèle notoirement proposé par D-Link.

$ snmpget -m +/usr/share/mibs/ietf/BRIDGE-MIB -On -c public -v 2c 172.16.252.4 .iso.org.dod.internet.mgmt.mib-2.dot1dBridge.dot1dBase.dot1dBaseNumPorts.0
.1.3.6.1.2.1.17.1.2.0 = INTEGER: 24 ports

En effet, ce modèle propose 24 ports 10/100/1000 Mb/s.

Ce petit exemple était destiné à démontrer que deux switches de marque bien différente savent répondre à la même question, si l'information demandée est définie dans la BRIDGE-MIB.

Bien sûr chaque constructeur va pouvoir apporter à ses équipements des particularités supplémentaires et spécifiques à sa marque et à son modèle. Elles sont dans ce cas placées après le nœud enterprises. Nous pourrons toujours obtenir ces données, mais sans les MIB associées, il sera difficile, voir impossible de déterminer ce que ces données représentent.

Encore une fois, pourquoi se passer d'un peu d'humour ?

~$ snmpwalk -Of -c public -v 1 172.16.252.2 enterprises

va nous donner :

.iso.org.dod.internet.private.enterprises.9.9.23.1.1.1.1.2.1 = INTEGER: 1
.iso.org.dod.internet.private.enterprises.9.9.23.1.1.1.1.2.2 = INTEGER: 1
...
.iso.org.dod.internet.private.enterprises.9.9.23.1.1.1.1.2.50 = INTEGER: 1
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.3.50.1 = INTEGER: 1
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.4.50.1 = Hex-STRING: AC 10 FC 03
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.5.50.1 = STRING: "ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))"
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.6.50.1 = Hex-STRING: 00 17 08 E4 C5 00
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.7.50.1 = STRING: "49"
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.8.50.1 = STRING: "ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))"
.iso.org.dod.internet.private.enterprises.9.9.23.1.2.1.1.9.50.1 = STRING: "8"
.iso.org.dod.internet.private.enterprises.9.9.23.1.3.1.0 = INTEGER: 1
.iso.org.dod.internet.private.enterprises.9.9.23.1.3.2.0 = INTEGER: 0
.iso.org.dod.internet.private.enterprises.9.9.23.1.3.3.0 = INTEGER: 0
...

Il y en a pour 7346 lignes sur notre Procurve. Le D-Link DGS-3024 quant à lui n'en sortira que 2205…

Sans les MIB qui vont avec, il sera quasiment impossible de savoir à quoi correspondent ces informations, car les MIB, en plus de traduire les chemins numériques en texte, peuvent donner des indications supplémentaires sur la nature de l'information extraite.

V-D - Mais encore…

Les MIB ne se contentent pas de fournir une traduction entre les modes numériques et textuels. Elles fournissent aussi quelques explications sur les paramètres qu'elles prennent en charge. La commande snmptranslate permet, une fois domestiquée, d'obtenir quelque documentation supplémentaire :

~$ snmptranslate -Tp SNMPv2-MIB::system

+--system(1)
|
+-- -R-- String    sysDescr(1)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -R-- ObjID     sysObjectID(2)
+-- -R-- TimeTicks sysUpTime(3)
|  |
|  +--sysUpTimeInstance(0)
|
+-- -RW- String    sysContact(4)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -RW- String    sysName(5)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -RW- String    sysLocation(6)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -R-- INTEGER   sysServices(7)
|        Range: 0..127
+-- -R-- TimeTicks sysORLastChange(8)
|        Textual Convention: TimeStamp
|
+--sysORTable(9)
|
+--sysOREntry(1)
|  Index: sysORIndex
|
+-- ---- INTEGER   sysORIndex(1)
|        Range: 1..2147483647
+-- -R-- ObjID     sysORID(2)
+-- -R-- String    sysORDescr(3)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -R-- TimeTicks sysORUpTime(4)
Textual Convention: TimeStamp

Nous obtenons, en art ASCII, une vue arborescente de la branche system.

Un peu de traduction pure et simple :

~$ snmptranslate -On SNMPv2-MIB::sysDescr
.1.3.6.1.2.1.1.1

~$ snmptranslate -Ot .1.3.6.1.2.1.1.1
SNMPv2-MIB::sysDescr

~$ snmptranslate -Of .1.3.6.1.2.1.1.1
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr

Et éventuellement quelques explications :

~$ snmptranslate -Ot -Td .1.3.6.1.2.1.1.1
SNMPv2-MIB::sysDescr
sysDescr OBJECT-TYPE
-- FROM       SNMPv2-MIB, RFC1213-MIB
-- TEXTUAL CONVENTION DisplayString
SYNTAX        OCTET STRING (0..255)
DISPLAY-HINT  "255a"
MAX-ACCESS    read-only
STATUS        current
DESCRIPTION   "A textual description of the entity.  This value hould
include the full name and version identification of
the system's hardware type, software operating-system,
and networking software."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) system(1) 1 }

Normalement, chaque bout de branche dispose d'une description. Ne vous attendez jamais à voir apparaitre autre chose que de l'anglais, bien entendu.

~$ snmptranslate -Ot -Td SNMPv2-MIB::sysORIndex
SNMPv2-MIB::sysORIndex
sysORIndex OBJECT-TYPE
-- FROM    SNMPv2-MIB
SYNTAX    INTEGER (1..2147483647)
MAX-ACCESS    not-accessible
STATUS    current
DESCRIPTION    "The auxiliary variable used for identifying instances
of the columnar objects in the sysORTable."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) system(1) sysORTable(9) sysOREntry(1) 1 }

Notez également que ceci peut parfois tourner au jeu de piste.

V-D-1 - Interro surprise 1

Est-ce que ceci aurait des chances de fonctionner ?

~$ snmptranslate -Ot -Td .1.3.6.1.2.1.17.1.2.0

Et ceci :

~$ snmptranslate -Ot -Td -m /usr/share/mibs/ietf/BRIDGE-MIB .1.3.6.1.2.1.17.1.2.0

Vous trouverez les réponses à la fin de l'exposé.

V-E - Et en mode graphique ?

Il existe un outil, TKmib qui, comme son nom l'indique, utilise TK et n'est donc pas des plus esthétiques. Ce genre d'outil, nommé « browser de MIB » permet de faire de façon graphique, ce que l'on a vu avec nsmpwalk, snmpget et snmptranslate.

Ce n'est pas très joli, mais ça fait le travail.

VI - En savoir un peu plus

Nous avons rapidement vu les outils permettant de soutirer des informations aux agents SNMP, à cette occasion nous avons parlé de communautés, mais nous n'avons pas vu ce que c'est. Voyons ceci en configurant (un minimum) un agent SNMP sur une distribution GNU/Linux.

VI-A - Les versions de SNMP

Il semble bien que finalement, seules les versions 1, 2c (classique) et 3 soient utilisées.

La version 3 apporte des fonctions de sécurité (chiffrement et authentification) qui permettent d'utiliser SNMP dans un environnement « hostile », mais n'est pas implémentée sur tous les matériels. Cette version n'apportant rien de plus pour la compréhension du fonctionnement de SNMP, nous n'en parlerons pas davantage.

La version 1 est généralement implémentée sur tous les équipements proposant SNMP, de même que la version 2c, qui ne fait qu'ajouter des compteurs sur 64 bits et une commande supplémentaire : GetBulk-Request. Cette nouvelle commande donne le même résultat que la commande Get-next-request, mais de façon plus efficace. Nous verrons cela plus loin dans les analyses de trames.

Ces deux versions offrent une sécurité tout à fait indigente. Il n'y a ni chiffrement des données ni authentification (aussi bien de l'agent que du manager). Dans un environnement « hostile » il restera possible de pallier cet inconvénient par l'usage de tunnels chiffrés, de VLAN, etc. Voyons tout de même ce que proposent les versions 1 et 2 en termes de restrictions d'accès.

VI-A-1 - Les communautés et leurs privilèges

Nous illustrerons le propos en configurant l'agent snmpd proposé dans les distributions GNU/Linux.

Une communauté représente un groupe d'utilisateurs. Nous nous sommes jusqu'ici déclarés de la communauté public (option -c public dans les diverses commandes).

Par défaut, la plupart des équipements proposent les communautés public et private. Il est toutefois possible de les renommer ou d'en créer d'autres.

La communauté public n'a généralement accès qu'en lecture, et pas forcément à toute l'étendue des informations exposées.

La communauté private est généralement exploitée pour écrire (donc reconfigurer) un équipement et disposer de la totalité des informations que l'agent sait exposer. Il est donc nécessaire d'en réserver l'accès aux seuls administrateurs autorisés, mais ceci ne peut se faire que sur la base des adresses IP des managers, ce qui reste très rudimentaire.

Il est clair que dans un environnement hostile, il reste assez simple d'utiliser SNMP (v1 et 2) à des fins tout à fait malveillantes.

Nous allons faire quelques manipulations sur notre Lynx Lucide pour illustrer les restrictions que l'on peut appliquer avec les communautés.

Nous avons fait, lors de l'installation de snmpd une modification de la configuration par défaut. Revoici une configuration minimale, équivalente, ne prenant en compte que les versions 1 et 2c de SNMP :

com2sec readonly  default         public
com2sec readwrite default         private

group MyROGroup v1         readonly
group MyROGroup v2c        readonly
group MyRWGroup v1         readwrite
group MyRWGroup v2c        readwrite

view all    included  .1

access MyROGroup ""      any       noauth    exact  all    none   none
access MyRWGroup ""      any       noauth    exact  all    all    none

La logique séquentielle de ce fichier n'est pas forcément la meilleure pour en comprendre le principe. Commençons donc par les view.

VI-A-1-a - Les « view »

Ici nous n'avons qu'une view qui inclut la totalité de l'arbre (.1) et qui s'appelle all. Nous aurions pu tout aussi bien écrire

view bidule    included  .1

ou

view machin    included  .1

le mot-clé est view le nom de la vue sera all (ou bidule ou machin) et ce qui est inclus dans cette vue c'est .1 c'est-à-dire la totalité de ce que l'agent peut proposer.

VI-A-1-b - Les « group »

Nous créons des noms de groupes auxquels nous associons un « nom de sécurité », en fonction de la version du protocole utilisé. Ceci n'a de réel sens qu'avec la version 3, mais en v1 et en v2c, il faut en passer par là quand même.

Nous avons écrit :

group MyROGroup v1         readonly
group MyROGroup v2c        readonly
group MyRWGroup v1         readwrite
group MyRWGroup v2c        readwrite

Nous aurions aussi bien pu faire :

group voyeurs v1     regarderMaisPasToucher
group voyeurs v2c    regarderMaisPasToucher
group violeurs v1    regardeEtPlus
group violeurs v2c   regardeEtPlus

pas forcément du meilleur goût, mais tout aussi correct syntaxiquement parlant.

Ces groupes et noms de sécurité nous serviront plus loin.

VI-A-1-c - Les « access »

Ils sont de la forme :

access GROUP CONTEXT {any|v1|v2c|usm} LEVEL PREFX READ WRITE NOTIFY

On va faire simple :

- le CONTEXT n'a de sens que pour la version 3 ;

- le LEVEL est forcément noauth pour les versions 1 et 2c ;

- le PREFIX n'a pas de sens pour v1 et v2c, nous mettrons exact ;

- le NOTIFY « is not currently used ».

Reste donc :

- le GROUP est un nom que l'on a créé de toutes pièces, juste au-dessus ;

- le READ sera le nom de la vue dans laquelle le groupe aura le droit de lire ou none s'il ne peut rien lire (ce qui n'aurait aucun sens, pourquoi créer un groupe qui aurait le droit de ne rien lire) ;

- le WRITE sera le nom de la vue dans laquelle le groupe pourra écrire (ou none s'il ne peut écrire).

Ainsi, dans notre fichier :

access MyROGroup ""      any       noauth    exact  all    none   none
access MyRWGroup ""      any       noauth    exact  all    all    none

Veut dire qu'il existe deux groupes, MyROGroup et MyRWGroup :

- MyROGroup peut lire dans la vue all mais ne peut y écrire et ce, en utilisant aussi bien les protocoles v1 que v2c ;

- MyRWGroup peut aussi bien lire qu'écrire dans la vue all aussi bien en v1 qu'en v2c.

VI-A-1-d - Le « com2sec »

C'est ici que l'on recolle tous les morceaux, en ajoutant en prime les communautés. De la forme :

com2sec  [-Cn CONTEXT] SECNAME SOURCE COMMUNITY

- CONTEXT n'a toujours pas de sens en v1 ni en v2c ;

- SECNAME, ça vient d'un peu plus haut dans l'explication ;

- SOURCE, c'est l'adresse IP source (ou le sous-réseau IP, ou default si c'est « wide open ») ;

- COMMUNITY, c'est le nom de la communauté dans laquelle l'agent s'est déclaré.

Nous avons :

com2sec readonly  default         public
com2sec readwrite default         private

Autrement dit, le groupe de sécurité readonly (qui aurait pu s'appeler regarderMaisPasToucher) est attaché à la communauté public. Comme ce groupe de sécurité est attaché au groupe MyROGroup (qui aurait pu s'appeler voyeurs) pour les protocoles v1 et v2c et que ce groupe MyROGroup peut aussi bien en v1 qu'en v2c lire et seulement lire partout, il s'ensuit que tout manager qui se connectera sur notre hôte en se déclarant de la communauté public pourra lire ce qu'il veut.

L'ennui, c'est que si le manager se déclare de la communauté private, qui est attachée au groupe de sécurité readwrite (qui aurait pu s'appeler ?…) depuis n'importe où (default) et que ce groupe de sécurité est attribué au groupe MyRWGroup (qui aurait pu s'appeler ?…), lequel peut lire dans all mais aussi y écrire, alors ce manager pourra modifier tout ce qui est modifiable sur notre hôte, preuve que notre configuration est complètement nulle. En fait, elle est là pour l'exemple, nous en ferons une moins sale par la suite.

VI-A-1-e - Particularité Debian

(Et dérivées)

Le fichier /,etc/default/snmpd contient des options ajoutées lors du lancement du service snmpd. Ces options, par défaut, limitent le service à écouter sur 127.0.0.1 :

# This file controls the activity of snmpd and snmptrapd

# MIB directories.  /usr/share/snmp/mibs is the default, but
# including it here avoids some strange problems.
export MIBDIRS=/usr/share/snmp/mibs

# snmpd control (yes means start daemon).
SNMPDRUN=yes

# snmpd options (use syslog, close stdin/out/err).
SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -g snmp -I -smux -p /var/run/snmpd.pid 127.0.0.1'

# snmptrapd control (yes means start daemon).  As of net-snmp version
# 5.0, master agentx support must be enabled in snmpd before snmptrapd
# can be run.  See snmpd.conf(5) for how to do this.
TRAPDRUN=no

# snmptrapd options (use syslog).
TRAPDOPTS='-Lsd -p /var/run/snmptrapd.pid'

# create symlink on Debian legacy location to official RFC path
SNMPDCOMPAT=yes

Un simple man snmpd nous expliquera facilement (une fois n'est pas coutume) qu'il suffit d'enlever l'adresse locale dans la ligne d'options pour que snmpd écoute sur toutes les interfaces. Notez que si nous avons deux interfaces, dont par exemple une attachée à un VLAN (un VLAN pourquoi pas réservé à l'administration des équipements), nous pouvons forcer snmpd à n'écouter que sur cette interface, ce qui permettrait de sécuriser quelque peu le dispositif.

Après modification de cette ligne et redémarrage du service, nous pouvons constater que :

# netstat -lupn
Connexions Internet actives (seulement serveurs)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat       PID/Program name
udp        0      0 0.0.0.0:68              0.0.0.0:*                           639/dhclient
udp        0      0 0.0.0.0:47712           0.0.0.0:*                           618/avahi-daemon: r
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           618/avahi-daemon: r
udp        0      0 0.0.0.0:161             0.0.0.0:*                           1507/snmpd

VI-B - C'est compris ?

Bien sûr ! Et ceci va nous permettre de créer une configuration un peu plus complète de la façon suivante :

- une communauté public, qui aura droit à l'accès en lecture seule, mais seulement à la branche system pour tous ceux qui peuvent joindre notre agent, quelle que soit leur adresse IP ;

- une communauté private aura droit à la lecture seule de toutes les informations possibles, mais seulement à partir d'un réseau IP particulier ;

- une communauté admin pourra lire et écrire partout où c'est possible, mais depuis une adresse IP bien particulière.

Voici la configuration proposée :

com2sec voirUnPeu     default                public
com2sec voirTout      192.168.0.0/24         private
com2sec voirEtToucher 192.168.0.16           admin

group touristes v1         voirUnPeu
group touristes v2c        voirUnPeu
group riverains v1         voirTout
group riverains v2c        voirTout
group proprio   v1         voirEtToucher
group proprio   v2c        voirEtToucher

view system included       .1.3.6.1.2.1.1.1
view all    included       .1

access touristes ""      any       noauth    exact  system none   none
access riverains ""      any       noauth    exact  all    none   none
access proprio   ""      any       noauth    exact  all    all    none

VI-B-1 - Interro surprise 2

1. Quelqu'un se déclarant de la communauté public pourra-t-il

1. se connecter depuis n'importe quelle adresse IP ?

2. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces ? (on pourra s'aider de snmptranslate pour obtenir la version numérique de cette branche)

2. Quelqu'un se déclarant de la communauté private pourra-t-il

1. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.1.25 ?

2. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.0.25 ?

3. Quelqu'un se déclarant de la communauté admin depuis l'adresse IP 192.168.0.17

1. pourra-t-il obtenir les informations de la branche .1.3.6.1.2.1.2 ?

2. pourra-t-il modifier une valeur accessible en écriture (SNMPv2-MIB::sysLocation par exemple) ?

Réponses toujours en dernière page.

VII - Analyse du protocole

Nous allons regarder avec Wireshark, notre sniffeur favori, ce qu'il se passe en utilisant trois commandes classiques : snmpget, snmpwalk et snmpbulkwalk (utilisable seulement avec la version v2c ou supérieure de SNMP).

VII-A - snmpget

Demandons, une fois encore, à notre switch de nous dire son nom :

~$ snmpget -v 1 -c public -Ot 172.16.252.2 SNMPv2-MIB::sysName.0
SNMPv2-MIB::sysName.0 = STRING: ProCurve Switch 2650-1

Voyons ce que notre sniffeur a épié :

No.     Time        Source                Destination           Protocol Info
1 0.000000    192.168.0.16          172.16.252.2          SNMP     get-request 1.3.6.1.2.1.1.5.0

Frame 1 (85 bytes on wire, 85 bytes captured)
...
User Datagram Protocol, Src Port: 42380 (42380), Dst Port: snmp (161)
Source port: 42380 (42380)
Destination port: snmp (161)
Length: 51
Checksum: 0x6910 [validation disabled]
[Good Checksum: False]
[Bad Checksum: False]
Simple Network Management Protocol
version: version-1 (0)
community: public
data: get-request (0)
get-request
request-id: 925410341
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.2.1.1.5.0: Value (Null)
Object Name: 1.3.6.1.2.1.1.5.0 (iso.3.6.1.2.1.1.5.0)

Nous sommes bien en UDP et le port cible est bien 161.

SNMP est bien utilisé en version 1, la commande est get-request et l'OID demandé est 1.3.6.1.2.1.1.5.0.

La réponse :

No.     Time        Source                Destination           Protocol Info
2 0.072588    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.5.0

Frame 2 (107 bytes on wire, 107 bytes captured)
...
User Datagram Protocol, Src Port: snmp (161), Dst Port: 42380 (42380)
Source port: snmp (161)
Destination port: 42380 (42380)
Length: 73
Checksum: 0x180f [validation disabled]
[Good Checksum: False]
[Bad Checksum: False]
Simple Network Management Protocol
version: version-1 (0)
community: public
data: get-response (2)
get-response
request-id: 925410341
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.2.1.1.5.0: 0726F43757276652053776974636820323635302D31
Object Name: 1.3.6.1.2.1.1.5.0 (iso.3.6.1.2.1.1.5.0)
Value (OctetString): 50726F43757276652053776974636820323635302D31

Nous avons la réponse (get-response), elle n'est pas très lisible, car donnée sous forme numérique (la version 1.2.7 de Wireshark semblant avoir du mal avec le décodage de SNMP).

Nous ne referons pas la manipulation en v2c, le résultat étant le même.

VII-B - snmpwalk

Voyons maintenant la branche system en entier, avec la commande snmpwalk :

$ snmpwalk -v 1 -c public -Ot 172.16.252.2 SNMPv2-MIB::system
SNMPv2-MIB::sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.11.2.3.7.11.44
DISMAN-EVENT-MIB::sysUpTimeInstance = 1123840470
SNMPv2-MIB::sysContact.0 = STRING: sysop
SNMPv2-MIB::sysName.0 = STRING: ProCurve Switch 2650-1
SNMPv2-MIB::sysLocation.0 = STRING:
SNMPv2-MIB::sysServices.0 = INTEGER: 74

Wireshark a vu une suite de commandes :

No.     Time        Source                Destination           Protocol Info
1 0.000000    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1
2 0.101794    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.1.0
3 0.101915    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.1.0
4 0.172930    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.2.0
5 0.173003    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.2.0
6 0.244100    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.3.0
7 0.244174    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.3.0
8 0.315341    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.4.0
9 0.315412    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.4.0
10 0.389045    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.5.0
11 0.389109    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.5.0
12 0.460725    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.6.0
13 0.460787    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.6.0
14 0.532128    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.7.0
15 0.532189    192.168.0.16          172.16.252.2          SNMP     get-next-request 1.3.6.1.2.1.1.7.0
16 0.624758    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.2.1.0

Pas la peine de détailler, nous voyons bien une suite de get-next-request émises par le client, suivies des get-response de l'agent SNMP du switch. Nous avons ici 8 trames d'interrogation et 8 trames de réponse. Si l'on désire parcourir une branche importante, le réseau va avoir du travail.

VII-C - snmpbulkwalk

Innovation de la version 2c, observons la différence :

$ snmpbulkwalk -v 1 -c public -Ot 172.16.252.2 SNMPv2-MIB::system
snmpbulkwalk: Cannot send V2 PDU on V1 session

Juste pour vérifier que cette commande ne peut fonctionner si l'on utilise SNMP v1.

$ snmpbulkwalk -v 2c -c public -Ot 172.16.252.2 SNMPv2-MIB::system
SNMPv2-MIB::sysDescr.0 = STRING: ProCurve J4899B Switch 2650, revision H.10.35, ROM H.08.02 (/sw/code/build/fish(mkfs))
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.11.2.3.7.11.44
DISMAN-EVENT-MIB::sysUpTimeInstance = 1123894614
SNMPv2-MIB::sysContact.0 = STRING: sysop
SNMPv2-MIB::sysName.0 = STRING: ProCurve Switch 2650-1
SNMPv2-MIB::sysLocation.0 = STRING:
SNMPv2-MIB::sysServices.0 = INTEGER: 74

À première vue, nous obtenons exactement le même résultat qu'avec snmpwalk. Cependant, voici ce qu'a vu Wireshark en vue condensée :

No.     Time        Source                Destination           Protocol Info
1 0.000000    192.168.0.16          172.16.252.2          SNMP     getBulkRequest 1.3.6.1.2.1.1
2 0.077623    172.16.252.2          192.168.0.16          SNMP     get-response 1.3.6.1.2.1.1.1.0 1.3.6.1.2.1.1.2.0 1.3.6.1.2.1.1.3.0 1.3.6.1.2.1.1.4.0 1.3.6.1.2.1.1.5.0 1.3.6.1.2.1.1.6.0 1.3.6.1.2.1.1.7.0 1.3.6.1.2.1.2.1.0 1.3.6.1.2.1.2.2.1.1.1 1.3.6.1.2.1.2.2.1.1.2

Deux trames seulement. Voyons maintenant le détail :

Frame 1 (83 bytes on wire, 83 bytes captured)
...
Simple Network Management Protocol
version: v2c (1)
community: public
data: getBulkRequest (5)
getBulkRequest
request-id: 112026182
non-repeaters: 0
max-repetitions: 10
variable-bindings: 1 item
1.3.6.1.2.1.1: Value (Null)
Object Name: 1.3.6.1.2.1.1 (iso.3.6.1.2.1.1)
Value (Null)

La requête est ici getBulkRequest et elle est unique. Tout le détail de la branche se trouve dans une seule réponse :

Frame 2 (353 bytes on wire, 353 bytes captured)
...
Simple Network Management Protocol
version: v2c (1)
community: public
data: get-response (2)
get-response
request-id: 112026182
error-status: noError (0)
error-index: 0
variable-bindings: 10 items
1.3.6.1.2.1.1.1.0: 50726F4375727665204A3438393942205377697463682032...
Object Name: 1.3.6.1.2.1.1.1.0 (iso.3.6.1.2.1.1.1.0)
Value (OctetString): 50726F4375727665204A3438393942205377697463682032...
1.3.6.1.2.1.1.2.0: 1.3.6.1.4.1.11.2.3.7.11.44 (iso.3.6.1.4.1.11.2.3.7.11.44)
Object Name: 1.3.6.1.2.1.1.2.0 (iso.3.6.1.2.1.1.2.0)
Value (OID): 1.3.6.1.4.1.11.2.3.7.11.44 (iso.3.6.1.4.1.11.2.3.7.11.44)
1.3.6.1.2.1.1.3.0: 1123894614
Object Name: 1.3.6.1.2.1.1.3.0 (iso.3.6.1.2.1.1.3.0)
Value (Timeticks): 1123894614
1.3.6.1.2.1.1.4.0: 7379736F70
Object Name: 1.3.6.1.2.1.1.4.0 (iso.3.6.1.2.1.1.4.0)
Value (OctetString): 7379736F70
1.3.6.1.2.1.1.5.0: 50726F43757276652053776974636820323635302D31
Object Name: 1.3.6.1.2.1.1.5.0 (iso.3.6.1.2.1.1.5.0)
Value (OctetString): 50726F43757276652053776974636820323635302D31
1.3.6.1.2.1.1.6.0:
Object Name: 1.3.6.1.2.1.1.6.0 (iso.3.6.1.2.1.1.6.0)
Value (OctetString):
1.3.6.1.2.1.1.7.0: 74
Object Name: 1.3.6.1.2.1.1.7.0 (iso.3.6.1.2.1.1.7.0)
Value (Integer32): 74
1.3.6.1.2.1.2.1.0: 55
Object Name: 1.3.6.1.2.1.2.1.0 (iso.3.6.1.2.1.2.1.0)
Value (Integer32): 55
1.3.6.1.2.1.2.2.1.1.1: 1
Object Name: 1.3.6.1.2.1.2.2.1.1.1 (iso.3.6.1.2.1.2.2.1.1.1)
Value (Integer32): 1
Object Name: 1.3.6.1.2.1.2.2.1.1.2 (iso.3.6.1.2.1.2.2.1.1.2)
Value (Integer32): 2

Deux trames qui font le même boulot que les 16 précédentes avec snmpwalk, le réseau va apprécier. De quoi convaincre d'utiliser plutôt v2c, quand c'est possible.

VIII - Exercice pratique

VIII-A - Le problème

Soit un switch (toujours le même), configuré comme indiqué ici, c'est-à-dire que nous disposons d'un serveur RADIUS, avec une base de données qui recense toutes les adresses MAC de nos stations.

Nous avons enrichi cette base en ajoutant le nom des stations. Par ailleurs, nous avons une table qui relie le numéro de chaque port du switch au numéro de la prise dans l'établissement.

Nous voulons utiliser SNMP pour savoir quels sont les clients actuellement en service et sur quelle prise (i.e. sur quel port de switch) ils sont branchés.

SNMP va peut-être nous permettre de savoir quelles adresses MAC sont présentes sur chaque port du switch (habituellement une seule), si notre BRIDGE-MIB définit cette information et indique où la trouver. C'est dans ces cas qu'un browser de MIB montre son utilité. Même tkmib sera plus agréable à manipuler que snmptranslate.

Notons un outil en ligne digne d'intérêt, le « SimpleWeb » dans la rubrique MIB en ce qui nous concerne dans le cas de figure. Nous trouvons la BRIDGE-MIB, développons son arborescence, et voyons que :

BRIDGE-MIB::dot1dTpFdbAddress
dot1dTpFdbAddress OBJECT-TYPE
-- FROM    BRIDGE-MIB
-- TEXTUAL CONVENTION MacAddress
SYNTAX    OCTET STRING (6)
DISPLAY-HINT    "1x:"
MAX-ACCESS    read-only
STATUS    current
DESCRIPTION    "A unicast MAC address for which the bridge has
forwarding and/or filtering information."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) dot1dBridge(17) dot1dTp(4) dot1dTpFdbTable(3) dot1dTpFdbEntry(1) 1 }

et que

BRIDGE-MIB::dot1dTpFdbPort
dot1dTpFdbPort OBJECT-TYPE
-- FROM    BRIDGE-MIB
SYNTAX    Integer32
MAX-ACCESS    read-only
STATUS    current
DESCRIPTION    "Either the value '0', or the port number of the port on
which a frame having a source address equal to the value
of the corresponding instance of dot1dTpFdbAddress has
been seen.  A value of '0' indicates that the port
number has not been learned, but that the bridge does
have some forwarding/filtering information about this
address (e.g., in the dot1dStaticTable).  Implementors
are encouraged to assign the port value to this object
whenever it is learned, even for addresses for which the
corresponding value of dot1dTpFdbStatus is not
learned(3)."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) dot1dBridge(17) dot1dTp(4) dot1dTpFdbTable(3) dot1dTpFdbEntry(1) 2 }

Ces deux OID sont susceptibles de nous intéresser.

Comme par ce beau jour d'été (nous sommes le 13 juillet 2010), il n'y a pas grand monde dans l'établissement, nous allons réaliser la manipulation sur le switch de tête, celui qui connecte tous les serveurs et les autres switches, le seul qui voit du monde à cette date.

VIII-B - Que dit SNMP ?

VIII-B-1 - dot1dTpFdbAddress

~$ snmpbulkwalk -Ob -m  +/var/lib/mibs/ietf/BRIDGE-MIB -c public -v 2c 172.16.252.4  BRIDGE-MIB::dot1dTpFdbAddress

L'option -Ob, comme dit le man : Display table indexes numerically, rather than trying to interpret the instance subidentifiers as string or OID values.

BRIDGE-MIB::dot1dTpFdbAddress.0.5.93.8.128.1 = STRING: 0:5:5d:8:80:1
BRIDGE-MIB::dot1dTpFdbAddress.0.19.212.88.167.204 = STRING: 0:13:d4:58:a7:cc
BRIDGE-MIB::dot1dTpFdbAddress.0.23.8.228.70.128 = STRING: 0:17:8:e4:46:80
BRIDGE-MIB::dot1dTpFdbAddress.0.23.8.228.70.206 = STRING: 0:17:8:e4:46:ce
BRIDGE-MIB::dot1dTpFdbAddress.0.23.8.228.197.0 = STRING: 0:17:8:e4:c5:0
BRIDGE-MIB::dot1dTpFdbAddress.0.23.8.228.197.79 = STRING: 0:17:8:e4:c5:4f
BRIDGE-MIB::dot1dTpFdbAddress.0.33.145.133.119.77 = STRING: 0:21:91:85:77:4d
BRIDGE-MIB::dot1dTpFdbAddress.0.35.84.55.145.46 = STRING: 0:23:54:37:91:2e
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.84.111 = STRING: 0:30:84:3a:54:6f
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.85.170 = STRING: 0:30:84:3a:55:aa
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.97.178 = STRING: 0:30:84:3a:61:b2
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.99.185 = STRING: 0:30:84:3a:63:b9
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.99.199 = STRING: 0:30:84:3a:63:c7
BRIDGE-MIB::dot1dTpFdbAddress.0.48.132.58.100.151 = STRING: 0:30:84:3a:64:97
BRIDGE-MIB::dot1dTpFdbAddress.144.230.186.157.115.173 = STRING: 90:e6:ba:9d:73:ad

Nous pouvons aussi le faire de façon totalement numérique :

~$ snmpbulkwalk -On -m  +/var/lib/mibs/ietf/BRIDGE-MIB -c public -v 2c 172.16.252.4  BRIDGE-MIB::dot1dTpFdbAddress
.1.3.6.1.2.1.17.4.3.1.1.0.5.93.8.128.1 = STRING: 0:5:5d:8:80:1
.1.3.6.1.2.1.17.4.3.1.1.0.19.212.88.167.204 = STRING: 0:13:d4:58:a7:cc
.1.3.6.1.2.1.17.4.3.1.1.0.23.8.228.70.128 = STRING: 0:17:8:e4:46:80
.1.3.6.1.2.1.17.4.3.1.1.0.23.8.228.70.206 = STRING: 0:17:8:e4:46:ce
.1.3.6.1.2.1.17.4.3.1.1.0.23.8.228.197.0 = STRING: 0:17:8:e4:c5:0
.1.3.6.1.2.1.17.4.3.1.1.0.23.8.228.197.79 = STRING: 0:17:8:e4:c5:4f
.1.3.6.1.2.1.17.4.3.1.1.0.33.145.133.119.77 = STRING: 0:21:91:85:77:4d
.1.3.6.1.2.1.17.4.3.1.1.0.35.84.55.145.46 = STRING: 0:23:54:37:91:2e
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.84.111 = STRING: 0:30:84:3a:54:6f
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.85.170 = STRING: 0:30:84:3a:55:aa
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.97.178 = STRING: 0:30:84:3a:61:b2
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.99.185 = STRING: 0:30:84:3a:63:b9
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.99.199 = STRING: 0:30:84:3a:63:c7
.1.3.6.1.2.1.17.4.3.1.1.0.48.132.58.100.151 = STRING: 0:30:84:3a:64:97
.1.3.6.1.2.1.17.4.3.1.1.144.230.186.157.115.173 = STRING: 90:e6:ba:9d:73:ad

Dans un cas comme dans l'autre, nous avons une table (.1.3.6.1.2.1.17.4.3.1.1.) qui contient toutes les adresses MAC que notre switch a vu passer. Ceci ne répond pas à notre question, mais nous apprend tout de même quelque chose, si l'on y regarde de plus près : les clés (surlignées en jaune), ne sont rien d'autre que l'expression en base 10 de l'adresse MAC correspondante. Cette remarque va nous servir dans la suite immédiate.

VIII-B-2 - dot1dTpFdbPort

Intéressons nous à la table suivante dont le descriptif dit clairement :
Either the value '0', or the port number of the port on which a frame having a source address equal to the value of the corresponding instance of dot1dTpFdbAddress has been seen.

~$ snmpbulkwalk -On -m  +/var/lib/mibs/ietf/BRIDGE-MIB -c public -v 2c 172.16.252.4  BRIDGE-MIB::dot1dTpFdbPort
.1.3.6.1.2.1.17.4.3.1.2.0.5.93.8.128.1 = INTEGER: 11
.1.3.6.1.2.1.17.4.3.1.2.0.19.212.88.167.204 = INTEGER: 5
.1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.70.128 = INTEGER: 23
.1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.70.206 = INTEGER: 23
.1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.197.0 = INTEGER: 24
.1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.197.79 = INTEGER: 24
.1.3.6.1.2.1.17.4.3.1.2.0.33.145.133.119.77 = INTEGER: 0
.1.3.6.1.2.1.17.4.3.1.2.0.35.84.55.145.46 = INTEGER: 6
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.84.111 = INTEGER: 8
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.85.170 = INTEGER: 9
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.97.178 = INTEGER: 10
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.99.185 = INTEGER: 4
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.99.199 = INTEGER: 3
.1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.100.151 = INTEGER: 7
.1.3.6.1.2.1.17.4.3.1.2.144.230.186.157.115.173 = INTEGER: 13

Cette table contient des numéros de ports, les clés correspondantes n'étant rien d'autre que l'expression décimale de l'adresse MAC vue sur ce port. D'ailleurs :

~$ snmpbulkwalk -OX -m  +/var/lib/mibs/ietf/BRIDGE-MIB -c public -v 2c 172.16.252.4  BRIDGE-MIB::dot1dTpFdbPort

L'option -OX comme le dit tout à fait clairement le man :
Display table indexes in a more “program like” output, imitating a traditional array-style index format.
Ceci permet d'afficher le résultat de façon bien lisible :

BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:5:5d:8:80:1] = INTEGER: 11
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:13:d4:58:a7:cc] = INTEGER: 5
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:17:8:e4:46:80] = INTEGER: 23
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:17:8:e4:46:ce] = INTEGER: 23
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:17:8:e4:c5:0] = INTEGER: 24
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:17:8:e4:c5:4f] = INTEGER: 24
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:21:91:85:77:4d] = INTEGER: 0
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:23:54:37:91:2e] = INTEGER: 6
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:54:6f] = INTEGER: 8
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:55:aa] = INTEGER: 9
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:61:b2] = INTEGER: 10
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:63:b9] = INTEGER: 4
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:63:c7] = INTEGER: 3
BRIDGE-MIB::dot1dTpFdbPort[STRING: 0:30:84:3a:64:97] = INTEGER: 7
BRIDGE-MIB::dot1dTpFdbPort[STRING: 90:e6:ba:9d:73:ad] = INTEGER: 13

Nous avons ici exactement l'information que nous recherchons, à savoir une table dont les clés sont les adresses MAC et les données le numéro du port qui les a vues.

En regardant bien ce tableau, nous constatons deux choses :

VIII-B-2-a - Le port 0

Le port 0 représente une adresse MAC connue du switch, mais ne venant pas d'un port réel. En l'occurrence, il s'agit d'une adresse MAC du switch lui-même :

~# arp -an
...
? (172.16.252.4) at 00:21:91:85:77:4d [ether] on eth0
...

VIII-B-2-b - Les ports 23 et 24

Ces ports sont référencés deux fois dans la table. C'est possible et même normal qu'un même port puisse voir plusieurs adresses MAC, si un autre switch est connecté dessus, ce qui est le cas ici.

VIII-C - Un début de solution

Compte tenu du problème énoncé, il est clair qu'il va falloir coder un outil qui réponde à la question. Pas question de le réaliser ici, mais nous allons amorcer la solution en utilisant PHP, juste pour montrer que l'on peut utiliser facilement un langage quelconque, du moment qu'il propose une bibliothèque pour gérer SNMP, ce qui est le cas de PHP. Cette bibliothèque est rudimentaire, mais suffisante pour nos besoins.

Nous avons bien dans un coin une Debian qui traine, avec Apache, MySQL et PHP, sur le serveur RADIUS par exemple. Nous allons juste réaliser une fonction qui remplira un tableau avec ce que nous dit SNMP.

Il faut bien entendu installer le module php5-snmp pour réaliser l'opération.

VIII-C-1 - Premier essai

Grâce par exemple au SimpleWeb, nous savons que l'OID de la table qui nous intéresse est .1.3.6.1.2.1.17.4.3.1.2.

Voici un premier code PHP (>= 5.2) :

<?php
// nous souhaitons traiter les OID de façon numérique
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);

$OID = '.1.3.6.1.2.1.17.4.3.1.2';

$X = snmprealwalk('172.16.252.4', 'public',$OID);
foreach($X as $key => $value) {
$macAddr = $key;
$port = $value;
echo $port.' == '.$macAddr.'<br />';
}
?>

La fonction snmp_set_oid_output_format permet d'indiquer comment nous désirons traiter les OID. Ici, sous forme numérique. SNMP_OID_OUTPUT_NUMERIC est une constante prédéfinie dans le module php5-snmp.

La fonction snmprealwalk est un genre de snmpwalk où l'on indique comme paramètres :

- la cible (adresse IP ou nom DNS) ;

- la communauté ;

- l'OID d'où l'on veut partir.

Ceci va nous donner le résultat suivant :

INTEGER: 11 == .1.3.6.1.2.1.17.4.3.1.2.0.5.93.8.128.1
INTEGER: 5 == .1.3.6.1.2.1.17.4.3.1.2.0.19.212.88.167.204
INTEGER: 23 == .1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.70.128
INTEGER: 23 == .1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.70.206
INTEGER: 24 == .1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.197.0
INTEGER: 24 == .1.3.6.1.2.1.17.4.3.1.2.0.23.8.228.197.79
INTEGER: 0 == .1.3.6.1.2.1.17.4.3.1.2.0.33.145.133.119.77
INTEGER: 6 == .1.3.6.1.2.1.17.4.3.1.2.0.35.84.55.145.46
INTEGER: 8 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.84.111
INTEGER: 9 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.85.170
INTEGER: 10 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.97.178
INTEGER: 4 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.99.185
INTEGER: 3 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.99.199
INTEGER: 7 == .1.3.6.1.2.1.17.4.3.1.2.0.48.132.58.100.151
INTEGER: 13 == .1.3.6.1.2.1.17.4.3.1.2.144.230.186.157.115.173

Pas bien exploitable. Il nous faut nettoyer un peu :

- les clés (OID) en enlevant l'OID de la table (.1.3.6.1.2.1.17.4.3.1.2.) ;

- les données en enlevant le type (INTEGER: ) ;

VIII-C-2 - Deuxième essai

Comme ceci n'est pas un cours de PHP, voici juste une façon de faire, parmi tant d'autres. La documentation officielle de PHP vous sera éventuellement d'un grand secours.

<?php
// nous souhaitons traiter les OID de façon numérique
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);

$OID = '.1.3.6.1.2.1.17.4.3.1.2';

$X = snmprealwalk('172.16.252.4', 'public',$OID);
foreach($X as $key => $value) {
$macAddr = substr($key,strlen($OID)+1) ;
$port = explode(': ',$value,2);
echo $port[1].' == '.$macAddr.'<br />';
}
?>

Ceci nous donne déjà quelque chose de plus exploitable :

11 == 0.5.93.8.128.1
5 == 0.19.212.88.167.204
23 == 0.23.8.228.70.128
23 == 0.23.8.228.70.206
24 == 0.23.8.228.197.0
24 == 0.23.8.228.197.79
0 == 0.33.145.133.119.77
6 == 0.35.84.55.145.46
8 == 0.48.132.58.84.111
9 == 0.48.132.58.85.170
10 == 0.48.132.58.97.178
4 == 0.48.132.58.99.185
3 == 0.48.132.58.99.199
7 == 0.48.132.58.100.151
13 == 144.230.186.157.115.173

Cependant :

- les adresses MAC (les clés) ne sont pas dans un format exploitable (représentation hexadécimale) ;

- les ports (les données) sont sous forme de texte, si bien qu'un tri se fera suivant le code ASCII, ce qui n'a pas de sens ici.

Nous allons donc créer un second tableau, avec des clés (adresses MAC) dans le format utilisé sur FreeRADIUS et des données de type entier.

VIII-C-3 - Troisième essai

VIII-C-3-a - L'adresse MAC

Créons une fonction dans laquelle nous injecterons l'adresse sous sa forme décimale, et qui nous renverra une chaine sous forme hexadécimale, avec le délimiteur : :

function parseMacAddr($T) {
$tok = strtok($T,".");
while ($tok !== false) {
$oct=dechex($tok);
settype($oct,"string");
if (strlen($oct)==1) $oct = "0".$oct;
$macAddr = $macAddr.$oct.":";
$tok = strtok(".");
}
$macAddr = substr($macAddr,0,strlen($macAddr)-1);
return $macAddr;
}

La fonction strtok n'est pas d'un usage bien intuitif, mais pour ceux qui ne la connaissent pas, la documentation donne des exemples clairs.

VIII-C-3-b - La solution définitive (?)

Finalement, le code suivant :

<?php
function parseMacAddr($T) {
$tok = strtok($T,".");
while ($tok !== false) {
$oct=dechex($tok);
settype($oct,"string");
if (strlen($oct)==1) $oct = "0".$oct;
$macAddr = $macAddr.$oct.":";
$tok = strtok(".");
}
$macAddr = substr($macAddr,0,strlen($macAddr)-1);
return $macAddr;
}

// nous souhaitons traiter les OID de façon numérique
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);

$OID = '.1.3.6.1.2.1.17.4.3.1.2';

$X = snmprealwalk('172.16.252.4', 'public',$OID);
foreach($X as $key => $value) {
$macAddr = parseMacAddr(substr($key,strlen($OID)+1));
$port = explode(': ',$value,2);
settype($port[1],'integer');
$Y[$macAddr]=$port[1];
}

unset($X);
asort($Y);

foreach($Y as $key => $value) {
echo $value.' == '.$key.'<br />';
}
?>

donne quelque chose d'acceptable :

0 == 00:21:91:85:77:4d
3 == 00:30:84:3a:63:c7
4 == 00:30:84:3a:63:b9
5 == 00:13:d4:58:a7:cc
6 == 00:23:54:37:91:2e
7 == 00:30:84:3a:64:97
8 == 00:30:84:3a:54:6f
9 == 00:30:84:3a:55:aa
10 == 00:30:84:3a:61:b2
11 == 00:05:5d:08:80:01
13 == 90:e6:ba:9d:73:ad
23 == 00:17:08:e4:46:80
23 == 00:17:08:e4:46:ce
24 == 00:17:08:e4:c5:4f
24 == 00:17:08:e4:c5:00

Notre tableau Y contient les informations issues du switch dans un format que l'on pourra aisément utiliser dans des requêtes sur notre base MySQL.

VIII-D - Pour finir

Beaucoup d'autres informations intéressantes peuvent être obtenues par SNMP. Toujours sur nos switches, il peut être utile de visualiser le trafic sur certains ports pour surveiller par exemple des goulots d'étranglement. SNMP couplé à des outils comme Cacti ou Zabbix permettra alors d'obtenir de jolis graphes et d'en conserver l'historique.

IX - Les réponses

IX-A - Interro surprise 1

Est-ce que ceci aurait des chances de fonctionner ?

~$ snmptranslate -Ot -Td .1.3.6.1.2.1.17.1.2.0

Pas vraiment, puisque cette branche est couverte par la MIB BRIDGE-MIB. Nous aurons donc une réponse très incomplète :

SNMPv2-SMI::mib-2.17.1.2.0
mib-2 OBJECT-TYPE
-- FROM    SNMPv2-SMI, RFC1213-MIB
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) 17 1 2 0 }

Et ceci :

~$ snmptranslate -Ot -Td -m /usr/share/mibs/ietf/BRIDGE-MIB .1.3.6.1.2.1.17.1.2.0

Dans ce cas, nous aurons effectivement une réponse plus explicite :

BRIDGE-MIB::dot1dBaseNumPorts.0
dot1dBaseNumPorts OBJECT-TYPE
-- FROM       BRIDGE-MIB
SYNTAX        Integer32
UNITS         "ports"
MAX-ACCESS    read-only
STATUS        current
DESCRIPTION   "The number of ports controlled by this bridging
entity."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) dot1dBridge(17) dot1dBase(1) dot1dBaseNumPorts(2) 0 }

Une description quasi compréhensible, ainsi que le type de réponse (Integer32) et l'unité, ici le nombre de ports. Ce paramètre est bien entendu accessible en lecture seule. Il serait en effet miraculeux que SNMP ait le pouvoir de multiplier les ports d'un switch, au grand détriment des profits des constructeurs.

IX-B - Interro surprise 2

Pour rappel :

com2sec voirUnPeu     default                public
com2sec voirTout      192.168.0.0/24         private
com2sec voirEtToucher 192.168.0.16           admin

group touristes v1         voirUnPeu
group touristes v2c        voirUnPeu
group riverains v1         voirTout
group riverains v2c        voirTout
group proprio   v1         voirEtToucher
group proprio   v2c        voirEtToucher

view system included       .1.3.6.1.2.1.1.1
view all    included       .1

access touristes ""      any       noauth    exact  system none   none
access riverains ""      any       noauth    exact  all    none   none
access proprio   ""      any       noauth    exact  all    all    none

1. Quelqu'un se déclarant de la communauté public pourra-t-il

1. se connecter depuis n'importe quelle adresse IP ?

Oui il pourra puisque la communauté public peut se connecter depuis default, c'est-à-dire de n'importe où (sous réserve qu'il n'y ait pas de restrictions mises à l'écoute du service lors de son lancement)

2. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces ? (on pourra s'aider de snmptranslate pour obtenir la version numérique de cette branche)

Non. La version numérique de cette branche est .1.3.6.1.2.1.2. La communauté public fait partie du groupe voirUnPeu qui lui-même fait partie des touristes. Les touristes n'ont accès qu'à la vue system c'est-à-dire la branche .1.3.6.1.2.1.1.1 seulement, et .1.3.6.1.2.1.2 n'en est pas une sous-branche.

2. Quelqu'un se déclarant de la communauté private pourra-t-il

1. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.1.25 ?

Non, la communauté private est accessible seulement à partir du sous-réseau 192.168.0.0/24 et 192.168.1.25 n'est pas dans ce sous-réseau.

2. obtenir les informations de la branche .iso.org.dod.Internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.0.25 ?

Oui. L'adresse IP est cette fois-ci autorisée. De plus, la communauté private est dans voirTout donc ce sont des riverains qui ont droit à la vue de tout l'arbre.

3. Quelqu'un se déclarant de la communauté admin depuis l'adresse IP 192.168.0.17

1. pourra-t-il obtenir les informations de la branche .1.3.6.1.2.1.2 ?

2. pourra-t-il modifier une valeur accessible en écriture (SNMPv2-MIB::sysLocation par exemple) ?

Non. Dans tous les cas, la communauté admin ne peut utiliser que l'adresse IP 192.168.0.16, ce qui n'est pas le cas ici. Sinon, cette communauté pouvant voirEtToucher c'est-à-dire faisant partie de proprio peut lire et écrire dans la vue all donc dans tout l'arbre (mais seulement depuis la station d'adresse IP 192.168.0.16)

X - Remerciements Developpez

Vous pouvez retrouver l'article original ici : L'Internet Rapide et Permanent. Christian Caleca a aimablement autorisé l'équipe « Réseaux » de Developpez.com à reprendre son article. Retrouvez tous les articles de Christian Caleca sur cette page.

Nos remerciements à Max pour sa relecture orthographique.

N'hésitez pas à commenter cet article ! Commentez

(1)logiciel très proche du matériel, logé dans une mémoire non volatile : ROM, EPROM, etc. dont le but est de gérer basiquement ledit matériel, notamment son initialisation à la mise sous tension. Le « driver » sert à interfacer le système d'exploitation avec le « firmware » d'un composant périphérique, comme une carte réseau, une carte son… Dans le cas d'une carte mère, le « firmware » peut être assimilé au BIOS, bien qu'à mon sens, le firmware n'en soit qu'un sous-ensemble.

(2)appelée BRIDGE-MIB et définie dans la rfc 1493