سؤال

قبل بضعة أسابيع، كتبت Relayer SNMP لمجموعة OPS الخاصة بنا. لديهم بعض الأجهزة الغبية التي يمكن أن ترسل الفخاخ فقط إلى IP واحد، ولدينا نظام مراقبة يستمع إلى IPS متعددة مقابل التوافر. كود ميت بسيط، وأساسيا:

while (recv($packet)) {
  foreach $target (@targets) {
    send($target, $packet);
  }
}

إنه يعمل، أساسا، ولكن الآن القادم القصير الواضح أنه لا يشمل IP المنشئ هو مشكلة (على ما يبدو تضمنت الدرجة الأولى من الجهاز المعلومات كبراويند وبعض الفئة الجديدة لا).

ما أود القيام به هو تغيير التعليمات البرمجية الخاصة بي إلى شيء مثل هذا:

while ($server->recv($packet)) {
  my $obj = decompile($packet)
  if (!$obj->{varbind}{snmpTrapAddress}) {
    $obj->{varbind}{snmpTrapAddress} = inet_ntoa($server->peeraddr());
  }
  $packet = compile($obj);
  foreach $target (@targets) {
    send($target, $packet);
  }
}

بمعنى آخر، إذا كان المرسل الخاص بي لا يشمل SNMPTRAPADDRESS، أضفه. المشكلة هي أن كل حزمة SNMP التي نظرت إليها ل Perl تبدو تركز بشدة للغاية على البنية التحتية لآخاخ الاستقبال والحصول على الأداء.

هكذا: هل هناك وحدة بيضاء بسيطة تسمح لي أن أقول "إليك شريط بيانات تمثل فخ SNMP. فك شفرة ذلك في شيء يمكنني التعامل معه بسهولة، ثم إعادة ترجمةها مرة أخرى في Blob يمكنني رمي عبر الشبكة"؟

إذا كانت الإجابة التي تعطيها هي "استخدام SNMP Dummy"، فهل يمكنك تقديم أمثلة على هذا؟ قد أكون أعمى، ولكن من إخراج بيرلدوك SNMP. ليس من الواضح لي كيفية استخدامه بهذه الطريقة.

تعديل:

اتضح بعد النظر حول بعض الشيء أن "ترميز SNMP" هو حقا asn.1 ber (قواعد الترميز الأساسية). بناء على ذلك أذهب مع تحويل :: BER. ما زلت أرحب بأي نصائح سهلة استراحة / تحرير / إعادة بنائها ل SNMP.

هل كانت مفيدة؟

المحلول

لم أجد أبدا حلا مثاليا لهذا. NET :: SNMP :: رسالة (جزء من نت :: SNMP.) قد تسمح بذلك ولكن لا يبدو أن لديها واجهة محددة عامة، ولم يكن أي من الشبكة :: واجهة SNMP ذات صلة خاصة. nsnmp. هو الأقرب إلى روح ما كنت أبحث عنه، لكنه هش ولم يعمل من أجل حزمتي خارج الصندوق وإذا كنت سأؤيد رمز هش، سيكون رمز هش الخاص بي =).

الاثنين :: SNMP. اقترب أيضا ما كنت أبحث عنه، ولكن تم كسره أيضا من الصندوق. يبدو أنه مهجور، مع الإصدار الأخير في عام 2001 والإصدار الأخير ل CPAN للمطور في عام 2002. لم أكن أدرك ذلك في ذلك الوقت، لكنني أعتقد الآن أنه مكسور بسبب تغيير في الواجهة للتحويل :: BER الوحدة التي يستخدمها.

الاثنين :: SNMP حصلت لي أشار نحو تحويل :: BER.. وبعد بضعة آلاف من قراءات التحويل :: PD Pod، The Mon :: SNMP، و RFC 1157. (ESP. 4.1.6، "trap-pdu") في وقت لاحق وقد توصلت إلى هذا الرمز كدليل على المفهوم للقيام بما أردت. هذا هو مجرد دليل على المفهوم (لأسباب سأفصل بعد الكود) لذلك قد لا يكون مثاليا، لكنني اعتقدت أنه قد يوفر مرجع مفيد للأشخاص الذين يعملون في المستقبل في هذا المجال، حتى هنا هو:

#!/usr/bin/perl

use Convert::BER;
use Convert::BER qw(/^(\$|BER_)/);

my $ber = Convert::BER->new();

# OID I want to add to the trap if not already present
my $snmpTrapAddress = '1.3.6.1.6.3.18.1.3';

# this would be from the incoming socket in production
my $source_ip = '10.137.54.253';

# convert the octets into chars to match SNMP standard for IPs
my $source_ip_str = join('', map { chr($_); } split(/\./, $source_ip));

# Read the binary trap data from STDIN or ARGV.  Normally this would
# come from the UDP receiver
my $d = join('', <>);

# Stuff my trap data into $ber
$ber->buffer($d);

print STDERR "Original packet:\n";
$ber->dump();

# Just decode the first two fields so we can tell what version we're dealing with
$ber->decode(
                SEQUENCE => [
                    INTEGER => \$version,
                    STRING => \$community,
                    BER => \$rest_of_trap,
                ],
) || die "Couldn't decode packet: ".$ber->error()."\n";

if ($version == 0) {
  #print STDERR "This is a version 1 trap, proceeding\n";

  # decode the PDU up to but not including the VARBINDS
  $rest_of_trap->decode(
    [ SEQUENCE => BER_CONTEXT | BER_CONSTRUCTOR | 0x04 ] =>
      [
        OBJECT_ID => \$enterprise_oid,
        [ STRING => BER_APPLICATION | 0x00 ] => \$agentaddr,
        INTEGER => \$generic,
        INTEGER => \$specific,
        [ INTEGER => BER_APPLICATION | 0x03 ] => \$timeticks,
        SEQUENCE => [ BER => \$varbind_ber, ],
      ],
  ) || die "Couldn't decode packet: ".$extra->error()."\n";;

  # now decode the actual VARBINDS (just the OIDs really, to decode the values
  # We'd have to go to the MIBs, which I neither want nor need to do
  my($r, $t_oid, $t_val, %varbinds);
  while ($r = $varbind_ber->decode(
    SEQUENCE => [
      OBJECT_ID => \$t_oid,
      ANY       => \$t_val,
    ], ))
  {
    if (!$r) {
      die "Couldn't decode SEQUENCE: ".$extra->error()."\n";
    }
    $varbinds{$t_oid} = $t_val;
  }

  if ($varbinds{$snmpTrapAddress} || $varbinds{"$snmpTrapAddress.0"}) {
    # the original trap already had the data, just print it back out
    print $d;
  } else {
    # snmpTrapAddress isn't present, create a new object and rebuild the packet
    my $new_trap = new Convert::BER;
    $new_trap->encode(
      SEQUENCE => [
        INTEGER => $version,
        STRING => $community,
        [ SEQUENCE => BER_CONTEXT | BER_CONSTRUCTOR | 0x04 ] =>
          [
            OBJECT_ID => $enterprise_oid,
            [ STRING => BER_APPLICATION | 0x00 ] => $agentaddr,
            INTEGER => $generic,
            INTEGER => $specific,
            [ INTEGER => BER_APPLICATION | 0x03 ] => $timeticks,
            SEQUENCE => [
              BER => $varbind_ber,
              # this next oid/val is the only mod we should be making
              SEQUENCE => [
                OBJECT_ID => "$snmpTrapAddress.0",
                [ STRING => BER_APPLICATION | 0x00 ] => $source_ip_str,
              ],
            ],
          ],
      ],
    );
    print STDERR "New packet:\n";
    $new_trap->dump();
    print $new_trap->buffer;
  }
} else {
  print STDERR "I don't know how to decode non-v1 packets yet\n";
  # send back the original packet
  print $d;  
}

لذلك، هذا كل شيء. ها هي كيكر. اتخذت OPS على كلمتها التي لم يتمكنها من الحصول على IP من المرسل الأصلي في الفخ. أثناء العمل من خلال هذا المثال، وجدت أنه، في المثال على الأقل أعطاني، كان IP الأصلي في حقل الوكيل - Addr في الفخ. بعد إظهار ذلك، وإطالته في API للأداة باستخدام ذلك يتعرض قد تم إيقاف تشغيله لمحاولة إجراء التغيير في نهايته. أشعر بالإحذارات من التعليمات البرمجية أعلاه في الوقت المناسب الذي يسألني عن شيء ما أحتاج إليه بالفعل إلى الوحل في الحزمة، ولكن في الوقت الراهن، ستبقى أعلاه دليل غير مختبر غير واضح على رمز المفهوم. آمل أن يساعد شخص ما يوما ما.

نصائح أخرى

هل جربت nsnmp.?

بالتأكيد تحقق من snmp_session.

http://code.google.com/p/snmp-sessession/

تأكد من اتباع الروابط إلى موقع التوزيع القديم الذي يحتوي على عدة أمثلة.

لقد سافرت أساسا نفس المسار من خلال Mon :: SNMP، تحويل :: BER، TCP / IP المصور، إلخ. SNMP_SESSES هو الشيء الوحيد الذي تمكنت من عمل العمل. من خلال العمل، أقصد قبول فخ SNMP على منفذ UDP 162 ويقوم بفك تشفيرها في معادلات السلسلة لتسجيل الدخول دون إعادة اختراع العديد من العجلات. أنا فقط أستخدم وظيفة تلقي فخ لكنني أعتقد أنه قد يفعل ما تريد أيضا.

إنه على رمز Google، وليس CPAN على الرغم من ذلك، فمن الصعب بعض الشيء العثور عليه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top