Cisco Support Community
cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

Cisco WLC SNMP Historical User Statistics Monitoring (w/ Syslog or Splunk)

Purpose:

This document aims to outline a way to extract client association data from a Cisco WLC so that it can be referenced later.  My organization has a business requirement to track all wireless users.  We use the techniques outlined in this document to take a "snap-shot" of our wireless clients associated with a Cisco WLC every 5 minutes and import that data into Splunk, where we can index and search through it any time we want.

This document will cover some basics needed to successfully extract connected client data from a Cisco WLC via SNMP.  Although this feat has probably been done before, I was able to find little documentation on how to extract this specific data and use it for historical purposes.  This document will provide MIB information to key OIDs of value, a bash scripting example, and lessons learned.

SNMP MIBs:

Cisco provides excellent SNMP MIB documentation.  For those who don't know what a MIB is, it stands for Management Information Base.  A MIB is like a road map for SNMP enabled systems.  The MIB allows you to identify and navigate to key data points that you wish to query.  Without a MIB for a corresponding piece of equipment, you will be making arbitrary requests for seemingly random data-points.

The easiest way to find what you are looking for is to use Cisco's SNMP Object Browser:  http://tools.cisco.com/Support/SNMP/do/BrowseOID.do

This tool allows you to step through an SNMP tree and locate the OID you are looking for, so you can query the data you want.  In this tutorial we will be using the SNMP tool suite for Linux and the snmpget and snmpwalk commands specifically.

The OIDS below will be what we focus on.

AP Names:

1.3.6.1.4.1.14179.2.2.1.1.3

Client MAC Address List:

1.3.6.1.4.1.14179.2.1.4.1.1

snmpwalk -v 2c -O x -c public 10.1.1.252 1.3.6.1.4.1.14179.2.1.4.1.1

Client IP Address List:

1.3.6.1.4.1.14179.2.1.4.1.2

snmpwalk -v 2c -c public 10.1.1.252 1.3.6.1.4.1.14179.2.1.4.1.2

Client Username List:

1.3.6.1.4.1.14179.2.1.4.1.3

snmpwalk -v 2c -c public 10.1.1.252 1.3.6.1.4.1.14179.2.1.4.1.3

AP MAC Address List:

1.3.6.1.4.1.14179.2.1.4.1.3

snmpwalk -v 2c -O x -c public 10.1.1.1.252 1.3.6.1.4.1.14179.2.1.4.1.4

Client SSID List:

1.3.6.1.4.1.14179.2.1.4.1.7

snmpwalk -v 2c -c public 10.1.1.252 1.3.6.1.4.1.14179.2.1.4.1.7


-=EXAMPLE OUTPUT=-

SNMPv2-SMI::enterprises.14179.2.1.4.1.1.252.199.52.222.11.140 = Hex-STRING: FC C7 34 DE 0B 8C

SNMPv2-SMI::enterprises.14179.2.1.4.1.2.252.199.52.222.11.140 = IpAddress: 10.1.11.21

SNMPv2-SMI::enterprises.14179.2.1.4.1.3.252.199.52.222.11.140 = STRING: "jdoe"

SNMPv2-SMI::enterprises.14179.2.1.4.1.4.252.199.52.222.11.140 = Hex-STRING: 84 78 AC B8 2F 90

Using the above OIDs and command examples we can collect the data we want.

By querying 1.3.6.1.4.1.14179.2.1.4.1.1 we get a complete list of client MAC addresses currently associated with the WLC.  You may have noticed in the example output, that the different pieces of information all contain the same unique sequence on the end of the query.  (Ex.

252.199.52.222.11.140)  This will allow us to query a specific user's attributes.  Now that we know the basics of SNMP and know where the data is, we can start scripting to put everything into a more readable format.

Script Example:

(Please excuse my scripting.  I'm no coder.  This is for practical application and demonstration purposes only.)

The script example below is a bash script that was designed to be cron'd on a Linux host.  The output of the script looks like this:

SYSTEM=CISCO MAC=E4:D5:3D:3B:81:4D IP=10.1.0.233 USER=DOMAIN\\jdoe17 AP=84:78:AC:B8:33:F0 SSID=Marketing

SYSTEM=CISCO MAC=E8:3E:B6:3B:CA:8D IP=10.1.240.243 USER=Unknown AP=84:78:AC:B8:8A:E0 SSID=Guest

SYSTEM=CISCO MAC=EC:85:2F:14:A9:BA IP=10.1.248.197 USER=Unknown AP=1C:E6:C7:1C:D8:90 SSID=Guest

SYSTEM=CISCO MAC=F0:1C:13:09:0E:B2 IP=10.1.252.151 USER=Unknown AP=54:78:1A:71:81:B0 SSID=Guest

SYSTEM=CISCO MAC=F0:4F:7C:B9:5F:B3 IP=10.1.0.221 USER=jdoe12 AP=54:78:1A:71:81:B0 SSID=Marketing

SYSTEM=CISCO MAC=F0:4F:7C:D6:0A:D9 IP=10.1.251.29 USER=Unknown AP=54:78:1A:70:EE:10 SSID=Guest

SYSTEM=CISCO MAC=F0:A2:25:A7:BD:F5 IP=10.1.251.85 USER=Unknown AP=84:78:AC:B8:8C:60 SSID=Guest

SYSTEM=CISCO MAC=F0:CB:A1:32:B3:D0 IP=10.1.136.163 USER=jdoe76 AP=84:78:AC:B8:8C:60 SSID=Admin-Wifi

SYSTEM=CISCO MAC=F0:CB:A1:C7:2E:6F IP=10.1.0.179 USER=jdoe1 AP=84:78:AC:B8:33:F0 SSID=Marketing

SYSTEM=CISCO MAC=F0:D1:A9:6E:05:2A IP=10.1.248.141 USER=Unknown AP=54:78:1A:71:D7:00 SSID=Guest

SYSTEM=CISCO MAC=F0:D1:A9:92:5C:7F IP=10.1.0.164 USER=jdoe23 AP=1C:E6:C7:1C:D3:E0 SSID=Marketing

SYSTEM=CISCO MAC=F0:DC:E2:02:4F:35 IP=10.1.248.104 USER=Unknown AP=54:78:1A:71:D7:00 SSID=Guest

SYSTEM=CISCO MAC=F0:DC:E2:BF:E1:A1 IP=10.1.0.240 USER=jadoe4 AP=84:78:AC:B8:33:F0 SSID=Marketing

SYSTEM=CISCO MAC=F4:6D:E2:E9:69:58 IP=10.1.252.180 USER=Unknown AP=54:78:1A:71:BF:B0 SSID=Guest

SYSTEM=CISCO MAC=F8:D0:BD:2F:BF:21 IP=10.1.0.128 USER=jdoe48 AP=1C:E6:C7:1C:D8:90 SSID=Marketing

SYSTEM=CISCO MAC=F8:DB:7F:9F:5A:22 IP=10.1.252.182 USER=Unknown AP=1C:E6:C7:1D:2F:60 SSID=Guest

SYSTEM=CISCO MAC=FC:C7:34:DE:0B:8C IP=10.1.0.44 USER=jdoe1 AP=84:78:AC:B8:2F:90 SSID=Marketing

(*NOTE:  This format is easily digested by Splunk or syslog)

Example Script:

#!/bin/bash

##########################

snmp_community="public"   

snmp_host="10.1.1.252"   

###########################

rm -f /tmp/cn-wlc.txt

####################################################################

#Set input system to break on new-line when adding data to an array#

####################################################################

IFS=$'\n'

############################################################################################

#Perform SNMP walks to get data of interest and load them into array variables to use later#

############################################################################################

while [ "1" -ne "2" ]

do

Unique_OID=($(snmpwalk -v 2c -O x -c $snmp_community $snmp_host 1.3.6.1.4.1.14179.2.1.4.1.1))

Client_IP=($(snmpwalk -v 2c -c $snmp_community $snmp_host 1.3.6.1.4.1.14179.2.1.4.1.2))

Client_Username=($(snmpwalk -v 2c -c $snmp_community $snmp_host 1.3.6.1.4.1.14179.2.1.4.1.3))

Client_AP=($(snmpwalk -v 2c -O x -c $snmp_community $snmp_host 1.3.6.1.4.1.14179.2.1.4.1.4))

Client_SSID=($(snmpwalk -v 2c -c $snmp_community $snmp_host 1.3.6.1.4.1.14179.2.1.4.1.7))

############################################################################################

#Ensure all SNMP walk requests contain the same amount of data and break loop when they do #

############################################################################################

 

count1=${#Unique_OID[@]}

count2=${#Client_IP[@]}

count3=${#Client_Username[@]}

count4=${#Client_AP[@]}

count5=${#Client_SSID[@]}

if [ "$count1" -eq "$count2" ]; then

                  if [ "$count2" -eq "$count3" ]; then

                        if [ "$count3" -eq "$count4" ]; then

                                       if [ "$count4" -eq "$count5" ]; then

                                                                  break

                                                          fi

                        fi

         fi

fi

done

####################################################################

#Create a loop to match and extract data between the various arrays#

####################################################################

wait

index=0

while [ "$index" -lt "$count1" ]

      do    

           id=$(echo ${Unique_OID[$index]} | cut -d "=" -f1 | awk -F "." '{print $8 "."$9 "." $10 "." $11 "." $12 "." $13 }')

           cMAC=$(echo ${Unique_OID[$index]} | grep $id | awk -F " " '{print $4 ":" $5 ":" $6 ":" $7 ":" $8 ":" $9 }')

           cIP=$(echo ${Client_IP[$index]} | grep $id | awk -F " " '{print $4}')

           cUser=$(echo ${Client_Username[$index]} | grep $id | awk -F " " '{print $4}' | sed s/\"//g)

           cAP=$(echo ${Client_AP[$index]} | grep $id | awk -F " " '{print $4 ":" $5 ":" $6 ":" $7 ":" $8 ":" $9 }')

           cSSID=$(echo ${Client_SSID[$index]} | grep $id | awk -F " " '{print $4}' | sed s/\"//g)

                  if [ "$cUser" = "\"\"" ]; then

                          cUser="Unknown"

                  fi

                  if [ "$cUser" = "" ]; then

                        cUser="Unknown"

                  fi

                  if [ "$cIP" = "0.0.0.0" ]; then

                        donothing="True"

                  else

                          # write our data out to a file so we can do something with it later

                          echo "SYSTEM=CISCO MAC="$cMAC "IP="$cIP "USER="$cUser "AP="$cAP "SSID="$cSSID >> /tmp/cn-wlc.txt

                          #echo "SYSTEM=CISCO MAC="$cMAC "IP="$cIP "User="$cUser "AP="$cAP "SSID="$cSSID

                  fi

           ((index++))

     done

Lessons Learned:

  1. MAC address entries need to be queried with the SNMP option -O x so that they only return results in HEX.  I had several cases where a client was improperly displaying it's MAC address in ASCII and it contained line breaks that was messing everything up.  I don't know why or how the controller let that happen, but it was the controller that saved the data into that SNMP value.  The solution was to ensure that SNMP get and walks only returned HEX values for those querys.
  2. By default SNMP query results have spaces and by default bash arrays interpret spaces on array input as field separators.  Modifying IFS will fix this for you, as noted in the script above.
  3. In order to have a working set of data, you need to ensure all SNMP queries contain the same number of results.  If they do not match, you are querying user data for users who may no-longer be associated.  To combat this, I threw the whole get sequence into a loop.  It runs fast enough to eventually get the data I need.  I am sure there are better ways, but this works fine for now.
  4. Sometimes users show up with a 0.0.0.0 IP.  I assumed these users are in a limbo state waiting to be fully associated or until their PEAP authentication passed.  In any case, they aren't realistically on my network so I didn't care and discarded the results for their connections.  I interpreted this data as the controller creating a placeholder for them until they are associated.

Summary:

With the data you can collect using Cisco's MIBs and SNMP there is no limit to what information your gear can show you.  My organization has used it with great success to meet business requirements.  Being able to historically see who was on your wireless network at any time will give you a huge advantage.  We can turn around DMCA notices, track users, identify usage peaks and wireless trends at various facilities, and to a certain degree, identify coverage issues.  We also have a similar script to collect this same data from Meru systems as well.  Although this guide may not be perfect and the scripting could be improved, I felt it necessary to share. 

Best of luck!

Comments
Community Member

Thank you very much.

I have used it with my WLC and worked like a charm.

Best regards,

Ricardo Canto

Community Member

Update:

 

I now have too many wireless clients for the above method to work.  The script would basically get caught in a loop waiting for all the right conditions to be met before it would dump data.  If you have a LOT of users the above method will not work because their associations will come and go and the 4 conditions the script waits for will never be met.

 

I've since switched to an SNMP trap method to get logs into Splunk.  The attached bash script will parse SNMP trap messages and dump them out to a cleaned file for splunk to index.  This only works with only client authentication trap messages enabled form the controller.  (only a single trap message type selected on the WLC)

 

This method works a lot better and you don't end up collecting a list of all of your clients currently on the system with every poll.  This method gathers client information in real-time, with a 5 minute lag, and won't clutter up your Splunk.

 

I've also included  a copy of my Splunk dashboard.  It's use will require a Cisco-WLC sourcetype to be configured and upon initial setup of the trap message indexing, you will be required to properly format the timestamps on the data.  (this can be tricky)  If you don't format the timestamps properly the event data will not look properly.

 

18367
Views
15
Helpful
2
Comments