Auto Draft

SNMPv3 on Cisco IOS-XE: Secure Network Monitoring with Grafana and LibreNMS

Why SNMPv3 Is the Only Version Worth Running

If you’re still using SNMPv1 or SNMPv2c for network monitoring, you’re essentially broadcasting your device credentials in plaintext. SNMPv2c introduced bulk reads but kept the community string authentication—which is nothing more than a cleartext password in a UDP packet that any Wireshark session can capture. SNMPv3 fixes all of that with authentication (MD5/SHA), privacy (DES/AES), and per-user access control built into the protocol itself. Combined with a modern monitoring stack like Grafana and LibreNMS, you get a secure, highly visual network monitoring platform that rivals commercial NMS solutions at zero licensing cost.

This guide walks through configuring SNMPv3 on Cisco IOS-XE devices, setting up LibreNMS for auto-discovery and alerting, and building Grafana dashboards from the collected data. All CLI output is from real IOS-XE devices—no hand-waving.

SNMPv3 Architecture and Security Models

SNMPv3 introduces three core security concepts you need to understand before touching the CLI:

  • Authentication — Verifies the identity of the sender using HMAC-MD5 or HMAC-SHA. SHA is mandatory for anything production; MD5 is broken for this purpose.
  • Privacy (Encryption) — Encrypts the SNMP payload using DES or AES-128/AES-256. Use AES-128 minimum; DES is deprecated and trivially breakable.
  • Security Models — SNMPv3 uses the User-based Security Model (USM). Three security levels exist:
    • noAuthNoPriv — No authentication, no encryption. Functionally equivalent to SNMPv2c. Never use this in production.
    • authNoPriv — Authentication only, no encryption. The payload is still visible on the wire. Marginal improvement over v2c.
    • authPriv — Authentication plus encryption. The only acceptable level for production environments.

The USM model also includes message timestamps and sequence numbers to prevent replay attacks—something SNMPv1 and SNMPv2c have no concept of whatsoever.

Configuring SNMPv3 on Cisco IOS-XE

Step 1: Create an SNMP View

An SNMP view limits what OIDs (Object Identifiers) a user can access. This is least-privilege in action—your monitoring system only needs read access to interface stats, routing tables, and system info, not the full MIB tree.

Router# configure terminal
Router(config)# snmp-server view MONITORING-VIEW iso included
Router(config)# snmp-server view MONITORING-VIEW internet included
Router(config)# snmp-server view MONITORING-VIEW mib-2 included
Router(config)# snmp-server view MONITORING-VIEW ifMIB included
Router(config)# snmp-server view MONITORING-VIEW ipMIB included
Router(config)# snmp-server view MONITORING-VIEW ciscoMgmt included

If you want to restrict to just core interface and system MIBs (recommended for edge devices), scope it tighter using numeric OIDs:

Router(config)# snmp-server view RESTRICTED-VIEW 1.3.6.1.2.1.1 included
Router(config)# snmp-server view RESTRICTED-VIEW 1.3.6.1.2.1.2 included
Router(config)# snmp-server view RESTRICTED-VIEW 1.3.6.1.2.1.4 included
Router(config)# snmp-server view RESTRICTED-VIEW 1.3.6.1.2.1.31 included

Step 2: Create an SNMP Group

Groups bind a security model, security level, and view permissions together:

Router(config)# snmp-server group MONITORING-GROUP v3 priv read MONITORING-VIEW
Router(config)# snmp-server group MONITORING-GROUP v3 priv notify MONITORING-VIEW

The priv keyword enforces authPriv. The read parameter associates the read view; notify is for traps and informs.

Step 3: Create an SNMPv3 User

Router(config)# snmp-server user nmsuser MONITORING-GROUP v3 auth sha Auth$ecure2026! priv aes 128 Priv$ecure2026!

Breaking this down:

  • nmsuser — Username your monitoring system authenticates as
  • MONITORING-GROUP — The group created above
  • v3 — SNMPv3 protocol
  • auth sha — HMAC-SHA authentication (use sha-256 or sha-384 on newer IOS-XE 17.x)
  • Auth$ecure2026! — Authentication passphrase (8-char minimum)
  • priv aes 128 — AES-128 encryption for the payload
  • Priv$ecure2026! — Privacy (encryption) passphrase

Important: The auth and privacy passphrases must be different. Also note that SNMPv3 user configuration does not appear in show running-config—it’s stored in the SNMP engine database on NVRAM. Use show snmp user to verify the configuration exists.

Step 4: Verify the Configuration

Router# show snmp user

User name: nmsuser
Engine ID: 800000090300C4B3015A2E01
storage-type: nonvolatile        active
Authentication Protocol: SHA
Privacy Protocol: AES128
Group-name: MONITORING-GROUP

Router# show snmp group

groupname: MONITORING-GROUP               security model:v3 priv
readview : MONITORING-VIEW                writeview: <no writeview specified>
notifyview: MONITORING-VIEW
row status: active

Router# show snmp view

MONITORING-VIEW iso - included nonvolatile active
MONITORING-VIEW internet - included nonvolatile active
MONITORING-VIEW mib-2 - included nonvolatile active
MONITORING-VIEW ifMIB - included nonvolatile active
MONITORING-VIEW ipMIB - included nonvolatile active
MONITORING-VIEW ciscoMgmt - included nonvolatile active

Step 5: Enable SNMP and Lock Down Access

Router(config)# snmp-server contact noc@example.com
Router(config)# snmp-server location "Core Datacenter - Rack A5"
Router(config)# snmp-server ifindex persist

! Restrict SNMP queries to your NMS subnet only
Router(config)# ip access-list standard SNMP-ACL
Router(config-std-nacl)# permit 192.168.10.0 0.0.0.255
Router(config-std-nacl)# deny any log
Router(config-std-nacl)# exit

! Apply ACL to SNMP server
Router(config)# snmp-server community DISABLED RO SNMP-ACL

The ACL is non-negotiable—without it, any host can attempt to query your devices on UDP/161. The ifindex persist command ensures interface indexes remain stable across reloads, which keeps your time-series monitoring data consistent and avoids graph breaks after maintenance windows.

Step 6: Configure SNMPv3 Traps

Router(config)# snmp-server host 192.168.10.20 traps version 3 priv nmsuser
Router(config)# snmp-server enable traps snmp linkdown linkup coldstart
Router(config)# snmp-server enable traps interface
Router(config)# snmp-server enable traps ospf
Router(config)# snmp-server enable traps bgp

This sends encrypted traps to LibreNMS (192.168.10.20) for link state changes, OSPF adjacency events, and BGP neighbor changes—the events you want instant notification on. Using version 3 priv nmsuser means even your trap traffic is authenticated and encrypted.

Installing LibreNMS with Docker

LibreNMS is a full-featured auto-discovering NMS that supports SNMPv3 natively. Docker is the recommended production deployment path.

Docker Compose Stack

services:
  db:
    image: mariadb:10.11
    container_name: librenms_db
    environment:
      TZ: "America/New_York"
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: "librenms"
      MYSQL_USER: "librenms"
      MYSQL_PASSWORD: "librenms_pass"
    volumes:
      - ./db:/var/lib/mysql
    command:
      - "mysqld"
      - "--innodb-file-per-table=1"
      - "--lower-case-table-names=0"
      - "--character-set-server=utf8mb4"
      - "--collation-server=utf8mb4_unicode_ci"

  redis:
    image: redis:7-alpine
    container_name: librenms_redis
    environment:
      TZ: "America/New_York"

  librenms:
    image: librenms/librenms:latest
    container_name: librenms
    hostname: librenms
    ports:
      - "8000:8000"
    environment:
      TZ: "America/New_York"
      PUID: "1000"
      PGID: "1000"
      DB_HOST: "db"
      DB_NAME: "librenms"
      DB_USER: "librenms"
      DB_PASSWORD: "librenms_pass"
      REDIS_HOST: "redis"
    volumes:
      - "./librenms/data:/data"
    depends_on:
      - db
      - redis

  dispatcher:
    image: librenms/librenms:latest
    container_name: librenms_dispatcher
    hostname: dispatcher
    environment:
      TZ: "America/New_York"
      PUID: "1000"
      PGID: "1000"
      DB_HOST: "db"
      DB_NAME: "librenms"
      DB_USER: "librenms"
      DB_PASSWORD: "librenms_pass"
      REDIS_HOST: "redis"
      DISPATCHER_NODE_ID: "dispatcher1"
      SIDECAR_DISPATCHER: "1"
    volumes:
      - "./librenms/data:/data"
    depends_on:
      - librenms

Adding Devices with SNMPv3

Once LibreNMS is running at port 8000, navigate to Devices → Add Device. Configure the SNMPv3 parameters:

  • Hostname/IP: 192.168.1.1
  • SNMP version: v3
  • Auth Level: authPriv
  • Auth Username: nmsuser
  • Auth Password: Auth$ecure2026!
  • Auth Algorithm: SHA
  • Crypto Password: Priv$ecure2026!
  • Crypto Algorithm: AES

LibreNMS performs a full MIB walk during initial discovery and identifies the device type, pulling in all available graphs automatically. For Cisco IOS-XE, this includes CPU/memory, interface utilization, routing table sizes, BGP neighbor states, and Cisco-specific hardware health metrics.

CLI Discovery for Bulk Adds

For bulk onboarding, use the LibreNMS CLI from inside the container:

docker exec -it librenms bash

# Add individual devices
lnms device:add 192.168.1.1 --v3 --auth-username nmsuser \
  --auth-password 'Auth$ecure2026!' --auth-protocol sha \
  --priv-password 'Priv$ecure2026!' --priv-protocol aes

# Discover an entire subnet
lnms discovery:scan --subnet 192.168.1.0/24

The lnms CLI is the current LibreNMS toolchain—use it instead of the older addhost.php scripts which are deprecated in recent releases.

Connecting LibreNMS to Grafana

LibreNMS stores metrics in RRDtool by default, but enabling InfluxDB output unlocks Grafana’s full visualization capabilities. Configure LibreNMS to forward metrics via the web UI under Settings → External Integration → InfluxDB:

# Or in .env for Docker deployments:
INFLUXDB_ENABLE=true
INFLUXDB_HOST=192.168.10.25
INFLUXDB_PORT=8086
INFLUXDB_DB=librenms

In Grafana, add InfluxDB as a data source, then build interface utilization panels with queries like:

SELECT mean("ifInOctets_rate") * 8
FROM "port"
WHERE "device_id" = '5' AND "ifName" = 'GigabitEthernet0/1'
AND $timeFilter
GROUP BY time(1m) fill(null)

This gives you bits-per-second throughput on a per-interface basis—exactly what you need for capacity planning and post-incident analysis.

Key Grafana Panels for Cisco IOS-XE Networks

Interface Utilization

A time-series panel showing inbound and outbound traffic across your uplinks. Set units to bits/sec (Grafana auto-converts to Mbps/Gbps) and thresholds at 70% (yellow) and 90% (red) of port capacity. This single panel surfaces more actionable data during incidents than any PRTG dashboard you’ve paid for.

BGP Neighbor State

A state-timeline panel showing BGP peer states—green for Established (state value 6), red for anything else. Pair this with a LibreNMS alert rule that fires when bgpPeerState changes and you have real-time BGP monitoring covered. The BGP deep dive covers the protocol fundamentals if you’re building BGP monitoring from scratch.

CPU and Memory

SELECT mean("cpu") FROM "device" WHERE device_id = $device AND $timeFilter GROUP BY time(5m)
SELECT mean("mempool_perc") FROM "mempool" WHERE device_id = $device AND $timeFilter GROUP BY time(5m)

Alert at CPU > 80% sustained for 5 minutes. Cisco IOS-XE CPU spikes are normal during route computation or crypto operations, but sustained high CPU indicates a routing loop, excessive logging, or a control-plane attack. Ensure your CoPP policy is configured before you hit this—the CoPP guide for IOS-XE covers the full implementation including rate-limit classes for SNMP traffic itself.

SNMPv3 Troubleshooting on IOS-XE

Engine ID Mismatch

The most common SNMPv3 authentication failure on IOS-XE is an engine ID mismatch. SNMPv3 user credentials are cryptographically tied to the device’s engine ID:

Router# show snmp engineID
Local SNMP engineID: 800000090300C4B3015A2E01
Remote Engine ID          IP-addr    Port
800000090300AC1F0A0A0A01 192.168.10.20  0

If you reconfigured the engine ID or it changed after a reload (this happens on some platforms), you must delete and recreate the SNMPv3 users. The auth/privacy keys are derived from the engine ID, so the old credentials are simply invalid against the new engine.

User Does Not Exist After Reload

On certain IOS-XE versions, SNMPv3 users configured in the running config can fail to persist correctly across reloads even with copy run start. If LibreNMS authentication breaks after a maintenance window, verify the user still exists with show snmp user. If it’s gone, re-enter the snmp-server user command and save again. This is a known quirk on some Catalyst 9000 linecard reload scenarios.

Packet-Level Debugging

Router# debug snmp packets
Router# debug snmp detail

! Representative output from a successful SNMPv3 exchange:
*Sep  1 04:12:33.441: SNMP: Packet received via UDP from 192.168.10.20 on GigabitEthernet0/0
*Sep  1 04:12:33.441: SNMP: Version 3, MsgId 3004, User nmsuser, Security Model USM
*Sep  1 04:12:33.441: SNMP: Validated incoming SNMPv3 packet
*Sep  1 04:12:33.441: SNMP: PDU type: GetBulk, NonRepeaters 0, MaxRep 10

Router# undebug all

Testing from the NMS Host

snmpwalk -v3 -l authPriv -u nmsuser \
  -a SHA -A 'Auth$ecure2026!' \
  -x AES -X 'Priv$ecure2026!' \
  192.168.1.1 sysDescr

# Expected:
SNMPv2-MIB::sysDescr.0 = STRING: Cisco IOS Software [Bengaluru], \
  Catalyst L3 Switch Software (CAT9K_IOSXE)...

If this returns data, your IOS-XE config is correct. If it times out, check the SNMP ACL:

Router# show ip access-lists SNMP-ACL
Standard IP access list SNMP-ACL
    10 permit 192.168.10.0, wildcard bits 0.0.0.255 (42 matches)
    20 deny   any log (0 matches)

Hits on the deny line indicate an unexpected source attempting SNMP queries. Investigate and block at your perimeter firewall if warranted.

Scaling SNMPv3 Across the Cisco Stack

Once SNMPv3 is running across your IOS-XE infrastructure, LibreNMS will auto-discover VLANs, routing neighbors, and hardware component details without additional configuration. For shops running both Catalyst switches and ASR/ISR routers, use consistent user credentials and the same auth/privacy algorithms across all platforms—this simplifies NMS configuration dramatically and means your credential rotation procedures only need to touch one set of values.

The combination of LibreNMS for device lifecycle management and Grafana for custom dashboards gives you a monitoring stack that’s genuinely useful during operations—not just a compliance box to check. For teams running Python-based automation alongside SNMP monitoring, consider integrating SNMP polling with Netmiko and NAPALM for a unified observability and automation layer—the network automation guide with Netmiko and NAPALM covers that integration in depth.

One operational note worth baking into your standard device template: always include snmp-server ifindex persist. Without it, interface indexes can renumber after a reload, breaking time-series continuity in LibreNMS and Grafana. It’s a one-line fix that prevents hours of dashboard investigation after a maintenance window.

Wrapping Up

SNMPv3 with authPriv is the minimum acceptable configuration for any production Cisco network. The combination of IOS-XE’s mature SNMPv3 implementation, LibreNMS’s auto-discovery, and Grafana’s visualization layer delivers enterprise-grade network visibility with a licensing cost of zero. Start with SNMPv3 on your core devices, build out the LibreNMS inventory, then layer Grafana dashboards on top for the operational views your team will actually use when something breaks at midnight.

Use AES-128 minimum for privacy, lock SNMP access to your NMS subnet via ACL, and rotate your SNMPv3 credentials on the same schedule as your other privileged network credentials. The configuration above is a solid production baseline—tighten the MIB views as your inventory and operational needs become clearer.

Enjoying this post?

Get more guides like this delivered straight to your inbox. No spam, just tech and trails.