http://www.perlmonks.org?node_id=1020379

ahm123 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I am trying to figure out how to encode snmpv2 trap using Encoding::BER module

This is my trap varbind.

varbindlist (
'1.3.6.1.2.1.1.3.0', , TIMETICKS, 600,
'1.3.6.1.6.3.1.1.4.1.0',OBJECT_IDENTIFIER,'1.3.6.1.4.1.42767.64.1.1.5.1.40.1',
'1.3.6.1.4.1.42767.64.1.1.3.1.9', INTEGER32, 11,
'1.3.6.1.4.1.42767.64.1.1.3.1.10', OBJECT_IDENTIFIER, 1.3.6.1.2.1.26.2.1.1.3.1.9,
'1.3.6.1.4.1.42767.64.1.1.3.1.11', COUNTER32, 10,
'1.3.6.1.4.1.42767.64.1.1.3.1.12', TIMETICKS, $curr_time,
'1.3.6.1.4.1.42767.64.1.1.3.1.13', INTEGER32, 2,
'1.3.6.1.4.1.42767.64.1.1.3.1.14', OCTET_STRING, ''
)

Thanks in advance for your help,
Ahm

Replies are listed 'Best First'.
Re: How to encode snmpv2 trap varbind
by VinsWorldcom (Prior) on Feb 25, 2013 at 02:12 UTC

    Are you trying to send SNMP (v2) traps? The Net::SNMP module does this for you without you needing to worry about the encoding yourself.

    I've done some decoding work with Net::SNMPTrapd, but for that I used Convert::ASN1.

    I would use Convert::ASN1 also for your task instead of the module you're currently trying with. The following works:

    use strict; use warnings; use Convert::ASN1; my $asn = Convert::ASN1->new; $asn->prepare(" varbind SEQUENCE OF SEQUENCE { oid OBJECT IDENTIFIER, choice CHOICE { val_integer INTEGER, val_string STRING, val_OID OBJECT IDENTIFIER, val_IpAddr [APPLICATION 0] STRING, val_Counter32 [APPLICATION 1] INTEGER, val_Guage32 [APPLICATION 2] INTEGER, val_TimeTicks [APPLICATION 3] INTEGER, val_Opaque [APPLICATION 4] STRING, val_Counter64 [APPLICATION 6] INTEGER } } "); my $pdu = $asn->encode( varbind => [ { oid => '1.3.6.1.2.1.1.3.0', choice => { val_TimeTicks => 600 } }, { oid => '1.3.6.1.6.3.1.1.4.1.0', choice => { val_OID => '1.3.6.1.4.1.42767.64.1.1.5.1.40.1' } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.9', choice => { val_integer => 11, } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.10', choice => { val_OID => '1.3.6.1.2.1.26.2.1.1.3.1.9', } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.11', choice => { val_Counter32 => 10, } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.12', choice => { val_TimeTicks => time() } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.13', choice => { val_integer => 2, } }, { oid => '1.3.6.1.4.1.42767.64.1.1.3.1.14', choice => { val_string => '' } } ] ); Convert::ASN1::asn_dump($pdu);

    And the output:

    VinsWorldcom@C:\Users\VinsWorldcom\tmp> perl test.pl 0000 186: SEQUENCE { 0003 14: SEQUENCE { 0005 8: OBJECT ID = 1.3.6.1.2.1.1.3.0 000F 2: [APPLICATION 3] 0011 : 02 58 __ __ __ __ __ __ __ __ __ __ __ __ __ __ .X 0013 : } 0013 29: SEQUENCE { 0015 10: OBJECT ID = 1.3.6.1.6.3.1.1.4.1.0 0021 15: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.5.1.40.1 0032 : } 0032 19: SEQUENCE { 0034 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.9 0044 1: INTEGER = 11 0047 : } 0047 30: SEQUENCE { 0049 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.10 0059 12: OBJECT ID = 1.3.6.1.2.1.26.2.1.1.3.1.9 0067 : } 0067 19: SEQUENCE { 0069 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.11 0079 1: [APPLICATION 1] 007B : 0A __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ . 007C : } 007C 22: SEQUENCE { 007E 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.12 008E 4: [APPLICATION 3] 0090 : 51 2A C7 73 __ __ __ __ __ __ __ __ __ __ __ __ Q*.s 0094 : } 0094 19: SEQUENCE { 0096 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.13 00A6 1: INTEGER = 2 00A9 : } 00A9 18: SEQUENCE { 00AB 14: OBJECT ID = 1.3.6.1.4.1.42767.64.1.1.3.1.14 00BB 0: STRING = '' 00BD : } 00BD : }

      Hi,

      For my testing, I needed to send source IP spoofed traps to SNMP
      manager (NMS). I am able to send traps now with some dirty way.
      I have used Net::SNMP module to send traps. Modified the IPTABLES rule to change the source ip of trap packets.

      #!/usr/bin/perl
      use lib '/opt/perl_64/lib/site_perl/5.8.8/';
      use strict;
      use warnings;
      use Net::SNMP qw(:ALL);
      my $curr_time = (scalar time);
      print "IPTABLES Rule inserted\n";
      `iptables -t nat -A POSTROUTING -d 10.10.70.14 -p udp --dport 5286 -j SNAT --to 10.10.16.230`;
      my ($session, $error) = Net::SNMP->session(
      -hostname => '10.10.70.14',
      -port => '5286',
      -localaddr => '192.168.10.121',
      -localport => '1028',
      -version => 'snmpv2c',
      -community => 'PUBLIC',
      );
      if (!defined($session)) {
      printf("ERROR: %s.\n", $error);
      exit 1;
      }

      my $result = $session->snmpv2_trap(
      -varbindlist => [
      '1.3.6.1.2.1.1.3.0', , TIMETICKS, 600,
      '1.3.6.1.6.3.1.1.4.1.0',OBJECT_IDENTIFIER,'1.3.6.1.4.1.42767.64.1.1.5.1.40.1',
      '1.3.6.1.4.1.42767.64.1.1.3.1.9', INTEGER32, 11,
      '1.3.6.1.4.1.42767.64.1.1.3.1.10', OBJECT_IDENTIFIER, 1.3.6.1.2.1.26.2.1.1.3.1.9,
      '1.3.6.1.4.1.42767.64.1.1.3.1.11', COUNTER32, 10,
      '1.3.6.1.4.1.42767.64.1.1.3.1.12', TIMETICKS, $curr_time,
      '1.3.6.1.4.1.42767.64.1.1.3.1.13', INTEGER32, 2,
      '1.3.6.1.4.1.42767.64.1.1.3.1.14', OCTET_STRING, '' ]
      );

      if (!defined($result)) {
      printf("ERROR: %s.\n", $session->error());
      }
      else {
      printf("SNMPv2-Trap-PDU sent.\n");
      }

      $session->close();
      `iptables -t nat -D POSTROUTING -d 10.10.70.14 -p udp --dport 5286 -j SNAT --to 10.10.16.230`;
      print "IPTABLES rules removed\n";

        Are you sure they have to be spoofed?

        The reason I ask is because there may be a simpler way to accomplish this. Most network monitoring systems (unless they're brain-damaged) support SNMP-COMMUNITY-MIB::snmpTrapAddress (1.3.6.1.6.3.18.1.3 with a .0 as your instance identifier). This is an SNMPv2 varbind that you can pass that contains an IP address to signify that the NMS should treat that as the originating SNMP source (commonly used by SNMP trap relays and aggregators). The docs on it noted that it should be the second varbind sent after the sysUptime (http://tools.ietf.org/html/rfc2576).

        This variable serves roughly the same purpose as the agent-addr value in SNMPv1 traps. In fact, if your NMS supports SNMPv1, using that and setting agent-addr should be another viable option.

        I've used both of the above methods successfully to "spoof" traps to multiple NMS's in the past. It works correctly on nearly all of them. In fact, if any of them fail to treat the trap as if it had come from the snmpTrapAddress/agent-addr, I'd recommend filing a bug with the developer and get them to fix their application.

        I'd definitely recommend giving this a try. It may simplify things a great deal for you, and save you from the hassle and complexity of packet-level spoofing.

        If needed, I might be able to dig up some (working) code I've used to accomplish the above; however, I was using the Net-SNMP project's SNMP perl module (not Net::SNMP), so the syntax is quite different.

Re: How to encode snmpv2 trap varbind
by Anonymous Monk on Feb 24, 2013 at 09:02 UTC
Re: How to encode snmpv2 trap varbind
by topher (Scribe) on Feb 24, 2013 at 20:10 UTC

    Can you show us what you've tried so far, or what issues you're running into?

    Also, can you give us a little more background on what you're trying to do? I've sent SNMP traps from Perl before, but I've never used Encoding::BER; it's possible there may be an alternate way of accomplishing what you're trying to do that may be easier.