Skip to content
Learni
View all tutorials
Réseaux

How to Configure Secure SNMP v3 in 2026

Lire en français

Introduction

SNMP (Simple Network Management Protocol) remains the gold standard for network device monitoring and management in 2026. However, versions 1 and 2c are obsolete due to vulnerabilities like sniffing and spoofing attacks, falling short of modern security needs. SNMP v3 introduces the USM (User-based Security Model) with HMAC-SHA authentication and AES encryption, safeguarding sensitive data such as CPU metrics, interfaces, or logs.

This advanced tutorial walks you through configuring an SNMP v3 agent on Ubuntu 24.04 with net-snmp, testing via CLI, and building a Python manager with pysnmp. You'll generate secure keys, manage informative traps, and scale to distributed monitoring. By the end, you'll have a production-ready setup, dodging common pitfalls like weak configurations. Ideal for sysadmins and DevOps handling Cisco, Linux, or IoT fleets.

Prerequisites

  • Ubuntu 24.04 LTS server (or Debian 12+).
  • Root privileges (sudo).
  • Python 3.12+ installed.
  • Advanced knowledge of Linux, TCP/UDP networking, and cryptography (HMAC, AES).
  • Open ports: UDP 161 (agent), UDP 162 (traps).

Install net-snmp

install-net-snmp.sh
#!/bin/bash
apt update
apt install -y snmp snmp-mibs-downloader snmpd libsnmp-dev
systemctl stop snmpd
systemctl disable snmpd

This script updates packages, installs net-snmp (agent), standard MIBs, and dev libs for pysnmp. It stops and disables the service for a clean config, avoiding conflicts with the insecure default v1 setup.

Basic SNMP v2c Configuration (for initial testing)

Before moving to v3, test v2c to validate the installation. Edit /etc/snmp/snmpd.conf to allow queries from localhost or a specific manager IP. Limit to rocommunity for read-only access with a non-trivial community string. Restart snmpd and test with snmpget to check basics like sysDescr.0.

SNMP v2c Configuration File

/etc/snmp/snmpd.conf
agentAddress udp:161
view systemonly included .1.3.6.1.2.1.1
view all included .1.0
rocommunity public localhost
rocommunity secretmon 192.168.1.100
sysLocation "Data Center"
sysContact admin@example.com

This config listens on UDP 161, restricts MIB views (systemonly for basics, all for everything), and allows 'public' locally plus 'secretmon' from 192.168.1.100. Add sysLocation/Contact for identification. Avoid 'public' in production.

Test SNMP v2c with snmpget

test-v2c.sh
#!/bin/bash
systemctl start snmpd
systemctl enable snmpd
snmpget -v2c -c public localhost sysDescr.0
snmpget -v2c -c secretmon localhost 1.3.6.1.2.1.1.5.0

Starts and enables the service, then queries sysDescr.0 (system description) and sysName.0 via standard OID. Success shows the Ubuntu description. Pitfall: allow 161/udp in ufw firewall or it times out.

Migrating to SNMP v3: Creating the USM User

SNMP v3 shines with USM: auth (SHA256) ensures integrity, priv (AES192) encrypts payloads. Use snmpusm to create a user without plaintext passwords (generated via localized algorithms). Then configure vacm for read-only access.

Create SNMP v3 User

create-snmpv3-user.sh
#!/bin/bash
snmpusm -v3 -u monuser -l authPriv localhost create monuser monuser
snmpusm -v3 -u monuser -l authPriv localhost passwd -PAUTH monpassold monpassnew
snmpusm -v3 -u monuser -l authPriv localhost passwd -PPRIV monpassold monpassnew

Creates the 'monuser' user in authPriv mode, changes the auth password from 'monpassold' to 'monpassnew' (SHA), then priv (AES). Use localhost since snmpd must be running. Store generated passwords securely—they're one-way hashed.

snmpd.conf Configuration for SNMP v3

/etc/snmp/snmpd.conf
agentAddress udp:161
rouser monuser authPriv .1.3.6.1.2.1
createUser monuser SHA "monpassnew" AES "monpassnew"
# Traps sink
trap2sink 192.168.1.100 public
informsink 192.168.1.100 monuser authPriv

Authorizes 'monuser' authPriv on all MIBs (.1.3.6.1.2.1). createUser recreates the user on startup (with hashed pass). Adds trap2sink for v2c traps and informsink for v3 informs to the manager. Restart snmpd afterward.

SNMP v3 Polling with Python and pysnmp

Pysnmp is the go-to Python library for advanced SNMP. Install it with pip install pysnmp. The scripts below handle USM context, timeouts, and errors. Use for GET (single value) and WALK (subtree).

Python SNMP v3 GET Script

snmp_get_v3.py
from pysnmp.hlapi import *

iterator = getCmd(SnmpEngine(),
                  UsmUserData('monuser', 'monpassnew', 'monpassnew', authProtocol=usmHMACSHAAuthProtocol, privProtocol=usmAesCfb128Protocol),
                  UdpTransportTarget(('localhost', 161)),
                  ContextData(),
                  ObjectType(ObjectIdentity('1.3.6.1.2.1.1.5.0')))

for errorIndication, errorStatus, errorIndex, varBinds in iterator:
    if errorIndication:
        print(errorIndication)
        break
    elif errorStatus:
        print('%s at %s' % (errorStatus.prettyPrint(),
                            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
        break
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))

This script performs a GET on sysName.0 with USM SHA/AES128. Handles errors like timeouts or badUser. Copy-paste ready after pip install pysnmp. Analogy: like a encrypted USB key—USM validates before reading.

Python SNMP v3 WALK Script

snmp_walk_v3.py
from pysnmp.hlapi import *

for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(SnmpEngine(),
    UsmUserData('monuser', 'monpassnew', 'monpassnew', authProtocol=usmHMACSHAAuthProtocol, privProtocol=usmAesCfb128Protocol),
    UdpTransportTarget(('localhost', 161)), ContextData(),
    ObjectType(ObjectIdentity('1.3.6.1.2.1.1')), lexicographicMode=False):

    if errorIndication:
        print(errorIndication)
        break
    elif errorStatus:
        print('%s at %s' % (errorStatus.prettyPrint(),
                            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
        break
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))

WALK traverses the entire system subtree (1.3.6.1.2.1.1). lexicographicMode=False for natural order. Scalable for exporting to Prometheus or Grafana. Pitfall: timeouts on large MIB trees—add retries.

SNMP v3 Trap Receiver in Python

snmp_trap_receiver.py
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import ntforwrd
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.proto.api import v2c

# Create engine
snmpEngine = engine.SnmpEngine()

# Configure v3 inform user
config.addV3User(snmpEngine, 'monuser', config.usmHMACSHAAuthProtocol,
                 'monpassnew', config.usmAesCfb128Protocol, 'monpassnew')

# Listen for traps/informs on UDP 162
config.addTransport(snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('0.0.0.0', 162)))

# Forward to console
ntforwrd.NotificationForwarder(snmpEngine)

print('Starting trap receiver on port 162...')
snmpEngine.transportDispatcher.jobStarted(1)
try:
    snmpEngine.transportDispatcher.runDispatcher()
except:
    snmpEngine.transportDispatcher.closeDispatcher()

This receiver listens for v3 informs/traps on UDP 162, validates with USM, and logs to console. Run with sudo python snmp_trap_receiver.py. Test by generating a trap from the agent. Essential for real-time alerts.

Best Practices

  • Generate >20 char random passwords with pwgen, store in a vault (HashiCorp Vault).
  • Limit VACMM views: e.g., exclude .1.3.6.1.6.2 for sensitive traps.
  • Enable unique engineID per agent for anti-replay.
  • Monitor logs in /var/log/syslog for auth failures.
  • Integrate with modern stacks: export MIBs to Prometheus via snmp_exporter.

Common Errors to Avoid

  • Plaintext pass in snmpd.conf: use createUser with hashed, or logs expose them.
  • Forgot firewall: ufw allow from 192.168.1.0/24 to any port 161 proto udp.
  • Protocol mismatch: SHA without authKey or AES without privKey → 'unknownUserName'.
  • Unsunk traps: agent sends but manager ignores without UDP 162 listener.

Next Steps