Slide 1

Slide 1 text

Tailored SNMP monitoring Your own SNMP MIB and sub-agent with Python and python-netsnmpagent OSMC 2018 November 6th, 2018 Pieter Hollants

Slide 2

Slide 2 text

Pieter who? Frankfurt, Germany-based developer (mostly Python) but also... ➔ 3y IT support in Netware/Win 95 times ➔ 9y (Senior) Intern at SUSE Consulting ➔ 4y Linux Systems Engineer at German Air Traffic Control (e.g. automated installations of high availability-systems, hardware standardization) ...and freelancing since over 15y (dev & admin)

Slide 3

Slide 3 text

MIB?

Slide 4

Slide 4 text

You’re down with…?

Slide 5

Slide 5 text

MIB ➔ Management Information Base ➔ Used to monitor and configure devices remotely ➔ Structured as tree with nameless root ➔ Defines entities called Managed Objects ➔ Access protocol “on the wire”: SNMP (Simple Network Management Protocol)

Slide 6

Slide 6 text

MIB modules ➔ MIB modules (“MIBs”) define branches of the tree, can be enterprise-specific or generic, e.g.: ➔ RFC 2863: IF-MIB (network interfaces) ➔ RFC 4022: TCP/IP MIB ➔ CISCOSB-MIB ➔ Defined in text files using ASN.1 subset called SMI (Structure of Management Information), v2: RFC2578 ➔ Definition != Implementation Wikipedia / CC-BY-SA

Slide 7

Slide 7 text

Managed Objects ➔ Uniquely identified by OID (Object Identifier) ➔ OIDs represented as ordered series of numbers (e.g. “.1.3.6.1.4.1”) or ASCII text labels (e.g. “.iso.org.dod. internet.private.enterprise”) ➔ Enterprise-specific OIDs with IANA assigned Enterprise Number ➔ https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers ➔ Two categories of data types: ➔ Scalar objects: ➔ (Un)Signed Integers ➔ Counters, Gauges, Time ticks ➔ Octet Strings/Display Strings, Bit Strings ➔ Network addresses ➔ Object identifiers ➔ Tabular objects (scalar objects grouped in tables)

Slide 8

Slide 8 text

Who’d write their own MIB? ➔ Application programmers wanting to expose internal metrics (e.g. transactions per second) ➔ OEMs (e.g. Nasuni Edge Appliance: https://cdn2.hubspot.net/ hubfs/3316942/Nasuni.com-assets/Support-Docs/Nasuni_Filer_Third- Party_Licensing_Guide.pdf) ➔ End users wishing to unify otherwise spread-out information under a common tree (e.g. vendor-neutral hardware agent used by German Air Traffic Control) ➔ InfraOps (e.g. DNSSEC monitoring: http://www.delaat.net/rp/2014-2015/p38/presentation.pdf) ➔ You? ;)

Slide 9

Slide 9 text

MIB deep dive Not Bernd Erk (Disclaimer: I know nothing about diving.)

Slide 10

Slide 10 text

MIB deep dive (5m) ➔ Formally defines ““ as everything between “BEGIN” and “END” ➔ Multiple MIB modules in a text file possible but uncommon ➔ Two dashes (“--”): comment lines

Slide 11

Slide 11 text

MIB deep dive (10m) ➔ Imports definitions (”features”) from existing MIBs, similar to “from … import …” in Python ➔ RFC 2579: SNMPv2-TC, RFC 2580: SNMPv2-CONF ➔ AgentX? We’ll see later...

Slide 12

Slide 12 text

MIB deep dive (15m) ➔ Collects module purpose, contact information, description, revision information ➔ Defined as OID of subtree this MIB handles (“plugs in”) ➔ Must be first item after module header and imports Wrong OID! Why?

Slide 13

Slide 13 text

MIB deep dive (20m) ➔ Associates a name with subtrees in a particular part of the MIB module’s OID tree, similar to naming subdirs ➔ For human convenience, technically not really required ➔ len(OID subtree def) == 2 ➔ “[..] must not be included in an IMPORTS statement”

Slide 14

Slide 14 text

MIB deep dive (25m) ➔ Defines scalar variables in a particular part of the MIB module’s OID tree, similar to naming files ➔ SYNTAX: type of the variable ➔ MAX-ACCESS: read-only/read-write/not-accessible/... ➔ STATUS: current/deprecated/obsolete ➔ DESCRIPTION: for humans and humanoids

Slide 15

Slide 15 text

MIB deep dive (30m) ➔ Defines a “row” as a SEQUENCE of scalar MOs ➔ Simulation of table through N subtrees ~= columns as defined here (holes possible!) ➔ MOs referenced with name and type only ➔ Still need explicit definition...

Slide 16

Slide 16 text

MIB deep dive (32m) ➔ Definitions of columns in a row ➔ MAX-ACCESS not-accessible in practical use for row that will be used as index row (here the only one) ➔ In this example other rows will be read-only

Slide 17

Slide 17 text

MIB deep dive (34m) ➔ Table ~= SEQUENCE OF (SEQUENCE ...) ➔ Both table and row themselves not-accessible ➔ INDEX magically overwrites 1 with values in referenced index column (values = indexes)

Slide 18

Slide 18 text

MIB deep dive (36m) ➔ Table object not-accessible → snmpget = no such object ➔ Same for defined row, e.g. firstTable.1 = no such object ➔ snmpwalk reveals low-level ... construct ➔ snmptable knows how to interpret tables semantics ➔ firstTableRowIndex values = indexes

Slide 19

Slide 19 text

MIB deep dive (40m) ➔ Always check your MIBs with “smilint” ➔ Part of libsmi, other nice tools such as “smidiff”, “smidump”… ➔ http://www.ibr.cs.tu-bs.de/projects/libsmi/ ➔ Also validate with increased “-lX” severity levels, then learn about MIB concepts you haven’t heard about yet (e.g. conformance groups)

Slide 20

Slide 20 text

Out of breath?

Slide 21

Slide 21 text

Let’s define our own MIB!

Slide 22

Slide 22 text

Let’s define our own MIB! We need something to monitor...

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

Our GT-MIB (1/2) ...we should actually register our own Enterprise Number with IANA! http://pen.iana.org/pen/PenApplication.page

Slide 25

Slide 25 text

Our GT-MIB (2/2) Index column doesn’t necessarily have to be named “...Index”

Slide 26

Slide 26 text

Implementing SNMP ➔ De-facto standard: Net-SNMP suite (formerly called UCD-SNMP), found in all major distros ➔ Current release: 5.8 (July 16th, 2018) ➔ Consists of ➔ Command-line applications such as snmpget, snmpset, snmpwalk, snmptable, snmptranslate... ➔ Extensible agent (software that handles SNMP requests) with built-in support for wide range of MIB modules: snmpd ➔ Daemon for receiving SNMP traps: snmptrapd ➔ Libraries for developing SNMP apps, C/Perl APIs ➔ Tools such as mib2c

Slide 27

Slide 27 text

Implementing MIBs ➔ snmpd: built-in support for number of MIBs, e.g. IF-MIB ➔ Extensible: snmpd as master agent allows for subagents implementing parts of the MIB (MIB modules) ➔ Three alternatives differing in data representation and communication mechanisms: ➔ Proxied SNMP: standard SNMP packet format, full fledged agent unaware of subagent role on non-standard port ➔ SMUX (RFC 1227): standard SNMP packet format, subagent registers with master agent, issues, historical ➔ AgentX (RFC 2741): more compact packet format, advanced functionality, state of the art, enabled with “master agentx” line in snmpd.conf

Slide 28

Slide 28 text

Net-SNMP mib2c (1/2) mib2c currently can’t handle MIBs with both tables and scalars Different approaches to implement tables possible Input: MIB Output: Skeleton C code

Slide 29

Slide 29 text

Net-SNMP mib2c (2/2) Only init callback shown here

Slide 30

Slide 30 text

Net-SNMP mib2c (2/2) Yeah, okay, C code but… isn’t there something easier?

Slide 31

Slide 31 text

Net-SNMP mib2c (2/2) Yeah, okay, C code but… isn’t there something easier?

Slide 32

Slide 32 text

Python & SNMP support ➔ Net-SNMP ships with Python “netsnmp” module ➔ 2500 lines C code that abstract Net-SNMP C API ➔ SNMP client only: get, walk… operations ➔ C API has support for writing agents as well (as seen with mib2c) ➔ Idea: access C API directly from Python using ctypes, imitating agents written in C ➔ Existing python-agentx module on Sourceforge ➔ Design issues (= I didn’t grok it ;) ➔ Orphaned ➔ 2015: pyagentx module on Github, actually implements AgentX network protocol, meanwhile orphaned as well

Slide 33

Slide 33 text

Hello python-netsnmpagent! ➔ Python module I wrote back in 2013 driven by requirements at German Air Traffic Control ➔ LGPLv3 licensed ➔ Source at https://github.com/pief/python-netsnmpagent ➔ Distributable archives on PyPI ➔ RPMs available on Open Build Service ➔ Compatible with Python 2.6, 2.7 and >=3.5 ➔ Tested with net-snmp 5.4.x (SLES11…), 5.7.x, 5.8 ➔ Two extensively commented files ➔ netsnmpapi.py (ctypes stuff for internal use), 317 LOC ➔ netsnmpagent.py (abstraction classes), 839 LOC ➔ No docs but example MIBs/agents included

Slide 34

Slide 34 text

Our gtmib_agent.py (1/3) Used by Net-SNMP e.g. to translate OIDs Default value for column Classes representing data types Only import required Column number Class factory OID this SNMP object handles

Slide 35

Slide 35 text

Our gtmib_agent.py (2/3) Values for index and data columns Connects to master agent – no more object registrations!

Slide 36

Slide 36 text

Our gtmib_agent.py (3/3) Signal handler triggered eg. by ^C Net-SNMP internal packet processing Example in this form not well-suited for real agents. Why?

Slide 37

Slide 37 text

Et voila! Live demo anyone?

Slide 38

Slide 38 text

The fineprint ➔ Currently no support for callback pattern, i.e. data structures must be periodically refreshed ➔ check_and_process() blocks, threading required to do processing and data updating in parallel ➔ Development has slowed somewhat because no active sponsor anymore → your chance? ➔ Some open issues ➔ No support for SNMP traps yet (but MR exists) ➔ Only rudimentary unit tests ➔ It’s Open Source, take your chance!

Slide 39

Slide 39 text

EOT Pieter Hollants [email protected] pfhllnts [email protected]