{"id":148,"date":"2015-11-10T21:15:02","date_gmt":"2015-11-10T21:15:02","guid":{"rendered":"http:\/\/svops.com\/blog\/?p=148"},"modified":"2016-01-22T16:35:12","modified_gmt":"2016-01-22T16:35:12","slug":"snmp-traps-with-logstash","status":"publish","type":"post","link":"http:\/\/svops.com\/blog\/snmp-traps-with-logstash\/","title":{"rendered":"SNMP traps with logstash"},"content":{"rendered":"<h1>The Basics<\/h1>\n<p>SNMP traps are generally easy to receive and process with logstash. \u00a0The <a href=\"https:\/\/www.elastic.co\/guide\/en\/logstash\/current\/plugins-inputs-snmptrap.html\" target=\"_blank\">snmptrap{} input<\/a> sets up a listener, which processes each trap and replaces the OIDs with the string representation found in the given mibs. \u00a0If the OID can&#8217;t be found, logstash will make a new field, using the OID value as the field name, e.g.<\/p>\n<pre>\"1.3.6.1.4.1.1234.1.2.3.4\": \"trap value\"<\/pre>\n<p>(Note that this is <a href=\"https:\/\/github.com\/logstash-plugins\/logstash-input-snmptrap\/issues\/13\" target=\"_blank\">currently broken<\/a> if you use Elasticsearch 2.0).<\/p>\n<h1>Forwarding<\/h1>\n<p>Probably the biggest issues with most traps is that they are sent to port 162, which is a low-numbered &#8220;system&#8221; port. \u00a0For logstash to listen on that port, it must be run as root, which is not recommended.<\/p>\n<p>The easiest workaround for this is to forward port 162 to a higher-numbered port to which logstash can connect. \u00a0iptables is the typical tool to perform the forwarding:<\/p>\n<pre>\/sbin\/iptables -A PREROUTING -t nat -i eth0 -p udp --dport 162 -j REDIRECT --to-port\u00a05000<\/pre>\n<p>where &#8216;5000&#8217; is the port on which logstash is listening.<\/p>\n<h1>SNMP Sequences<\/h1>\n<p>Some SNMP traps come in with a &#8220;sequence number&#8221;, which allows the receiver to know if all traps have been received. \u00a0In the ones we&#8217;ve seen, the sequence is appended to each OID, e.g.<\/p>\n<pre>\"1.3.6.1.4.1.1234.1.2.3.4.90210\": \"trap value\"<\/pre>\n<p>where &#8220;90210&#8221; is the sequence number.<\/p>\n<p>This seems like a handy feature, but it doesn&#8217;t appear to be supported by logstash (or perhaps the underlying SNMP library that is uses). \u00a0With the basic snmptrap config, logstash is unable to apply the mib definition and remove the sequence number, so you end up with a new field for each trap value. \u00a0That&#8217;s not good for you or for elasticsearch\/kibana.<\/p>\n<p>Since traps aren&#8217;t just simple plain text, you can&#8217;t use a &#8220;tcp&#8221; listener, apply your own filter to remove the sequence, and feed the result back into logstash&#8217;s &#8220;snmptrap&#8221; mechanism. \u00a0Without modifying the snmptrap input plugin, you have to fix the problem before it hits logstash.<\/p>\n<blockquote><p>I was a fan of logstash plugins (and have written a few), but logstash 1.5 requires everything to be done as ruby gems, which has been a painful path. \u00a0As such, I&#8217;m doing more outside of logstash, like this recommendation.<\/p><\/blockquote>\n<h1>snmptrapd<\/h1>\n<p>We&#8217;re now running snmptrapd on our logstash machines. \u00a0They listen for traps on port 162 and write them to a regular log file that can then be read by logstash.<\/p>\n<h2>Basic config<\/h2>\n<p>Update \/etc\/snmp\/snmptrapd.conf to include:<\/p>\n<pre class=\"p1\">disableAuthorization yes<\/pre>\n<p>Put your mib definitions in\/usr\/share\/snmp\/mibs.<\/p>\n<h2>Trap formatting<\/h2>\n<p>To make the traps easier to process by logstash, I format the output as json. \u00a0This is done with OPTIONS set in \/etc\/sysconfig\/snmptrapd:<\/p>\n<pre>OPTIONS=\"-A -Lf \/var\/log\/snmptrap -p \/var\/run\/snmptrapd.pid -m ALL -F '{ \\\"type\\\": \\\"snmptrap\\\", \\\"timestamp\\\": \\\"%04y-%02m-%02l %02h:%02j:%02k\\\", \\\"host_ip\\\":\\\"%a\\\", \\\"trapEnterprise\\\": \\\"%N\\\", \\\"trapSubtype\\\": \\\"%q\\\", \\\"trapType\\\": %w, \\\"trapVariables\\\": \\\"%v\\\" }\\n' \"<\/pre>\n<p>The flags used are:<\/p>\n<ul>\n<li>-A &#8211; append to the log file rather than truncating it<\/li>\n<li>-Lf &#8211; log to a file<\/li>\n<li>-m ALL &#8211; use all the mibs it can find<\/li>\n<li>-F &#8211; use this printf-style string for formatting<\/li>\n<\/ul>\n<p>Then, in logstash, use the json filter:<\/p>\n<pre>filter {\r\n    json {\r\n        source =&gt; \"message\"\r\n    }\r\n}<\/pre>\n<p>I use a ruby filter to make the separate fields and cast them to the correct type.<\/p>\n<p>Don&#8217;t forget to setup a log file rotation on your new \/var\/log\/snmptrap file and setup a process monitor for snmptrapd.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Basics SNMP traps are generally easy to receive and process with logstash. \u00a0The snmptrap{} input sets up a listener, which processes each trap and replaces the OIDs with the string representation found in the given mibs. \u00a0If the OID &hellip; <a href=\"http:\/\/svops.com\/blog\/snmp-traps-with-logstash\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/posts\/148"}],"collection":[{"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/comments?post=148"}],"version-history":[{"count":7,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/posts\/148\/revisions"}],"predecessor-version":[{"id":169,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/posts\/148\/revisions\/169"}],"wp:attachment":[{"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/media?parent=148"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/categories?post=148"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/svops.com\/blog\/wp-json\/wp\/v2\/tags?post=148"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}