Collecting crypto VPN traffic info from Cisco routers

Cisco crypto site to site VPNs are quite useful but it is difficult to collect traffic stats when there is no virtual interface for SNMP to track. Instead the stats are held in the Cisco SNMP mibs in various places and you have to cross-reference between those places to work out which SNMP entry refers to which VPN tunnel. This gets harder the more tunnels you have from your router.

With this in mind I’ve created a WhatsUp performance monitor script to collect the traffic receive (rx) and transmit (tx) stats through SNMP. You’ll need to grab the Cisco router mibs and install them into the WhatsUp mibs directory first before this script will work.

On the Cisco side you’ll be setting up a vpnmap entry such as this one:

crypto map mymap 141 ipsec-isakmp set peer x.x.x.x set transform-set xxxx match address myvpn-acl 

The crypto map number is useful as this is how the script finds the correct VPN tunnel in SNMP:

'The remote peer

The other variable to alter is whether the statistic to be collected is receive (rx) or transmit (tx) with respect to the router being polled. This is specified by this line:

' The direction of traffic (rx or tx)

How the script works

The script gets a list of all the ipsec tunnels (get_ipsecTunnel_list) which is held at SNMP OID It looks down the list for entries which relate to the vpnmap number, 141 in this case and compiles a list of entries. This list is then used to collect the receive or transmit statistics and add the values together for each ipsec tunnel associates with that isakmp tunnel (there can be many ipsec tunnels per isakmp tunnel depending on your match acl setup).

The script in full

'The remote peer

' The direction of traffic (rx or tx)

ipSecVPNMapIndex = ""
ipSecInOct              = ""
ipSecOutOct             = ""

set objSNMPReq = CreateObject("CoreAsp.SnmpRqst")
strDeviceID = Context.GetProperty("DeviceID")
set objSNMPInit = objSNMPReq.Initialize(strDeviceID)

if objSNMPInit.Failed then
    ' Get a list of indexes which match the VPN map number
    arrIpsecIndex = split(get_ipsecTunnel_list(ipSecVPNMapIndex,strVPNMapNumber),",")

    intFirstReading = get_TrafficSum()
    context.logmessage "FirstReading=" & intFirstReading 
    intSecondReading = get_TrafficSum()
    context.logmessage "SecondReading=" & intSecondReading 
    intTotalTrafficReading = intSecondReading - intFirstReading
    'value is in bytes
    Context.SetValue (intTotalTrafficReading * 8)/1000
    context.logmessage "Total=" & (intTotalTrafficReading * 8)/1000
end if

function get_TrafficSum()
    context.logmessage ubound(arrIpsecIndex)
    for each ipsecTunnelID in arrIpsecIndex
        context.logmessage "Processing Tunnel ID " & ipsecTunnelID
        if string_compare(strDirection,"rx") then
        end if
        inttmpResult=get_SNMPget(strtmpOID & "." & ipsecTunnelID)
        context.logmessage ipsecTunnelID & "=" & inttmpResult
        inttmpTotalTrafficReading = inttmpTotalTrafficReading + inttmpResult
    get_TrafficSum = inttmpTotalTrafficReading
end function

function get_ipsecTunnel_list (strOID,strtmpTargetValue)

    set objtmpSNMPResult = objSNMPReq.GetNext(strOID)

                context.logmessage "Looking for entry index OID for target " & strtmpTargetValue

    While boolExitWhile <> 1
        currSNMPPayload = objtmpSNMPResult.GetValue
        context.logmessage currSNMPIndex & "=" & currSNMPPayload 

        if currSNMPPayload = strtmpTargetValue then 
                                    context.logmessage currSNMPPayload & "=" & strtmpTargetValue
            if tmpReturnValue = "" then
                                                '    context.logmessage "ipsec index num is " & currIndexNum
                tmpReturnValue = tmpReturnValue & "," & currIndexNum
                                                '                   context.logmessage "ipsec index num is " & currIndexNum
            end if
            context.logmessage "index num is " & tmpReturnValue
        end if

        if string_compare(strOID,currSNMPIndex) then
            'context.logmessage "Setting next entry after " & currSNMPIndex
            set objtmpSNMPResult = objSNMPReq.GetNext(currSNMPIndex)
            'context.logmessage currSNMPIndex & " isn't in OID " & strOID
            'context.logmessage "Didn't find match for target " & strtmpTargetValue 
        end if
    context.logmessage "Got value=" &  tmpReturnValue
    get_ipsecTunnel_list = tmpReturnValue
end function

function get_SNMPget(strtmpOID)
    set objtmpSNMPResult = objSNMPReq.Get(strtmpOID)
    context.logmessage strtmpOID & " returned value " & strtmpValue
end function

private function string_compare(expression,targetstring)
    set oreg= new regexp
    oReg.IgnoreCase = TRUE
    if ("" = expression OR "" = targetstring) then
    end if
    if oReg.test (targetstring) then
    end if
end function

function sleep(intseconds)
    intstarttime = timer()
    while timer() < intstarttime+intseconds
end function

function get_indexFromOID(strtmpOID)

    context.logmessage "get_indexFromOID=" & strtmpValue

end function

Download the script (rename to zip)

Tagged , , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: