====== snmp ====== ===== Liens ===== *http://www.queret.net/blog/index.php/2007/04/26/82-linux-debian-40-etch-installer-et-configurer-un-serveur-snmp *http://www.net-snmp.org/wiki/index.php/Tutorials *http://lea-linux.org/pho/read/5/326891 En relation avec nagios: *http://nagiosplugins.org/man/check_snmp ===== Introduc ===== ==== Client/Serveur ==== **''smnpd''** est un daemon qui attend les requetes des clients. Les logiciels clients sont **''snmpget''**, **''snmpgetnext''**, **''snmpwalk''**, etc... Le daemon **''smnpd''** peut dés l'installation répondre a quelques requetes... (encore faut-il le configurer pour autoriser les clients) ==== OID & MIB ==== OID ----- Object IDentifier\\ Version numéric d'un MIB (?)\\ Exemple: ''.1.3.6.1.2.1.1.3.0'' [[http://fr.wikipedia.org/wiki/Management_Information_Base|MIB]] ----- Management Information Base\\ Version ascii d'un OID (?)\\ Exemple: ''SNMPv2-MIB::sysUpTime.0'' ==== Arbre ==== Les objects sont disposés dans un "arbre", qu'on parcours en commencant par "."... Voir la commande **''snmptranslate''** qui permet de convertir un OID en MIB et inversement. {{http://upload.wikimedia.org/wikipedia/commons/1/1c/SNMP.MIB-Tree.PNG|}} ====== installation ====== ===== snmpd ===== # aptitude install snmpd Le "daemon" ecoute en **''udp''** sur le port **''161''**.\\ Il attend les requetes des clients. Les clients sont autorisés selon le fichier **''/etc/snmp/snmpd.conf''**.\\ Dans les extraits suivants, j'ai coupé les parties présentes par défaut, du genre: # sec.name source community com2sec paranoid default public #com2sec readonly default public #com2sec readwrite default private ... ==== community ==== Dans le fichier **''snmpd.conf''** : #### # 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 # TJ ----------- com2sec admin localhost code_secret1 com2sec admin 10.20.0.20 code_secret2 com2sec localnet 10.20.0.0/16 code_secret3 # -------------- | com2sec | déclare la relation entre une communauté et un "security name" | | sec.name | "security name" (groupe) associé a la communauté | | source | d'où qui vient | | community | le nom de la communauté | Dans les faits, ce qui est nommé "community" (communauté), est un pseudo mot de passe. | :!: | les mots de passe circulent en clair ! (sauf depuis la "v3", si bien configuré, mais pas trés populaire il me semble...) | ==== group ==== Dans **''snmpd.conf''** : #### # Second, map the security names into group names: # sec.model sec.name # TJ ----------- group RWmaison v1 admin group RWmaison v2c admin group ROmaison v1 localnet group ROmaison v2c localnet # -------------- Là, on créé des groupes... | group | This directive defines the mapping from securitymodel/securityname to group. | | name | le nom du groupe | | sec.model | "security model" ... la version du protocole plutot... non ? | | sec.name | le "security name" qui nous renvoit vers la "commununity" | | "v1" | c'est bien, ca passe partout. y a juste des soucis avec les compteurs 64 bits | | "v2c" | (version 2 en fait, mais bon), c'est mieux, sans les problèmes de la "v1" | | "v3" | c'est encore mieux, mot de passe crypté, etc...: trop compliqué pour moi | Comme vous le voyez, on peut avoir plusieurs versions ! super. ==== view ==== #### # Third, create a view for us to let the groups have rights to: # incl/excl subtree mask view all included .1 80 view system included .iso.org.dod.internet.mgmt.mib-2.system Là, j'ai rien touché.\\ Ca semble definir des "groupes" de qu'on a le droit de voir. (et lire ou ecrire) ==== access ==== #### # Finally, grant the 2 groups access to the 1 view with different # write permissions: # context sec.model sec.level match read write notif # TJ --------- access ROmaison "" any noauth exact all none none access RWmaison "" any noauth exact all all none # ------------ | context | voir ''man'' | | sec.model | "v1" "v2c" "any" etc... selon les "protocoles" accepté | | sec.level | "noauth" => sans authentication (le "community name" suffit) | | match | voir ''man'' | | read | autorise la lecture ou pas | | write | autorise l'ecriture ou pas | | notif | voir ''man'' | ==== Conclusion ==== Au final le "snmpd.conf" permet l'accés au client. # /etc/init.d/snmpd restart ===== Clients ===== ==== Installer ==== # aptitude update # aptitude install snmp (Et **''libsnmp-session-perl''** ?) Et voila. ==== snmptranslate ==== Transformer un OID en MIB : $ snmptranslate .1.3.6.1.2.1.1.3.0 DISMAN-EVENT-MIB::sysUpTimeInstance Transformer un MIB en OID : $ snmptranslate -On DISMAN-EVENT-MIB::sysUpTimeInstance .1.3.6.1.2.1.1.3.0 Transformer en ses sous-identifiers nommés: $ snmptranslate -Of DISMAN-EVENT-MIB::sysUpTimeInstance .iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance Un **''MIB''** est garantie etre unique (sauf rare cas isolé).\\ De ce fait, il doit être précis.\\ Par exemple: $ snmptranslate sysUpTimeInstance No log handling enabled - turning on stderr logging sysUpTimeInstance: Unknown Object Identifier (Sub-id not found: (top) -> sysUpTimeInstance) Ca ne fonctionne pas, sauf si on demande a la commande de faire une recherche "aléatoire" : $ snmptranslate -IR sysUpTimeInstance DISMAN-EVENT-MIB::sysUpTimeInstance Ou $ snmptranslate -On -IR sysUpTimeInstance .1.3.6.1.2.1.1.3.0 Recherche par 'regex': $ snmptranslate -Ib 'sys.*ime' SNMPv2-MIB::sysORUpTime Oups, ce n'est pas ce qu'on voulait: $ snmptranslate -Ib 'sysUp.*ime' SNMPv2-MIB::sysUpTime Pour avoir la liste des "noeuds" qui corresponde a la recherche: $ snmptranslate -TB 'sys.*ime' SNMPv2-MIB::sysORUpTime SNMPv2-MIB::sysUpTime DISMAN-EVENT-MIB::sysUpTimeInstance HOST-RESOURCES-MIB::hrSystemUptime La description complete (pas trés clair dans cet exemple): $ snmptranslate -On -Td DISMAN-EVENT-MIB::sysUpTimeInstance .1.3.6.1.2.1.1.3.0 sysUpTimeInstance OBJECT-TYPE -- FROM DISMAN-EVENT-MIB ::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) system(1) sysUpTime(3) 0 } Un diagramme: $ snmptranslate -Tp -IR 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 Oh! un arbre! ==== v1 ou v2c ==== Il faudra choisir un protocole "-v1" , "-v 1" , "-v2c" ou "-v 2c". Les réponses n'ont pas toujours le même format. Nous, on choisira "-v 2c" ... mouai. ==== snmpget ==== Retourne l'information associé à un object "MIB": $ snmpget -v 2c -c DISMAN-EVENT-MIB::sysUpTimeInstance DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (8193500) 22:45:35.00 On précise la version "2c", la "", l'adresse de l'hôte a interroger, et la MIB. Soit en clair: $ snmpget -v 2c -c code_secret1 localhost DISMAN-EVENT-MIB::sysUpTimeInstance En plus simple: $ snmpget -v 2c -c code_secret1 localhost sysUpTime.0 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (8221481) 22:50:14.81 Plus interessant: $ snmpget -v 2c -c code_secret1 localhost UCD-SNMP-MIB::extOutput.1 UCD-SNMP-MIB::extOutput.1 = STRING: RAID OK (2/2) (sera developpé ultérieurement) ==== snmpgetnext ==== Pareil que "snmpget", sauf que ca retourne l'objet valide **''SUIVANT''** . L'interet est de simplifier les requetes en laissant la commande rechercher l'objet valide dans les sous-branches. Exemple: $ snmpgetnext -v 2c -c code_secret1 localhost DISMAN-EVENT-MIB::sysUpTimeInstance.0 SNMPv2-MIB::sysContact.0 = STRING: Root (configure /etc/snmp/snmpd.local.conf) C'est bien le suivant! Mais c'est surtout interessant pour les OID incomplets: $ snmpgetnext -v 2c -c code_secret1 localhost sysUpTime DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (8262728) 22:57:07.28 Comme vous pouvez l'imaginer, on peut "marcher" en parcourant l'arbre... ==== snmpwalk ==== Retourne quelques infos de l'arbre: $ snmpwalk -v 2c -c code_secret1 localhost sysORID SNMPv2-MIB::sysORID.1 = OID: IF-MIB::ifMIB SNMPv2-MIB::sysORID.2 = OID: SNMPv2-MIB::snmpMIB SNMPv2-MIB::sysORID.3 = OID: TCP-MIB::tcpMIB SNMPv2-MIB::sysORID.4 = OID: IP-MIB::ip SNMPv2-MIB::sysORID.5 = OID: UDP-MIB::udpMIB SNMPv2-MIB::sysORID.6 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup SNMPv2-MIB::sysORID.7 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance SNMPv2-MIB::sysORID.8 = OID: SNMP-MPD-MIB::snmpMPDCompliance SNMPv2-MIB::sysORID.9 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance Retourner toutes les informations de la branche ".1" $ snmpwalk -v 2c -c code_secret1 localhost .1 ou $ snmpwalk -v 2c -c code_secret1 localhost .iso (huge output !) Un poil plus interessant: $ snmpwalk -v 2c -c code_secret1 localhost .1.3.6.1.4.1.2021.8.1 UCD-SNMP-MIB::extIndex.1 = INTEGER: 1 UCD-SNMP-MIB::extNames.1 = STRING: raidmon UCD-SNMP-MIB::extCommand.1 = STRING: /usr/bin/sudo /root/prod/snmpd/raidmon UCD-SNMP-MIB::extResult.1 = INTEGER: 0 UCD-SNMP-MIB::extOutput.1 = STRING: RAID OK (2/2) UCD-SNMP-MIB::extErrFix.1 = INTEGER: 0 UCD-SNMP-MIB::extErrFixCmd.1 = STRING: ==== snmptable ==== Sortir des tables... $ snmptable -v 2c -c code_secret1 localhost sysORTable SNMP table: SNMPv2-MIB::sysORTable sysORID sysORDescr sysORUpTime IF-MIB::ifMIB The MIB module to describe generic objects for network interface sub-layers 0:0:00:00.00 SNMPv2-MIB::snmpMIB The MIB module for SNMPv2 entities 0:0:00:00.00 TCP-MIB::tcpMIB The MIB module for managing TCP implementations 0:0:00:00.00 IP-MIB::ip The MIB module for managing IP and ICMP implementations 0:0:00:00.00 UDP-MIB::udpMIB The MIB module for managing UDP implementations 0:0:00:00.00 SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup View-based Access Control Model for SNMP. 0:0:00:00.00 SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance The SNMP Management Architecture MIB. 0:0:00:00.00 SNMP-MPD-MIB::snmpMPDCompliance The MIB for Message Processing and Dispatching. 0:0:00:00.00 SNMP-USER-BASED-SM-MIB::usmMIBCompliance The management information definitions for the SNMP User-based Security Model. 0:0:00:00.00 ==== snmpset ==== Fixer une valeur:\\ "The SET request is used to modify information on the target agent - updating the configuration of that agent, or controlling the behaviour of the remote system." [[http://www.net-snmp.org/wiki/index.php/TUT:snmpset|Suite]] ==== snmptrap ==== FIXME ====== tips ====== ===== snmp et commande externe ===== On va prendre exemple d'un monitoring de RAID ! ==== commande ==== On a composé un script de monitoring RAID trés simple: $ cat /root/prod/snmpd/raidmon #!/bin/sh # pour snmpd # Il n'accepte que la 1er ligne en reponse MDADM=/sbin/mdadm EGREP=/bin/egrep [ -x "$MDADM" ] || exit 0 COUNT=0 RAIDOK=0 CRITICAL=0 for RAIDDEV in /dev/md* do if [ -b "$RAIDDEV" ] then COUNT=$(( COUNT + 1 )) if [ -z "$( $MDADM --detail $RAIDDEV | $EGREP '^ *State *: *(clean|active) *$' )" ] then CRITICAL=$(( CRITICAL + 1 )) else RAIDOK=$(( RAIDOK + 1 )) fi fi done if [ "$CRITICAL" = "0" ] then echo "RAID OK ($RAIDOK/$COUNT)" else echo "RAID CRITICAL ($CRITICAL/$COUNT)" fi exit 0 ### vim: set shiftwidth=2 softtabstop=2 : ### En root, quand on fait : **''/root/prod/snmpd/raidmon''** on a : # /root/prod/snmpd/raidmon RAID OK (2/2) On attend qu'une simple ligne en retour, avec "OK" ou "CRITICAL" (c'est pour **''nagios''**, voir plus loin) Mais en simple **''user''** on aura: $ /root/prod/snmpd/raidmon mdadm: cannot open /dev/md0: Permission denied mdadm: cannot open /dev/md1: Permission denied RAID CRITICAL (2/2) Donc, il faudra l'executer en **"root"**, mais le daemon **''snmpd''** ne tourne (idéalement) qu'en simple user **''snmp''**. On peut changer en **''root''**, __mais on ne le fera pas__ ! On va utiliser [[brouillon_sudo|sudo]] ! Donc, aprés avoir configuré "sudo" pour autoriser le **''user''** **''snmp''**, on fera: $ sudo /root/prod/snmpd/raidmon RAID OK (2/2) Bien ! ==== snmpd.conf ==== Insérer la commande dans le fichier de conf (exemple): # TJ ---------- exec raidmon /usr/bin/sudo /root/prod/snmpd/raidmon # ------------- Puis on redemarre: # /etc/init.d/snmpd restart ==== snmpget RAID ==== $ snmpget -v 2c -c code_secret1 localhost .1.3.6.1.4.1.2021.8.1.101.1 UCD-SNMP-MIB::extOutput.1 = STRING: RAID OK (2/2) Ou encore: $ snmpget -v 2c -c code_secret1 localhost UCD-SNMP-MIB::extOutput.1 UCD-SNMP-MIB::extOutput.1 = STRING: RAID OK (2/2) Un peu plus d'info: $ snmpwalk -v 2c -On -c code_secret1 localhost .1.3.6.1.4.1.2021.8.1 .1.3.6.1.4.1.2021.8.1.1.1 = INTEGER: 1 .1.3.6.1.4.1.2021.8.1.2.1 = STRING: raidmon .1.3.6.1.4.1.2021.8.1.3.1 = STRING: /usr/bin/sudo /root/prod/snmpd/raidmon .1.3.6.1.4.1.2021.8.1.100.1 = INTEGER: 0 .1.3.6.1.4.1.2021.8.1.101.1 = STRING: RAID OK (2/2) .1.3.6.1.4.1.2021.8.1.102.1 = INTEGER: 0 .1.3.6.1.4.1.2021.8.1.103.1 = STRING: Si j'ai bien compris, chaque script ajouté dans la conf de "snmpd" ajouter "+1" a l'OID de l'objet, dans l'ordre de leur déclaration. Donc: .1.3.6.1.4.1.2021.8.1.1.1 .1.3.6.1.4.1.2021.8.1.1.2 .1.3.6.1.4.1.2021.8.1.1.3 etc... .1.3.6.1.4.1.2021.8.1.101.1 .1.3.6.1.4.1.2021.8.1.101.2 .1.3.6.1.4.1.2021.8.1.101.3 etc... etc... ==== snmp et autres ==== === disk === Documenté dans le fichier de conf, on ajouter: # TJ --------- disk / 10000000 # ------------ Pour voir la place dispo sur le disk (avec un minimum facultatif): $ snmpwalk -v 2c -c code_secret1 localhost .1.3.6.1.4.1.2021.9 UCD-SNMP-MIB::dskIndex.1 = INTEGER: 1 UCD-SNMP-MIB::dskPath.1 = STRING: / UCD-SNMP-MIB::dskDevice.1 = STRING: /dev/md0 UCD-SNMP-MIB::dskMinimum.1 = INTEGER: 10000000 UCD-SNMP-MIB::dskMinPercent.1 = INTEGER: -1 UCD-SNMP-MIB::dskTotal.1 = INTEGER: 74975192 UCD-SNMP-MIB::dskAvail.1 = INTEGER: 68444916 UCD-SNMP-MIB::dskUsed.1 = INTEGER: 2721672 UCD-SNMP-MIB::dskPercent.1 = INTEGER: 4 UCD-SNMP-MIB::dskPercentNode.1 = INTEGER: 1 UCD-SNMP-MIB::dskErrorFlag.1 = INTEGER: 0 UCD-SNMP-MIB::dskErrorMsg.1 = STRING: === charge cpu === $ snmpwalk -v 2c -c code_secret1 localhost .1.3.6.1.4.1.2021.10