Skip to main content

Command Palette

Search for a command to run...

Monitor your network interface with SNMP and Logstash

Published
10 min read
Monitor your network interface with SNMP and Logstash
Y

Product Manager at Synapticiel, IT & Telecoms Professional, Interested in ML, AI, IoT, BigData, Cyber Security, RA, FMS, Next Generation BSS/OSS, Mobile Money

What is SNMP ? (This part has been inspired from ManageEngine web site.

Simple Network Management Protocol (SNMP) is an application–layer protocol defined by the Internet Architecture Board (IAB) in RFC1157 for exchanging management information between network devices. It is a part of Transmission Control Protocol⁄Internet Protocol (TCP⁄IP) protocol suite.

SNMP is one of the widely accepted network protocols to manage and monitor network elements. Most of the professional–grade network elements come with bundled SNMP agent. These agents have to be enabled and configured to communicate with the network monitoring tools or network management system (NMS).

SNMP basic components and their functionalities

SNMP consists of :

  • SNMP Manager : A manager or management system is a separate entity that is responsible to communicate with the SNMP agent implemented network devices. This is typically a computer that is used to run one or more network management systems.

SNMP Manager’s key functions :

  1. Queries agents
  2. Gets responses from agents
  3. Sets variables in agents
  4. Acknowledges asynchronous events from agents

In our case, we will be using logstash, with the nice snmp input plugin, to pull data from the snmp agent on the managed device.

  • Managed Devices : A managed device or the network element is a part of the network that requires some form of monitoring and management e.g. routers, switches, servers, workstations, printers, UPSs, etc...

  • SNMP Agent : The agent is a program that is packaged within the network element. Enabling the agent allows it to collect the management information database from the device locally and makes it available to the SNMP manager, when it is queried for. These agents could be standard (e.g. Net-SNMP) or specific to a vendor (e.g. HP insight agent)

SNMP agent’s key functions :

  1. Collects management information about its local environment
  2. Stores and retrieves management information as defined in the MIB.
  3. Signals an event to the manager.
  4. Acts as a proxy for some non–SNMP manageable network node.

image.png

  • Management Information database or Management Information Base (MIB)

Every SNMP agent maintains an information database describing the managed device parameters. The SNMP manager uses this database to request the agent for specific information and further translates the information as needed for the Network Management System (NMS). This commonly shared database between the Agent and the Manager is called Management Information Base (MIB).

Typically these MIB contains standard set of statistical and control values defined for hardware nodes on a network. SNMP also allows the extension of these standard values with values specific to a particular agent through the use of private MIBs.

In short, MIB files are the set of questions that a SNMP Manager can ask the agent. Agent collects these data locally and stores it, as defined in the MIB. So, the SNMP Manager should be aware of these standard and private questions for every type of agent.

Using a simple logstash config like this, we can easily pull data from our device on a regular basis :

input {
  snmp {
    tables => [{
                    "name" => "interfaces" 
                    "columns" => ["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2", "1.3.6.1.2.1.2.2.1.10", "1.3.6.1.2.1.2.2.1.16"]
                }]
    hosts => [{
                host => "udp:127.0.0.1/161" 
                community => "public"  
                version => "2c"  
                retries => 2  
                timeout => 1000
              }
            ]
    interval => 5
  }
}

output {
    stdout {}
}

The result looks like this, an array of all interfaces on the devices with selected attributes from the agent MIB.

{
          "host" => "127.0.0.1",
    "interfaces" => [
        [0] {
             "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets" => 812249618,
            "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets" => 3093204737,
                                                                             "index" => "1",
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex" => 1,
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr" => "FastEthernet0/0"
        },
        [1] {
             "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets" => 2431688168,
            "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets" => 438889274,
                                                                             "index" => "2",
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex" => 2,
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr" => "FastEthernet1/0"
        },
        [2] {
             "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets" => 877744609,
            "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets" => 447410155,
                                                                             "index" => "3",
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex" => 3,
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr" => "FastEthernet2/0"
        },
        [3] {
             "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets" => 382207741,
            "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets" => 760358,
                                                                             "index" => "4",
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex" => 4,
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr" => "FastEthernet3/0"
        },
        [4] {
             "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets" => 2438113932,
            "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets" => 392582221,
                                                                             "index" => "5",
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex" => 5,
                "iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr" => "FastEthernet4/0"
        }
    ],
      "@version" => "1",
    "@timestamp" => 2020-12-17T14:12:34.594Z
}

That is, of course, fairly useless for analysis if we areusing the patterns we generally use with events from other sources. So ideally, we'd like to have something like this :

{
  "@timestamp": "2020-12-17T13:08:37.158Z",
  "host": "127.0.0.1",
  "ifIndex": 1,
  "ifDescr": "FastEthernet0/0",
  "ifInOctets": 316876067,
  "ifOutOctets": 150562
}

The mutate filter provide multiple possibilities to transform the data, one of them is the split function that will allow us to get multiple events from the array, means 1 event for each interface.

Following is a complete logstash configuration that allow to transform the data and send it back to elasticsearch for analysis

input {
  snmp {
    tables => [{
                    "name" => "interfaces" 
                    "columns" => ["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2", "1.3.6.1.2.1.2.2.1.10", "1.3.6.1.2.1.2.2.1.16"]
                }]
    hosts => [{
                host => "udp:127.0.0.1/161" 
                community => "public"  
                version => "2c"  
                retries => 2  
                timeout => 1000
              }
            ]
    interval => 5
  }
}

filter {

split {
   field => "interfaces"
 }

mutate { 
        rename => { "[interfaces][index]" => "index" }
        rename => { "[interfaces][iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex]" => "ifIndex" } 
        rename => { "[interfaces][iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifDescr]" => "ifDescr" } 
        rename => { "[interfaces][iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifInOctets]" => "ifInOctets" } 
        rename => { "[interfaces][iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOutOctets]" => "ifOutOctets" } 
    }

mutate {
        convert => {
          "ifInOctets" => "integer"
          "ifOutOctets" => "integer"
        }
    }

mutate {
        remove_field => [ "interfaces", "@version" ]
      }
}

output {        
   elasticsearch {
    hosts => ["https://localhost:9200"]
    user => "elastic"
    password => "changeme"
    cacert => "/opt/logstash_snmp/ca.crt"
    ssl => true
    index => "snmp-logs-%{+YYYY-MM-dd}"
    action => "index"
}
}

The following is an example of index template that can be used to host the date pulled by logstash

PUT _template/snmp-logs
{
  "index_patterns": [
    "snmp-logs-*"
  ],
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "host": {
        "type": "keyword"
      },
      "ifDescr": {
        "type": "keyword"
      },
      "ifInOctets": {
        "type": "long"
      },
      "ifIndex": {
        "type": "long"
      },
      "ifOutOctets": {
        "type": "long"
      },
      "index": {
        "type": "integer"
      }
    }
  }
}

Of course, the template will depend on the snmp table attributed selected For example if you want to get all interfaces on the devices with all attribute, we to pull data from the table OID : .1.3.6.1.2.1.2.2 and apply all the necessary renaming on logstash filter to get all required attributes

image.png

You can correlate all OIDs to an interface name below by snmp walking ifName: 1.3.6.1.2.1.31.1.1.1.1

High Speed interfaces

For high-speed interfaces (100Mbps or above) you should use 64-bit counters if the device supports them :

  • ifHCInOctets: 1.3.6.1.2.1.31.1.1.1.6 (64-bit Octets in counter)
  • ifHCOutOctets: 1.3.6.1.2.1.31.1.1.1.10 (64-bit Octets out counter)
  • ifHCInUcastPkts: 1.3.6.1.2.1.31.1.1.1.7 (64-bit Packets in counter)
  • ifHCOutUcastPkts: 1.3.6.1.2.1.31.1.1.1.11 (64-bit Packets out counter)
  • ifHighSpeed: 1.3.6.1.2.1.31.1.1.1.15 (An estimate of the interface's current bandwidth in units of 1Mbps)

Low Speed interfaces

Lower speed interfaces can get by with 32-bit counters. If you use 32-bit counters on high-speed interfaces, they can wrap quickly; a 10 Mbps stream of back-to-back, full-size packets causes ifInOctets to wrap in just over 57 minutes. At 100 Mbps, the minimum wrap time is 5.7 minutes, and at 1 Gbps, the minimum is 34 seconds Note 1

  • ifInOctets: 1.3.6.1.2.1.2.2.1.10 (32-bit Octets in counter)
  • ifOutOctets: 1.3.6.1.2.1.2.2.1.16 (32-bit Octets out counter)
  • ifInUcastPkts: 1.3.6.1.2.1.2.2.1.11 (32-bit Packets in counter)
  • ifOutUcastPkts: 1.3.6.1.2.1.2.2.1.17 (32-bit Packets out counter)
  • ifSpeed: 1.3.6.1.2.1.2.2.1.5 (Currently negotiated speed of the interface - Max: 4.294 Gbps)

Once done, and data is inside elasticsearch, you can laverage different analytics using lens in Kibana :

image.png

Y

Hello im using this ultra simple conf file:

input { snmp { hosts => [{host => "udp:192.168.24.1/161" community => "public" version => "2c" retries => 2 timeout => 1000}] tables => [ {"name" => "interfaces" "columns" => ["1.3.6.1.2.1.2.2.1.2.3", "1.3.6.1.2.1.2.2.1.4.3"]} ] interval => 5 } }

output { stdout {} }

i run it using pragma_admin@pragma:/usr/share/logstash/bin$ sudo ./logstash -f /etc/logstash/conf.d/snmp.conf

the resulting window prints:

Using bundled JDK: /usr/share/logstash/jdk OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs errors to the console [INFO ] 2022-03-24 13:03:43.763 [main] runner - Starting Logstash {"logstash.version"=>"8.1.1", "jruby.version"=>"jruby 9.2.20.1 (2.5.8) 2021-11-30 2a2962fbd1 OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +indy +jit [linux-x86_64]"} [INFO ] 2022-03-24 13:03:43.770 [main] runner - JVM bootstrap flags: [-Xms1g, -Xmx1g, -XX:+UseConcMarkSweepGC, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -Djruby.compile.invokedynamic=true, -Djruby.jit.threshold=0, -Djruby.regexp.interruptible=true, -XX:+HeapDumpOnOutOfMemoryError, -Djava.security.egd=file:/dev/urandom, -Dlog4j2.isThreadContextMapInheritable=true, --add-opens=java.base/java.security=ALL-UNNAMED, --add-opens=java.base/java.io=ALL-UNNAMED, --add-opens=java.base/java.nio.channels=ALL-UNNAMED, --add-opens=java.base/sun.nio.ch=ALL-UNNAMED, --add-opens=java.management/sun.management=ALL-UNNAMED] [WARN ] 2022-03-24 13:03:44.117 [LogStash::Runner] multilocal - Ignoring the 'pipelines.yml' file because modules or command line options are specified [INFO ] 2022-03-24 13:03:45.772 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600, :ssl_enabled=>false} [INFO ] 2022-03-24 13:03:46.462 [Converge PipelineAction::Create<main>] Reflections - Reflections took 137 ms to scan 1 urls, producing 120 keys and 417 values [INFO ] 2022-03-24 13:03:47.091 [Converge PipelineAction::Create<main>] javapipeline - Pipeline main is configured with pipeline.ecs_compatibility: v8 setting. All plugins in this pipeline will default to ecs_compatibility => v8 unless explicitly configured otherwise. [INFO ] 2022-03-24 13:03:47.209 [[main]-pipeline-manager] javapipeline - Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>4, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>500, "pipeline.sources"=>["/etc/logstash/conf.d/snmp.conf"], :thread=>"#<Thread:0x7bd39b12 run>"} [INFO ] 2022-03-24 13:03:47.893 [[main]-pipeline-manager] javapipeline - Pipeline Java execution initialization time {"seconds"=>0.68} [INFO ] 2022-03-24 13:03:47.933 [[main]-pipeline-manager] snmp - using plugin provided MIB path /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-input-snmp-1.3.1/lib/mibs/logstash [INFO ] 2022-03-24 13:03:47.952 [[main]-pipeline-manager] snmp - using plugin provided MIB path /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-input-snmp-1.3.1/lib/mibs/ietf [INFO ] 2022-03-24 13:03:50.635 [[main]-pipeline-manager] snmp - ECS compatibility is enabled but target option was not specified. This may cause fields to be set at the top-level of the event where they are likely to clash with the Elastic Common Schema. It is recommended to set the target option to avoid potential schema conflicts (if your data is ECS compliant or non-conflicting, feel free to ignore this message) [INFO ] 2022-03-24 13:03:50.640 [[main]-pipeline-manager] javapipeline - Pipeline started {"pipeline.id"=>"main"} [INFO ] 2022-03-24 13:03:50.694 [Agent thread] agent - Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}

AND nothing else im running ubuntu 20.04.4 install logstash .deb via apt install

the host IS accessible and responds in a fraction of a second here is a snmwalk testing one of the oid

pragma_admin@pragma:/usr/share/logstash/bin$ sudo snmpwalk -v2c -cpublic 192.168.24.1 1.3.6.1.2.1.2.2.1.2.3 iso.3.6.1.2.1.2.2.1.2.3 = STRING: "ether1 Hacia Internet"

please help

2
Y

Can you try a walk on the logstash config ?

input { snmp { hosts => [ { host => "udp:192.168.24.1/161" community => "public" version => "2c" retries => 2 timeout => 1000 } ] walk => ["1.3.6.1.2.1.2.2.1.2.3"] interval => 5 } }

Y

Yassine LASRI

Walk didnt work either but the get option worked like a charm.

1
Y

Yassine LASRI

SOLVED for some reason tables and walk options dont work with OIDs that are formed by eleven elements that is oids that are not walkable. 1.3.6.1.2.1.2.2.1.2.3 will not work but 1.3.6.1.2.1.2.2.1.2 will work

1
Y

Ygal Mizrachi i was a victim of my own ignorance

1
Y

Ygal Mizrachi Happy that you are able to get your pipeline working feel free to connect if i can help

More from this blog

My Tech Memories

10 posts

Welcome to my Hashnode blog where i post some of my finding in tech world, mostly interested by topics related to data analytics, observability and cyber security. I like share my experience on ELK