Table of Contents
SNMP v3
snmp supervision
par franck, juillet 2007 maj par julien, décembre 2008
Présentation
On cherche à mettre en place des outils permettant de surveiller les serveurs linuxwall.info. Pour cela l'outil le plus classique est SNMP.
SNMP (Simple Network Management Protocol) est un protocole particulièrement adapté à la surveillance et la mesure de noeuds dans un réseau informatique. Il peut être également étendu à leur gestion dans une certaine mesure (c'est-à-dire agir sur ces noeuds). SNMP n'a pas bonne presse en terme de sécurité, mais il est toutefois possible d'arriver à un bon compromis en faisant attention à ce que l'on fait. On dispose pour cela dans la version 3 d'un cryptage et d'une authentification.
La version 3, telle qu'elle est définie dans la RFC 2570 et 2574, vise à pallier les déficiences de la version 2 afin d'utiliser SNMP de façon sécurisée de bout en bout.
À cette fin, elle permet de définir les autorisations et les contrôles d'accès. D'où la naissance du modèle USM (User-based Security Model) pour éviter la falsification des messages de commande en utilisant des mots de passe personnels scellés avec HMAC-MD5 ou HMAC-SHA, au choix. Mieux encore, lors de la transmission d'un message, USM modifie à chaque noeud la clé de chiffrement, ce qui évite, si un segment est endommagé, de menacer l'intégrité des informations reçues par le reste du réseau.
De plus, un cryptage des données est mise en place, en ayant recours cette fois à l'algorithme DES ou AES. La version 3 de SNMP abrite en outre un mécanisme de synchronisation entre les différents moteurs SNMP afin d'empêcher la duplication d'un message lors de son trajet en s'appuyant sur le temps parcouru depuis l'émetteur jusqu'au récepteur.
Les données décrites et transportées par ce protocole utilisent un nommage hiérarchique. Certaines branches sont normalisées et décrivent donc des mesures et des unités connues, d'autres branches sont maintenues par des entreprises pour leur besoins propre (CISCO, etc). L'ensemble du catalogue des informations gérables via SNMP s'appelle la MIB (Management Information Base). Techniquement, le nommage d'une information précise dans la hiérarchie d'une MIB se fait à l'aide d'une notation sous forme d'identifiants séparés par des points (un chemin hiérarchique), et qui commencent par un “1” (.1.3.6.1.6.3.1.1.5.3). On peut aussi récupérer des informations directement avec leurs noms (sysName.0).
Une fois que toutes les informations sont récupérées, on utilisera Cacti pour faire de beaux graphiques.
Installation / Configuration de SNMP v3
Ici, on va voir comment configurer la supervision d'une machine grace aux agents SNMP. Pour la doc, voir les pages de man de snmpd.conf et snmp.examples.
Les agents
Chaque machine que l'on souhaite monitorer est composée d'un agent et de traps. Les agents servent les informations aux clients qui les contactent et/ou envoient périodiquement ces informations au moyen de traps.
Pour monitorer notre machine, on a besoin du daemon “snmpd”. On ajoute également “snmp” pour pouvoir tester avec le client en local. (Pour utiliser le chiffrement, installer le packet “openssl”)
# apt-get install snmp snmpd
La configuration de l'agent est très simple. On remplace le fichier automatiquement créé par Debian (et particulièrement verbeux) par quelque chose de très basique.
On demande la création d'un seul utilisateur via la ligne “createUser”. Il faut lancer le serveur une fois avec cette ligne dans le fichier de configuration pour que l'utilisateur soit créé.
Attention, la passphrase pour AES doit être supérieure à 8 caractère, sinon snmpd plantera au lancement avec ces lignes dans syslog :
Oct 12 12:54:52 sachiel snmpd[4777]: Error: passphrase chosen is below the length requirements of the USM (min=8). Oct 12 12:54:52 sachiel snmpd[4777]: /etc/snmp/snmpd.conf: line 3: Error: could not generate the authentication key from the supplied pass phrase.
# vi /etc/snmpd/snmpd.conf rouser <utilisateur> priv createUser <utilisateur> SHA <supermotdepasse> AES <superpassphrase> syslocation Paris, France syscontact adresse@email.com
Explication :
- “rouser” définit un utilisateur ayant accès en lecture seule à toutes les MIB (sinon, on peut la préciser en rajouter “system” a la fin, par exemple). Le mode “priv” force l'utilisation du chiffrement
- “createUser” crée cet utilisateur avec un mot de passe scellé avec HMAC-SHA et une passphrase de chiffrement pour AES
- les lignes syslocations et syscontact sont purement facultatives
On peut ensuite enlever la ligne “createUser” et relancer le serveur avec le fichier snmpd.conf suivant :
# vi /etc/snmpd/snmpd.conf rouser <utilisateur> priv system syslocation Paris, France syscontact adresse@email.com
On ne stocke donc pas de mot de passe dans la config.
Après le restart, syslog affiche simplement les lignes :
Oct 12 12:57:14 miniarael snmpd[4800]: Received TERM or STOP signal... shutting down... Oct 12 12:57:16 miniarael snmpd[4813]: NET-SNMP version 5.4.1
et l'on a un socket UDP en écoute sur le port 161 :
# netstat -upan |grep snmp Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 127.0.0.1:161 0.0.0.0:* 4662/snmpd
Test de SNMP v3
SNMPwalk permet d'afficher le contenu de la MIB. Vous pouvez ensuite choisir une valeur particulière avec SNMPget.
$ snmpwalk -v 3 -u <utilisateur> -l authPriv -a SHA -A <supermotdepasse> -x AES -X <superpassphrase> 127.0.0.1
pour avoir l'uptime
$ snmpget -v 3 -u <utilisateur> -l authPriv -a SHA -A <supermotdepasse> -x AES -X <superpassphrase> 127.0.0.1 sysUpTime.0 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (107614) 0:17:56.14
ou la charge de eth0
$ snmpget -v 3 -u <utilisateur> -l authPriv -a SHA -A <supermotdepasse> -x AES -X <superpassphrase> 127.0.0.1 ifInOctets.2 IF-MIB::ifInOctets.2 = Counter32: 94056351
Si l'on prend la MIB des interfaces réseaux, par exemple, on a la liste des valeurs disponibles dans la RFC 2863 :
IfEntry ::= SEQUENCE { ifIndex InterfaceIndex, ifDescr DisplayString, ifType IANAifType, ifMtu Integer32, ifSpeed Gauge32, ifPhysAddress PhysAddress, ifAdminStatus INTEGER, ifOperStatus INTEGER, ifLastChange TimeTicks, ifInOctets Counter32, ifInUcastPkts Counter32, ifInNUcastPkts Counter32, -- deprecated ifInDiscards Counter32, ifInErrors Counter32, ifInUnknownProtos Counter32, ifOutOctets Counter32, ifOutUcastPkts Counter32, ifOutNUcastPkts Counter32, -- deprecated ifOutDiscards Counter32, ifOutErrors Counter32, ifOutQLen Gauge32, -- deprecated ifSpecific OBJECT IDENTIFIER -- deprecated }
Bon, tout cela marche en local, mais qu'en est il de l'exterieur ??
SNMPd écoute par défaut que les requêtes sur l'adresse IP 127.0.0.1:161 en UDP. Seule la machine sur laquelle SNMPd est installé peut donc faire des requêtes SNMP, comme le montre netstat :
# netstat -upan |grep snmp Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 127.0.0.1:161 0.0.0.0:* 4662/snmpd
Si on fait le test avec nmap depuis l'exterieur
sachiel:# nmap -sU -p 161 192.168.0.20 Interesting ports on 192.168.0.20: PORT STATE SERVICE 161/udp closed snmp
et depuis l'intérieur
sachiel:# nmap -sU -p 161 127.0.0.1 Interesting ports on wiki.linuxwall.info (127.0.0.1): PORT STATE SERVICE 161/udp open|filtered snmp
Il faut donc modifier la conf, et d'après la doc :
snmpd 127.0.0.1:161 127.0.0.1:6161 The AgentX port option ('-x') works in much the same way.
On adapte, en conséquence, nos paramètres de lancement du démon afin d'écouter sur la bonne interface (ici, 192.32.189.158) :
sachiel:# vi /etc/default/snmpd [...] SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -I -smux -p /var/run/snmpd.pid 192.32.189.158' [...]
Vérification :
# netstat -upan |grep snmp udp 0 0 192.32.189.158:161 0.0.0.0:* 4762/snmpd
Attention toutefois, en faisant cela 127.0.0.1 ne sera plus accessible. En local du serveur, il faudra donc lancer les commande directement sur l'adresse IP.
Vérifications, conclusion de la partie "configuration de SNMP"
Le chiffrement des communications en AES dans SNMPv3 est uniquement fait sur la valeur retournée par le protocole. Ce qui laisse l'ensemble des champs SNMP de la requête et de la réponse libres.
Afin de tester cela, on va utiliser deux comptes:
- test : un compte avec authentification HMAC-SHA et chiffrement AES
- youpi : un compte sans rien
De fait, snmpd.conf ressemble à cela :
rouser test priv system rouser youpi noauth system createUser test SHA testmotdepasse AES testpassphrase createUser youpi syslocation Paris, France syscontact adresse@email.com
On va lancer un tcpdump pour écouter les communications et visualiser tout cela dans Wireshark.
# tcpdump -w /home/julien/dumpsnmp.pcap -s 0 -XSvni lo udp and port 161 tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
note : si l'argument “-s 0” de tcpdump n'est pas positionné, ce dernier ne capture pas la totalité de chaque paquet mais seulement les 68 premiers octets, ce qui n'est pas suffisant pour SNMP
Puis, on lance deux requêtes, une par test avec la sécurité activée, l'autre par youpi à poil. Les deux font un GET sur la même valeur.
# snmpget -v 3 -u youpi -l noauthnopriv 192.32.189.158 ifInOctets.2 IF-MIB::ifInOctets.2 = Counter32: 97826353 # snmpget -v 3 -u test -l authPriv -a SHA -A testmotdepasse -x AES -X testpassphrase 192.32.189.158 ifInOctets.2 IF-MIB::ifInOctets.2 = Counter32: 97836087
Les résultats sont OK, on visualise le fichier obtenu avec Wireshark. Les paquets 1 à 4 sont la requête en clair, les paquets 5 à 8 la requête chiffrée.
1er screenshot : la réponse en clair
2eme screenshot : la réponse chiffrée
On voit bien les bits Encrypted et Authenticated qui sont valorisés à 1 pour la requête chiffrée alors qu'il sont à 0 pour la requête en clair.
On peut également vérifier le champ msgData de chaque paquet :
1. la réponse en clair
msgData: plaintext (0) plaintext contextEngineID: 80001F888056FFB63F2CB9F148 1... .... = Engine ID Conformance: RFC3411 (SNMPv3) Engine Enterprise ID: net-snmp (8072) Engine ID Format: Reserved/Enterprise-specific (128): Net-SNMP Random Engine ID Data: 56FFB63F Engine ID Data: Creation Time: Oct 12, 2008 10:45:32 contextName: <MISSING> data: get-response (2) get-response request-id: 1790278574 error-status: noError (0) error-index: 0 variable-bindings: 1 item IF-MIB::ifInOctets.2 (1.3.6.1.2.1.2.2.1.10.2): 97826353 Object Name: 1.3.6.1.2.1.2.2.1.10.2 (IF-MIB::ifInOctets.2) IF-MIB::ifEntry.ifIndex: 2 IF-MIB::ifInOctets: 97826353
2. la réponse chiffrée
msgData: encryptedPDU (1) encryptedPDU: 7551A8AFF145EDDEDD81ACD2632540F0F1FB98A117D7E7F9...
Ca c'est de la requête bien cryptée des familles !
A lire :
D'un point de vue “configurationnel”
D'un point de vue sécuritaire :
- http://www.thehackademy.net/article.php?story_id=102&topic_id=40 (récupération des données à l'insu de l'admin)
- http://www.01net.com/article/176594.html (failles dans SNMP v1)
~~DISCUSSION~~