Hack81.Remotely Monitor and Configure a Variety of Networked Equipment


Hack 81. Remotely Monitor and Configure a Variety of Networked Equipment

Using SNMP, you can collect information about almost any device attached to your network.

For everything that has a network interface, chances are there's some form of Simple Network Management Protocol (SNMP) daemon that can run on it. Over the years, SNMP daemons have been added to everything from environmental sensors to UPSs to soda vending machines. The point of all of this is to be able to remotely access as much information about the host as humanly possible. As an added bonus, proper configuration can allow administrators to change values on the host remotely as well.

SNMP daemon packages are available for all of the widely used distributions, along with possibly separate packages containing a suite of SNMP command-line tools. You might have come across the snmpwalk or snmpget commands before in your travels, or you might've seen similarly named functions in scripting languages such as Perl and PHP.

Let's have a look at a small bit of a "walk" on an SNMP-enabled Linux host and use it to explain how this works:

 $ snmpwalk -v2c -c public livid interfaces    IF-MIB::ifNumber.0 = INTEGER: 4    IF-MIB::ifIndex.1 = INTEGER: 1    IF-MIB::ifIndex.2 = INTEGER: 2    IF-MIB::ifIndex.3 = INTEGER: 3    IF-MIB::ifIndex.4 = INTEGER: 4    IF-MIB::ifDescr.1 = STRING: lo    IF-MIB::ifDescr.2 = STRING: eth0    IF-MIB::ifDescr.3 = STRING: eth1    IF-MIB::ifDescr.4 = STRING: sit0    IF-MIB::ifType.1 = INTEGER: softwareLoopback(24)    IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6)    IF-MIB::ifType.3 = INTEGER: ethernetCsmacd(6)    IF-MIB::ifType.4 = INTEGER: tunnel(131)    IF-MIB::ifPhysAddress.1 = STRING:    IF-MIB::ifPhysAddress.2 = STRING: 0:a0:cc:e7:24:a0    IF-MIB::ifPhysAddress.3 = STRING: 0:c:f1:d6:3f:32    IF-MIB::ifPhysAddress.4 = STRING: 0:0:0:0:3f:32    IF-MIB::ifAdminStatus.1 = INTEGER: up(1)    IF-MIB::ifAdminStatus.2 = INTEGER: up(1)    IF-MIB::ifAdminStatus.3 = INTEGER: down(2)    IF-MIB::ifAdminStatus.4 = INTEGER: down(2)    IF-MIB::ifOperStatus.1 = INTEGER: up(1)    IF-MIB::ifOperStatus.2 = INTEGER: up(1)    IF-MIB::ifOperStatus.3 = INTEGER: down(2)    IF-MIB::ifOperStatus.4 = INTEGER: down(2) 

As you can see, there's a good bit of information here, and I've cut out the bits that aren't important right now. Furthermore, this is only one part of one SNMP "tree" (the "interfaces" tree). Under that tree lie settings and status information for each interface on the system. If you peruse the list, you'll see separate values for each interface corresponding to things like the interface description (the name the host calls the interface), the physical address, and the interface type.

But what is this "tree" I'm speaking of? SNMP data is actually organized much like LDAP data, or DNS data, or even your Linux system's file hierarchythey're all trees! Our output above has hidden some of the detail from us, however. To see the actual path in the tree for each value returned, we'll add an option to our earlier command:

 $ snmpwalk -Of -v2c -c public livid interfaces .iso.org.dod.internet.mgmt.mib-2.interfaces.ifNumber.0 = INTEGER: 4 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.1 = INTEGER: 1 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.2 = INTEGER: 2 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.3 = INTEGER: 3 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.4 = INTEGER: 4 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr.1 = STRING: lo .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr.2 = STRING: eth0 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr.3 = STRING: eth1 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr.4 = STRING: sit0 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifType.1 = INTEGER: softwareLoopback(24) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifType.2 = INTEGER: ethernetCsmacd(6) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifType.3 = INTEGER: ethernetCsmacd(6) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifType.4 = INTEGER: tunnel(131) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifPhysAddress.1 = STRING: .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifPhysAddress.2 = STRING: 0:a0:cc:e7:24:a0 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifPhysAddress.3 = STRING: 0:c:f1:d6:3f:32 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifPhysAddress.4 = STRING: 0:0:0:0:3f:32 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.1 = INTEGER: up(1) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.2 = INTEGER: up(1) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.3 = INTEGER: down(2) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.4 = INTEGER: down(2) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.1 = INTEGER: up(1) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.2 = INTEGER: up(1) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.3 = INTEGER: down(2) .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.4 = INTEGER: down(2) 

Now we can clearly see that the "interfaces" tree sits underneath all of those other trees. If you replaced the dot separators with a forward slashes, it would look very much like a directory hierarchy, with the value after the last dot being the filename and everything after the equals sign being the content of the file. Now this should start to look a little more familiarmore like the output of a find command than something completely foreign (I hope).

A great way to get acquainted with an SNMP-enabled (or "managed") device is to simply walk the entire tree for that device. You can do this by pointing the snmpwalk command at the device without specifying a tree, as we've done so far. Be sure to redirect the output to a file, though, because there's far too much data to digest in one sitting! To do this, use a command like the following:

 $ snmpwalk -Ov -v2c -c public livid > livid.walk 

You can run the same command against switches, routers, firewalls, and even some specialized devices such as door and window contact sensors and environmental sensors that measure the heat and humidity in your machine room.

9.5.1. The Code

Even just sticking to Linux boxes offers a wealth of information. I've written a script in PHP, runnable from a command line, that gathers basic information and reports on listening TCP ports, using only SNMP. Here's the script:

 #!/usr/bin/php <?php snmp_set_quick_print(1); $string = "public"; $host = "livid"; check_snmp($host); spitinfo($host); function check_snmp($box)//see if this box is running snmp before we throw  //requests at it. { $string="public"; $infocheck = @snmpget("$box", "$string", "system.sysDescr.0"); if(! $infocheck) { die("SNMP doesn't appear to be running on $box"); } else { return $infocheck; } } function spitinfo($host)//retrieves and displays snmp data. {    $string = "public";    $hostinfo = @snmpget("$host","$string","system.sysDescr.0");    list ($k)=array(split(" ", $hostinfo));    $os = $k[0];    $hostname = @snmpget("$host","$string","system.sysName.0");    $user = @snmpget("$host","$string","system.sysContact.0");    $location = @snmpget("$host","$string","system.sysLocation.0");    $macaddr = @snmpget   ("$host","$string","interfaces.ifTable.ifEntry. ifPhysAddress.2");    $ethstatus =    @snmpget("$host","$string","interfaces.ifTable.ifEntry.  ifOperStatus.2");    $ipfwd = @snmpget("$host","$string","ip.ipForwarding.0");    $ipaddr = @gethostbyname("$host");    $info=array("Hostname:"=>"$hostname","Contact:"=>"$user", "Location:"=>"$location","OS:"=>"$os","MAC Address:"=> "$macaddr","IP Address:"=>"$ipaddr","Network Status"=> "$ethstatus", "Forwarding:"=>"$ipfwd");    print "$host\n";    tabdata($info);    print "\nTCP Port Summary\n";    snmp_portscan($hostname); } function tabdata($data) { foreach($data as $label=>$value) { if($label){ print "$label\t"; }else{ print "Not Available"; } if($value){ print "$value\n"; }else{ print "Not Available"; } } } function snmp_portscan($target) { $listen_ports = snmpwalk("$target", "public", ".1.3.6.1.2.1.6.13.1.3. 0.0.0.0"); foreach($listen_ports as $key=>$value) { print "TCP Port $value (" . getservbyport($value, 'tcp') . ") listening \n"; } } ?> 

9.5.2. Running the Code

Save this script to a file named report.php, and make it executable (chmod 775 report.php). Once that's done, run it by issuing the command ./report.php.

I've hard-coded a value for the target host in this script to shorten things up a bit, but you'd more likely want to feed a host to the script as a command-line argument, or have it read a file containing a list of hosts to prod for data. You'll also probably want to scan for the number of interfaces, and do other cool stuff that I've left out here to save space. Here's the output when run against my Debian test system:

 Hostname: livid Contact: jonesy(jonesy@linuxlaboratory.org Location: Upstairs office OS: Linux MAC Address: 0:a0:cc:e7:24:a0 IP Address: 192.168.42.44 Network Status up Forwarding: notForwarding TCP Port Summary TCP Port 80 (http) listening TCP Port 111 (sunrpc) listening TCP Port 199 (smux) listening TCP Port 631 (ipp) listening TCP Port 649 ( ) listening TCP Port 2049 (nfs) listening TCP Port 8000 ( ) listening TCP Port 32768 ( ) listening 

You'll notice in the script that I've used numeric values to search for in SNMP. This is because, as in many other technologies, the human-readable text is actually mapped from numbers, which are what the machines use under the covers. Each record returned in an snmpwalk has a numeric object identifier, or OID. The client uses the Management Information Base (MIB) files that come with the Net-SNMP distribution to map the numeric OIDs to names. In a script, however, speed will be of the essence, so you'll want to skip that mapping operation and just get at the data.

You'll also notice that I've used SNMP to do what is normally done with a port scanner, or with a bunch of calls to some function like (in PHP) fsockopen. I could've used function calls here, but it would have been quite slow because we'd be knocking on every port in a range and awaiting a response to see which ones are open. Using SNMP, we're just requesting the host's list of which ports are open. No guessing, no knocking, and much, much faster.



Linux Server Hacks (Vol. 2)
BSD Sockets Programming from a Multi-Language Perspective (Programming Series)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 162
Authors: M. Tim Jones

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net