SNMP Agent on Port 1161: Timeout Issue with Net-SNMP Queries

78 views Asked by At

I have a custom snmp agent, based on pysnmp and I started it on port 1161, and also I have the custom MIB file. I want to check if it works with the get command, but I get the error "Timeout: No response"

my_snmp-agent.py

from pysnmp.hlapi import *
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp import debug
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.smi import instrum, builder
from pysnmp.proto.api import v2c
import psutil
from pysnmp.smi import exval

# Create SNMP engine
snmpEngine = engine.SnmpEngine()

# Custom OIDs from MY-MIB
CPU_OID = '1.3.6.1.4.1.9999.2'  # MY-MIB::cpuUtil
MEMORY_OID = '1.3.6.1.4.1.9999.1'  # MY-MIB::memoryUtil
DISK_OID = '1.3.6.1.4.1.9999.3'  # MY-MIB::diskUtil

def get_cpu_usage():
    """ CPU usage percentage """
    return int(psutil.cpu_percent(interval=1))

def get_memory_usage():
    """ Memory usage percentage """
    memory = psutil.virtual_memory()
    return int(memory.used * 100 / memory.total)

def get_disk_usage():
    """ Disk usage percentage: main partition """
    disk = psutil.disk_usage('/')
    return int(disk.used * 100 / disk.total)

def create_variable_binds(oid, value):
    return [ObjectType(ObjectIdentity(oid), Integer32(value))]

def create_snmp_agent():
    """ an SNMP agent listening for GET requests """
    
    def process_snmp_request(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx):
        """ Processing SNMP GET requests """
        oid, = [x[0] for x in varBinds]
        oid_str = str(oid)
    
        print("Received request for OID:", oid_str)
    
        # Using appropriate response based on the OID
        if oid_str.startswith(CPU_OID):
            value = get_cpu_usage()
        elif oid_str.startswith(MEMORY_OID):
            value = get_memory_usage()
        elif oid_str.startswith(DISK_OID):
            value = get_disk_usage()
        else:
            value = 0  # Default response for unrecognized OIDs

        # Creating and sending the response
        varBinds = create_variable_binds(oid, value)
        cmdrsp.sendVarBinds(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx)

    # Registering SNMP application
    cmdrsp.GetCommandResponder(snmpEngine, CommunityData('public', mpModel=1))

    # Processing SNMP GET requests
    snmpContext = context.SnmpContext(snmpEngine)
    snmpContext.registerContextName(v2c.OctetString('public'), process_snmp_request)
    # Transport (UDP over IPv4)
    config.addTransport(snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', 1161)))

    print("SNMP Agent is running...")
    snmpEngine.transportDispatcher.jobStarted(1)

    try:
        # Start dispatcher for receiving queries and sending responses
        snmpEngine.transportDispatcher.runDispatcher()
    except:
        snmpEngine.transportDispatcher.closeDispatcher()
        raise

if __name__ == "__main__":
    create_snmp_agent()

MY-MIB.txt

MY-MIB DEFINITIONS ::= BEGIN
  IMPORTS
      MODULE-IDENTITY, OBJECT-TYPE, Integer32 
      FROM SNMPv2-SMI;
  
  myMIB MODULE-IDENTITY
      LAST-UPDATED "202401260000Z"
      ORGANIZATION "MyOrganization"
      CONTACT-INFO "[email protected]"
      DESCRIPTION "MIB for custom SNMP agent"
      REVISION "202401260000Z"
      DESCRIPTION "This custom version MIB"
      ::= { enterprises 9999 }

  enterprises OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) }

  memoryUtil OBJECT-TYPE
      SYNTAX Integer32
      MAX-ACCESS read-only
      STATUS current
      DESCRIPTION "Memory Utilization in percentage"
      ::= { myMIB 1 }

  cpuUtil OBJECT-TYPE
      SYNTAX Integer32
      MAX-ACCESS read-only
      STATUS current
      DESCRIPTION "CPU Utilization in percentage"
      ::= { myMIB 2 }

  diskUtil OBJECT-TYPE
      SYNTAX Integer32
      MAX-ACCESS read-only
      STATUS current
      DESCRIPTION "Disk Utilization in percentage"
      ::= { myMIB 3 }
END

Successfully compiled it.

smidump -k -f python -o my-mib.py MY-MIB.txt

Starting my Agent in 1st Terminal:

python3 my_snmp-agent.py
SNMP Agent is running...

Testing with Net-SNMP in 2nd Terminal:

snmpget -v2c -c public 127.0.0.1:1161 1.3.6.1.4.1.9999.1
Timeout: No Response from 127.0.0.1:1161.
snmpwalk -v2c -c public 127.0.0.1:1161 1.3.6.1.4.1.9999
Timeout: No Response from 127.0.0.1:1161
snmpbulkget -v2c -c public 127.0.0.1:1161 1.3.6.1.4.1.9999.1 1.3.6.1.4.1.9999.2 1.3.6.1.4.1.9999.3
Timeout: No Response from 127.0.0.1:1161

Using Debugging(-d) option in 2nd Terminal:

snmpget -v2c -c public -d 127.0.0.1:1161 1.3.6.1.4.1.9999.1
No log handling enabled - using stderr logging

Sending 43 bytes to UDP: [127.0.0.1]:1161->[0.0.0.0]:0
0000: 30 29 02 01  01 04 06 70  75 62 6C 69  63 A0 1C 02    0).....public?..
0016: 04 19 1E B4  74 02 01 00  02 01 00 30  0E 30 0C 06    ...?t......0.0..
0032: 08 2B 06 01  04 01 CE 0F  01 05 00                    .+....?....

Starting tcpdump in 3rd Terminal:

tcpdump -i any port 1161 -vv
tcpdump: data link type PKTAP
tcpdump: listening on any, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
19:20:30.761706 IP (tos 0x0, ttl 64, id 13838, offset 0, flags [none], proto UDP (17), length 71, bad cksum 0 (->4696)!)
    localhost.49661 > localhost.health-polling: [bad udp cksum 0xfe46 -> 0x1ad6!] UDP, length 43
19:20:30.761729 IP (tos 0x0, ttl 64, id 13838, offset 0, flags [none], proto UDP (17), length 71, bad cksum 0 (->4696)!)
    localhost.49661 > localhost.health-polling: [bad udp cksum 0xfe46 -> 0x1ad6!] UDP, length 43
19:20:31.766991 IP (tos 0x0, ttl 64, id 17114, offset 0, flags [none], proto UDP (17), length 71, bad cksum 0 (->39ca)!)

1

There are 1 answers

0
Lex Li On

The answer is that OID access was not configured in your code.

You need to call config.addVacmUser to open up OID access to any community/user names.

I've written a complete example here.