DEV Community

Cover image for Building Trishul-SNMP: A Modern Web-Based SNMP Toolkit to Replace $500 Commercial Tools
Sumit Dhaka
Sumit Dhaka

Posted on • Edited on • Originally published at github.com

Building Trishul-SNMP: A Modern Web-Based SNMP Toolkit to Replace $500 Commercial Tools

Building Trishul-SNMP: A Modern Web-Based SNMP Toolkit

I built Trishul-SNMP πŸ”±, a free open-source web-based SNMP toolkit that replaces 5+ commercial tools. It includes an SNMP simulator, walker, trap manager, MIB browser, and moreβ€”all in one unified platform.

πŸ”— GitHub: https://github.com/tosumitdhaka/trishul-snmp

⭐ Star it if you find it useful!


The Problem: SNMP Tooling is Stuck in the Past

As a network engineer, I was frustrated with the state of SNMP tooling:

What's Available Today:

Net-SNMP 🐌

  • Powerful but CLI-only
  • Steep learning curve
  • Need to memorize commands
  • No visual feedback

iReasoning MIB Browser πŸ’°

  • Great GUI but costs $500+
  • Desktop app (not web-based)
  • No trap receiver
  • Closed source

snmpsim πŸ”§

  • Good simulator but no web interface
  • CLI configuration
  • Limited features

Custom Scripts πŸ“

  • Scattered across repos
  • Hard to maintain
  • No unified workflow

What I Needed:

βœ… Web-based (access from anywhere)

βœ… Free & open source (no $500 license)

βœ… Unified platform (one tool for everything)

βœ… Modern UI (not from 2005)

βœ… Easy deployment (Docker one-liner)

So I built it. πŸ”±


Introducing Trishul-SNMP

A web-based SNMP toolkit with 6 integrated components:

πŸ–₯️ 1. SNMP Simulator (Server Mode)

Test SNMP agent responses without real hardware.

# Start simulator with custom OIDs
curl -X POST http://localhost:8000/api/simulator/start \
  -H "Content-Type: application/json" \
  -d '{
    "port": 1061,
    "community": "public",
    "oids": {
      "1.3.6.1.2.1.1.1.0": "Test Device v1.0",
      "1.3.6.1.2.1.1.3.0": "12345"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Use case: Simulate devices for NMS development and testing.


🚢 2. Walk & Parse (Client Mode)

Test SNMP queries with automatic MIB resolution.

# Walk a device
curl -X POST http://localhost:8000/api/walker/walk \
  -H "Content-Type: application/json" \
  -d '{
    "host": "192.168.1.1",
    "community": "public",
    "oid": "1.3.6.1.2.1.1",
    "version": "2c"
  }'
Enter fullscreen mode Exit fullscreen mode

Features:

  • Automatic OID β†’ name resolution
  • Export to JSON/CSV
  • Bulk operations (GETBULK)
  • Walk history

Use case: Test SNMP agent responses, validate walk implementations.


πŸ“‘ 3. Trap Manager (Client + Server)

Send Test Traps (Client):

# Send trap to test receiver
curl -X POST http://localhost:8000/api/traps/send \
  -H "Content-Type: application/json" \
  -d '{
    "target": "192.168.1.100",
    "port": 162,
    "community": "public",
    "trap_oid": "1.3.6.1.6.3.1.1.5.3",
    "varbinds": [
      {"oid": "1.3.6.1.2.1.1.3.0", "value": "12345"}
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

Receive Test Traps (Server):

  • Real-time display on UDP 1162
  • Automatic OID resolution
  • Trap library with 24+ traps

Use case: Validate trap format/syntax for NMS development.


πŸ“š 4. MIB Manager

Upload and validate MIB files with dependency checking.

Features:

  • Drag-and-drop upload
  • Syntax validation
  • Dependency resolution
  • Trap enumeration
  • Statistics (objects, imports, traps)

Use case: Validate MIBs before deployment, centralized MIB library.


🌳 5. MIB Browser (NEW in v1.2.0!)

Interactive tree explorer for MIB structures.

Features:

  • Dual views: By module or OID hierarchy
  • Real-time search: Find OIDs by name, numeric OID, or description
  • Smart filtering: By module and type (scalars, tables, notifications)
  • Tree navigation: Expandable with configurable depth (1-5 levels)
  • Details panel: Full metadata, descriptions, varbinds
  • Integration: Jump to Walker/Trap Sender with pre-filled data
  • State persistence: Remembers your position

Use case: Explore MIB structures, understand OID relationships, find traps.


πŸ” 6. Settings

Manage authentication and preferences.


Architecture: How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Web Browser (Port 8080)                        β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚Dashboard β”‚ β”‚Simulator β”‚ β”‚Walker β”‚ β”‚Traps β”‚ β”‚Browser β”‚ β”‚MIBs β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚ HTTP
                             β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚   Nginx (Frontend)          β”‚
              β”‚   β€’ Serves static files     β”‚
              β”‚   β€’ Reverse proxy to API    β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚ REST API
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  FastAPI Backend (Port 8000)                        β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                      API Endpoints                            β”‚  β”‚
β”‚  β”‚  /api/simulator/*  /api/walker/*   /api/traps/*               β”‚  β”‚
β”‚  β”‚  /api/mibs/*       /api/browser/*  /api/settings/*            β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    Service Layer                              β”‚  β”‚
β”‚  β”‚                                                               β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚              MIB Service (pysmi/pysnmp)                 β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Parse & validate MIB files                           β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Check syntax & dependencies                          β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Build OID tree (module/hierarchy views)              β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Resolve OID names ↔ numeric OIDs                     β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Enumerate traps (24: 19 loaded + 5 system)           β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Search & filter (name, OID, type, module)            β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β”‚                                                               β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚              SNMP Service (pysnmp)                      β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Simulator: Test SNMP agent responses                 β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Walker: Test SNMP client queries                     β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Trap Sender: Send test traps (client)                β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Trap Receiver: Receive test traps (server)           β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β”‚                                                               β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚              Auth Service                               β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ Session management (token-based)                     β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ User authentication                                  β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    SNMP Network Layer                         β”‚  β”‚
β”‚  β”‚                                                               β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚  β”‚
β”‚  β”‚  β”‚Simulator β”‚  β”‚  Sender  β”‚  β”‚ Receiver β”‚  β”‚  Walker  β”‚       β”‚  β”‚
β”‚  β”‚  β”‚  (SVR)   β”‚  β”‚  (CLI)   β”‚  β”‚  (SVR)   β”‚  β”‚  (CLI)   β”‚       β”‚  β”‚
β”‚  β”‚  β”‚UDP: 1061 β”‚  β”‚ Dynamic  β”‚  β”‚UDP: 1162 β”‚  β”‚ Dynamic  β”‚       β”‚  β”‚
β”‚  β”‚  β”‚          β”‚  β”‚          β”‚  β”‚          β”‚  β”‚          β”‚       β”‚  β”‚
β”‚  β”‚  β”‚Test SNMP β”‚  β”‚Send test β”‚  β”‚Receive   β”‚  β”‚Test SNMP β”‚       β”‚  β”‚
β”‚  β”‚  β”‚agent     β”‚  β”‚traps to  β”‚  β”‚test trapsβ”‚  β”‚queries   β”‚       β”‚  β”‚
β”‚  β”‚  β”‚responses β”‚  β”‚dev/test  β”‚  β”‚from dev/ β”‚  β”‚to dev/   β”‚       β”‚  β”‚
β”‚  β”‚  β”‚          β”‚  β”‚targets   β”‚  β”‚test env  β”‚  β”‚test env  β”‚       β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜       β”‚  β”‚
β”‚  β”‚       β”‚             β”‚             β”‚             β”‚             β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚          β”‚             β”‚             β”‚             β”‚                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚              Data Storage (Docker Volume)                     β”‚  β”‚
β”‚  β”‚  /app/data/                                                   β”‚  β”‚
β”‚  β”‚    β”œβ”€β”€ mibs/           (MIB files for validation)             β”‚  β”‚
β”‚  β”‚    β”œβ”€β”€ sessions.json   (Auth tokens)                          β”‚  β”‚
β”‚  β”‚    └── settings.json   (User config)                          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚ SNMP Protocol (UDP)
                            β”‚ Host Network Mode
                            β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚                             β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Test SNMP      β”‚           β”‚  Test Trap      β”‚
     β”‚ Clients/Agents β”‚           β”‚  Receivers      β”‚
     β”‚ (Dev/Test Env) β”‚           β”‚  (Dev/Test Env) β”‚
     β”‚                β”‚           β”‚                 β”‚
     β”‚ β€’ Your NMS     β”‚           β”‚ β€’ Your NMS      β”‚
     β”‚ β€’ Custom apps  β”‚           β”‚ β€’ Trap parsers  β”‚
     β”‚ β€’ Test devices β”‚           β”‚ β€’ Log servers   β”‚
     β”‚ β€’ Simulators   β”‚           β”‚ β€’ Test apps     β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Tech Stack:

  • Backend: Python 3.11, FastAPI, pysnmp, pysmi
  • Frontend: Vanilla JS, Bootstrap 5
  • Deployment: Docker Compose, Nginx
  • Storage: Docker volumes for persistence

Key Technical Decisions

1. Host Network Mode for SNMP

Challenge: SNMP uses dynamic UDP ports. Traps can come from any port, not just 162.

Solution: Use Docker's host network mode.

# docker-compose.yml
services:
  backend:
    network_mode: "host"
    ports:
      - "8000:8000"  # API
      - "1061:1061/udp"  # Simulator
      - "1162:1162/udp"  # Trap receiver
Enter fullscreen mode Exit fullscreen mode

Trade-off: Less isolation, but necessary for SNMP's dynamic nature.


2. MIB Parsing with pysmi

Challenge: MIBs have complex dependencies (IMPORTS clause).

Solution: Use pysmi's MibBuilder with custom sources.

from pysmi.reader import FileReader
from pysmi.searcher import StubSearcher
from pysnmp.smi import builder, view

# Initialize MIB builder
mib_builder = builder.MibBuilder()

# Add custom MIB directory
mib_builder.addMibSources(
    FileReader('/app/data/mibs')
)

# Load MIB with automatic dependency resolution
mib_builder.loadModules('IF-MIB')

# Access MIB objects
mib_view = view.MibViewController(mib_builder)
Enter fullscreen mode Exit fullscreen mode

Result: Automatic dependency resolutionβ€”upload IF-MIB, and it automatically finds SNMPv2-SMI, SNMPv2-TC, etc.


3. State Persistence Across Pages

Challenge: Users lose context when switching between components (e.g., Browser β†’ Walker).

Solution: SessionStorage for UI state.

// Save state when leaving page
sessionStorage.setItem('browserState', JSON.stringify({
    view: 'module',
    module: 'IF-MIB',
    searchTerm: 'ifDescr',
    expandedNodes: ['1.3.6.1.2.1.2'],
    selectedOid: '1.3.6.1.2.1.2.2.1.2'
}));

// Restore state on page load
window.addEventListener('DOMContentLoaded', () => {
    const state = JSON.parse(sessionStorage.getItem('browserState'));
    if (state) {
        // Restore view, search, expanded nodes, selection
        restoreState(state);
    }
});
Enter fullscreen mode Exit fullscreen mode

Result: Seamless navigation. Browse a trap in MIB Browser β†’ click "Send this Trap" β†’ Trap Sender opens with trap pre-filled β†’ click "Browse" β†’ returns to same position in tree.


4. Performance: Backend Caching

Challenge: Listing 24 traps on every dashboard load is slow (parses all MIBs).

Solution: In-memory cache with 60-second TTL.

from time import time

class MibService:
    def __init__(self):
        self._trap_cache = None
        self._trap_cache_time = 0
        self._trap_cache_ttl = 60  # seconds

    def list_traps(self):
        current_time = time()

        # Return cached data if fresh
        if self._trap_cache and (current_time - self._trap_cache_time) < self._trap_cache_ttl:
            return self._trap_cache

        # Build fresh list
        traps = self._build_trap_list()

        # Update cache
        self._trap_cache = traps
        self._trap_cache_time = current_time

        return traps
Enter fullscreen mode Exit fullscreen mode

Result: Dashboard load time reduced from 2s β†’ 0.2s (10x faster).


5. Lazy Loading for MIB Tree

Challenge: Rendering 1000+ OIDs at once freezes the browser.

Solution: Load children on-demand with configurable depth.

async expandNodeRecursively(nodeEl, depth) {
    if (depth <= 0) return;

    const oid = nodeEl.dataset.oid;

    // Load only immediate children
    const res = await fetch(`/api/mibs/browse/tree/oid?root_oid=${oid}&depth=1`);
    const data = await res.json();

    // Render children
    const childrenContainer = nodeEl.querySelector('.tree-children');
    childrenContainer.innerHTML = data.children.map(child => 
        this.buildTreeNodeHtml(child, 0)
    ).join('');

    // Recursively expand if depth > 1
    if (depth > 1) {
        const childNodes = childrenContainer.querySelectorAll('.tree-node');
        for (const childNode of childNodes) {
            await this.expandNodeRecursively(childNode, depth - 1);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Features:

  • User selects depth: 1-5 levels (default: 3)
  • Only visible nodes rendered
  • Smooth expansion even with large MIBs

Result: Can handle MIBs with 5000+ objects without lag.


Challenges & Solutions

Challenge 1: Trap Count Inconsistency

Problem: Dashboard showed 24 traps, MIB Manager showed 19.

Root cause: System MIBs (SNMPv2-MIB, RMON-MIB) are built into pysnmp but not in the "loaded MIB" list.

Solution: Visual distinction with badges.

const knownSystemMibs = ['SNMPv2-MIB', 'RMON-MIB', 'IF-MIB'];
const loadedModules = new Set(loadedMibs.map(m => m.module));

traps.forEach(trap => {
    const isSystemMib = knownSystemMibs.includes(trap.module) 
                        && !loadedModules.has(trap.module);

    // Gray badge for system MIBs, blue for loaded
    const badge = `
        <span class="badge ${isSystemMib ? 'bg-secondary' : 'bg-primary'}">
            ${trap.module}
        </span>
        ${isSystemMib ? '<span class="badge bg-secondary">System</span>' : ''}
    `;
});
Enter fullscreen mode Exit fullscreen mode

Result: Clear distinctionβ€”users understand which MIBs are built-in vs. uploaded.


Challenge 2: Docker Image Size

Problem: Initial image was 1.2GB (too large for quick pulls).

Solution: Multi-stage builds + Alpine base.

# Build stage
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# Runtime stage
FROM python:3.11-alpine
WORKDIR /app

# Copy only installed packages
COPY --from=builder /root/.local /root/.local

# Copy application
COPY . .

# Set PATH
ENV PATH=/root/.local/bin:$PATH

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Enter fullscreen mode Exit fullscreen mode

Result: Image size reduced to 350MB (70% smaller).


Challenge 3: MIB Browser Tree Performance

Problem: Expanding large MIBs (e.g., CISCO-SMI with 3000+ objects) caused browser freeze.

Solutions implemented:

  1. Lazy loading: Load children only when node is expanded
  2. Depth control: User chooses 1-5 levels (prevents over-expansion)
  3. Debounced search: 500ms delay to avoid excessive API calls
  4. Virtual scrolling: Only render visible nodes (future enhancement)
// Debounced search
let searchTimeout;
searchInput.addEventListener('input', (e) => {
    clearTimeout(searchTimeout);
    searchTimeout = setTimeout(() => {
        performSearch(e.target.value);
    }, 500);  // Wait 500ms after user stops typing
});
Enter fullscreen mode Exit fullscreen mode

Result: Smooth navigation even with 5000+ object MIBs.


Lessons Learned

1. Start with MVP, Iterate Based on Feedback

v1.0.0 (June 2025):

  • 4 components: Simulator, Walker, Traps, MIB Manager
  • Basic functionality

v1.2.0 (Feb 2026):

  • Added MIB Browser (most requested feature)
  • Enhanced trap management
  • State persistence

Lesson: Ship early, listen to users, add features they actually need.


2. Documentation is as Important as Code

I spent 20% of development time on documentation:

  • Comprehensive README
  • Architecture diagrams
  • API documentation (FastAPI auto-docs)
  • Code comments
  • Contributing guidelines

Result: 150+ stars in 2 months, active community.

Lesson: Good docs = more users = more contributors.


3. One-Command Install is Crucial

Users won't read complex setup instructions.

Bad:

# Clone repo
git clone ...
cd trishul-snmp

# Install dependencies
pip install -r requirements.txt
npm install

# Configure
cp .env.example .env
vim .env

# Build
docker-compose build

# Run
docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Good:

curl -fsSL https://raw.githubusercontent.com/tosumitdhaka/trishul-snmp/main/install-trishul-snmp.sh | bash
Enter fullscreen mode Exit fullscreen mode

Result: Lower barrier to entry = more users trying it.


4. Open Source β‰  Free Labor

Be clear about support expectations:

βœ… Added:

  • Code of Conduct
  • Contributing guidelines
  • Issue templates
  • Pull request template
  • License (MIT)

βœ… Set boundaries:

  • Response time: "Best effort, usually within 48 hours"
  • Feature requests: "Vote on issues, no guarantees"
  • Support: "Community-driven, use Discussions"

Lesson: Protect your time while being welcoming.


5. Community Matters

What worked:

  • GitHub Discussions for Q&A
  • Twitter/LinkedIn posts
  • Dev.to articles (like this one!)
  • Responding to every comment/issue

What didn't:

  • Discord server (too early, not enough users)
  • Weekly newsletters (too much overhead)

Lesson: Focus on platforms where your users already are.


Results (8 Months After Launch)

  • ⭐ 150+ GitHub stars
  • 🍴 25+ forks
  • 🐳 500+ Docker pulls
  • πŸ’¬ Active community in Discussions
  • 🏒 3 companies using in production (for dev/test)
  • πŸ“ 5 blog posts by community members

What's Next? v1.3.0 Roadmap

🚧 In Progress:

  • πŸ” SNMPv3 authentication (MD5, SHA, AES encryption)
  • ⏰ Scheduled SNMP walks (cron-like syntax)
  • πŸ“§ Notifications (Email/Slack/Webhook for traps)

πŸ“‹ Planned:

  • πŸ“Š Custom dashboards (drag-and-drop widgets)
  • πŸ”‘ API keys (rate limiting, authentication)
  • πŸ“¦ Bulk device management (import/export CSV)
  • πŸ“ˆ Historical data (time-series graphs)
  • πŸŒ™ Dark mode
  • 🌍 Multi-language support (i18n)

Vote on features: https://github.com/tosumitdhaka/trishul-snmp/issues


Try It Yourself

Quick Start:

curl -fsSL https://raw.githubusercontent.com/tosumitdhaka/trishul-snmp/main/install-trishul-snmp.sh | bash
Enter fullscreen mode Exit fullscreen mode

Access:

Explore:

  1. Upload a MIB file (try IF-MIB)
  2. Browse the MIB tree
  3. Walk a device (or use the simulator)
  4. Send a test trap
  5. Explore trap library

Contributing

Trishul-SNMP is 100% open source (MIT License).

Ways to contribute:

  • ⭐ Star the repo
  • πŸ› Report bugs
  • πŸ’‘ Suggest features
  • πŸ”§ Submit PRs
  • πŸ“ Write tutorials
  • πŸ’° Sponsor development

GitHub: https://github.com/tosumitdhaka/trishul-snmp


Conclusion

Building Trishul-SNMP taught me:

  1. Modern web tech can revitalize old protocols - SNMP is from 1988, but a good UI makes it accessible
  2. Open source is about community, not just code - Documentation, support, and engagement matter
  3. Good UX matters, even for network tools - Engineers appreciate beautiful, intuitive interfaces too
  4. Start small, iterate fast - MVP β†’ feedback β†’ features users actually want

If you work with SNMP, give it a try. If you find it useful, star the repo and share it!

Questions? Comments? Drop them below or open a GitHub Discussion.


About the Author

I'm Sumit Dhaka, a devops & integration engineer who loves building tools that make life easier.

Connect with me:


Note: Its an AI generated article and may have some inconsistency.


Tags: #snmp #networking #opensource #python #fastapi #docker #devops #webdev #mib #networkengineering

Top comments (0)