#!/usr/bin/perl
# ============================================================================
# $Id$
# Derek Gassen
# Script to monitor flow specification ( flow-spec ) route filters
# via an snmp poll.
# parses the __dynamic_default_inet__ juniper filter using
# the appropriate OIDs and totals up all active peer and transit
# DoS mitigations. Doesn't use Net::SNMP's non-block'g.
#
# Taken out of dtown's cpan table.pl example. Diff with
# http://search.cpan.org/src/DTOWN/Net-SNMP-5.2.0/examples/table.pl
# to see changes from the original.
# Copyright (c) 2000-2002 David M. Town
# All rights reserved.
# This program is free software; you may redistribute it and/or modify it
# under the same terms as Perl itself.
# ============================================================================
use strict;
use Data::Dumper;
use Net::SNMP;
use POSIX qw(strftime);
my ($fwPacketOid,$fwPacketCount,%rtrPacketCount,%totalCounts,$curRtr,$now);
$now=strftime "%y%m%e%H%M", localtime;
open (PEERTRAN, "< /pathname/juniper.peer")||die "router list is missing!: ", $!;
while (){
chomp;
$curRtr = lc($_);
($fwPacketCount) = getRtrCount($curRtr);
foreach (keys %{$fwPacketCount}){
$rtrPacketCount{$curRtr."|".$_."|".$now}+=$fwPacketCount->{$_};
$totalCounts{$_."|".$now}+=$fwPacketCount->{$_};
}
}
print "Total flowspec DDoS mitigation:\n";
foreach (keys %totalCounts){
printf("%s:\t%10d\n", $_, $totalCounts{$_});
}
# dump some hashes for reference
open (BYRTR, ">> /pathname/FSCounts.o")||die "Can't write to FSCounts.o transaction log: ",$!;
print BYRTR Dumper(\%totalCounts);
print BYRTR Dumper(\%rtrPacketCount);
close (BYRTR);
sub getRtrCount {
my $router = $_[0];
print "working on: $router\n";
# Create the SNMP session
my ($session, $error) = Net::SNMP->session(
-hostname => $router,
-community => 'public',
-port => 161,
-maxmsgsize=> 16384,
-version => 'snmpv2c'
);
# Was the session created?
if (!defined($session)) {
printf("ERROR: %s.\n", $error);
exit 1;
}
# show firewall family filter __dynamic_default_inet__
my $ifTable = '1.3.6.1.4.1.2636.3.5.2.1.7.24.95.95.100.121.110.97.109.105.99.95.100.101.102.97.117.108.116.95.105.110.101.116.95.95';
my ($result,$fwInvert,$fwPacket,%fwPacketOid,%fwFSName,%fsCount);
if (defined($result = $session->get_table(-baseoid => $ifTable))) {
%{$fwInvert}=reverse%{$result}; # invert hash to name->oid
foreach (keys(%{$fwInvert})) {
# stick your flowspec routes to ignore filter list here.
next if m@^1\.2\.3.4,2\.3\.4\.5,proto=17@; # some weird route
next if m@proto=1,=6@; # don't care about this one
next if m@^[^.]+(?:\.[^.]+){3},\*,proto=6,dstport=80@; # more weirdness
$fwPacketOid{$_}=$fwInvert->{$_};
$fwPacketOid{$_}=~s@(2636\.3\.5\.2\.1)\.7@$1.4@;
}
} else {
printf("ERROR: %s.\n\n", $session->error());
}
undef $session;
# Create the SNMP session
my ($session, $error) = Net::SNMP->session(
-hostname => $ARGV[0] || $router,
-community => $ARGV[1] || 'public',
-port => $ARGV[2] || 161,
-maxmsgsize=> 16384,
-version => 'snmpv2c'
);
# Was the session created?
if (!defined($session)) {
printf("ERROR: %s.\n", $error);
exit 1;
}
$ifTable=~s@(2636\.3\.5\.2\.1)\.7@$1.4@;
if (!defined($result = $session->get_table(-baseoid => $ifTable))) {print "Error can't get packet counts!\n"};
foreach (keys(%fwPacketOid)){
printf("%s => %s\n", $_, $result->{$fwPacketOid{$_}});
$fsCount{$_}=$result->{$fwPacketOid{$_}};
}
$session->close;
return \%fsCount;
}