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"
}
}'
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"
}'
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"}
]
}'
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 β
ββββββββββββββββββ βββββββββββββββββββ
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
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)
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);
}
});
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
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);
}
}
}
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>' : ''}
`;
});
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"]
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:
- Lazy loading: Load children only when node is expanded
- Depth control: User chooses 1-5 levels (prevents over-expansion)
- Debounced search: 500ms delay to avoid excessive API calls
- 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
});
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
Good:
curl -fsSL https://raw.githubusercontent.com/tosumitdhaka/trishul-snmp/main/install-trishul-snmp.sh | bash
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
Access:
- Frontend: http://localhost:8080
-
Default login:
admin/admin123
Explore:
- Upload a MIB file (try IF-MIB)
- Browse the MIB tree
- Walk a device (or use the simulator)
- Send a test trap
- 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:
- Modern web tech can revitalize old protocols - SNMP is from 1988, but a good UI makes it accessible
- Open source is about community, not just code - Documentation, support, and engagement matter
- Good UX matters, even for network tools - Engineers appreciate beautiful, intuitive interfaces too
- 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:
- π GitHub: @tosumitdhaka
- πΌ LinkedIn: Sumit Dhaka
- π§ Email: sumitdhaka@zohomail.in
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)