mirror of
https://github.com/manuelkasper/AS-Stats.git
synced 2025-02-20 11:44:12 +08:00
Merge pull request #67 from JackSlateur/master
Support optional IP to ASN mapping for netflow v5 / sFlow
This commit is contained in:
commit
5b1f2af37a
@ -45,6 +45,7 @@ Prerequisites
|
||||
- libdbd-sqlite3-perl
|
||||
- one or more routers than can generate NetFlow v8/v9 AS aggregation records
|
||||
or sFlow samples
|
||||
- ip2as.pm, for additional lookup (https://github.com/JackSlateur/perl-ip2as)
|
||||
|
||||
Considerations
|
||||
-------------
|
||||
|
@ -12,6 +12,7 @@ use IO::Socket;
|
||||
use RRDs;
|
||||
use Getopt::Std;
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
use ip2as;
|
||||
|
||||
my %knownlinks;
|
||||
my %link_samplingrates;
|
||||
@ -39,7 +40,7 @@ my $v10_templates = {};
|
||||
my $sflow_server_port = 6343;
|
||||
|
||||
use vars qw/ %opt /;
|
||||
getopts('r:p:P:k:a:n', \%opt);
|
||||
getopts('r:p:P:k:a:nm:', \%opt);
|
||||
|
||||
my $usage = "$0 [-rpPka]\n".
|
||||
"\t-r <path to RRD files>\n".
|
||||
@ -47,12 +48,14 @@ my $usage = "$0 [-rpPka]\n".
|
||||
"\t(-P <sFlow UDP listen port - default $sflow_server_port, use 0 to disable sFlow)\n".
|
||||
"\t-k <path to known links file>\n".
|
||||
"\t-a <your own AS number> - only required for sFlow\n".
|
||||
"\t-n enable peer-as statistics\n";
|
||||
"\t-n enable peer-as statistics\n".
|
||||
"\t-m IP<->ASN mapping\n";
|
||||
|
||||
my $rrdpath = $opt{'r'};
|
||||
my $knownlinksfile = $opt{'k'};
|
||||
my $myas_opt = $opt{'a'};
|
||||
my $peerasstats = $opt{'n'};
|
||||
my $mapping = $opt{'m'};
|
||||
|
||||
die("$usage") if (!defined($rrdpath) || !defined($knownlinksfile));
|
||||
|
||||
@ -129,6 +132,13 @@ if ($sflow_server_port > 0) {
|
||||
|
||||
my ($him,$datagram,$flags);
|
||||
|
||||
if (defined($mapping)) {
|
||||
ip2as::init($mapping);
|
||||
} else {
|
||||
#I don't use the mapping, to use an empty one
|
||||
ip2as::init('/dev/null');
|
||||
}
|
||||
|
||||
# main datagram receive loop
|
||||
while (1) {
|
||||
while (my @ready = $sel->can_read) {
|
||||
@ -160,6 +170,18 @@ while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
sub replace_asn {
|
||||
my $ip = shift;
|
||||
my $asn = shift;
|
||||
|
||||
my $new_asn = ip2as::getas4ip($ip);
|
||||
if (defined($new_asn)) {
|
||||
return $new_asn;
|
||||
} else {
|
||||
return $asn;
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_netflow_v5 {
|
||||
my $datagram = shift;
|
||||
my $ipaddr = shift;
|
||||
@ -173,8 +195,14 @@ sub parse_netflow_v5 {
|
||||
for (my $i = 0; $i < $count; $i++) {
|
||||
my $flowrec = substr($datagram, $v5_header_len + ($i*$v5_flowrec_len), $v5_flowrec_len);
|
||||
my @flowdata = unpack("NNNnnNNNNnnccccnnccN", $flowrec);
|
||||
#print "ipaddr: " . inet_ntoa($ipaddr) . " octets: $flowdata[6] srcas: $flowdata[15] dstas: $flowdata[16] in: $flowdata[3] out: $flowdata[4] 4 \n";
|
||||
handleflow($ipaddr, $flowdata[6], $flowdata[15], $flowdata[16], $flowdata[3], $flowdata[4], 4, 'netflow');
|
||||
my $srcip = join '.', unpack 'C4', pack 'N', $flowdata[0];
|
||||
my $dstip = join '.', unpack 'C4', pack 'N', $flowdata[1];
|
||||
|
||||
my $srcas = replace_asn($srcip, $flowdata[15]);
|
||||
my $dstas = replace_asn($dstip, $flowdata[16]);
|
||||
|
||||
#print "ipaddr: " . inet_ntoa($ipaddr) . " octets: $flowdata[6] srcas: $srcas dstas: $dstas in: $flowdata[3] out: $flowdata[4] 4 \n";
|
||||
handleflow($ipaddr, $flowdata[6], $srcas, $dstas, $flowdata[3], $flowdata[4], 4, 'netflow');
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,6 +591,42 @@ sub parse_sflow {
|
||||
}
|
||||
}
|
||||
|
||||
# Extract src & dst IP from packet's header
|
||||
my $srcip = undef;
|
||||
my $dstip= undef;
|
||||
my (undef, $ethertype, $ipdata) = unpack('a12H4a*', $sFlowSample->{'HeaderBin'});
|
||||
if($ethertype eq '8100'){
|
||||
(undef, $ethertype, $ipdata) = unpack('nH4a*', $ipdata);
|
||||
}
|
||||
|
||||
if($ethertype eq '0800'){
|
||||
(undef, undef, undef, $srcip, $dstip) = unpack('nnB64NN', $ipdata);
|
||||
$srcip = join '.', unpack 'C4', pack 'N', $srcip;
|
||||
$dstip = join '.', unpack 'C4', pack 'N', $dstip;
|
||||
}
|
||||
|
||||
if($ethertype eq '86dd'){
|
||||
(undef, $sFlowSample->{HeaderDatalen}, undef, $srcip, $dstip) = unpack('NnnB128B128', $ipdata);
|
||||
my @array_src = ( $srcip =~ m/......../g );
|
||||
my @array_dst = ( $dstip =~ m/......../g );
|
||||
$srcip = '';
|
||||
$dstip = '';
|
||||
for(my $x = 0; $x < scalar @array_src; $x = $x + 2){
|
||||
$srcip .= sprintf("%02x%02x:", oct("0b$array_src[$x]"), oct("0b$array_src[$x + 1]"));
|
||||
}
|
||||
chop($srcip);
|
||||
|
||||
for(my $x = 0; $x < scalar @array_dst; $x = $x + 2){
|
||||
$dstip .= sprintf("%02x%02x:", oct("0b$array_dst[$x]"), oct("0b$array_dst[$x + 1]"));
|
||||
}
|
||||
chop($dstip);
|
||||
}
|
||||
|
||||
if (defined($srcip) && defined($dstip)){
|
||||
$srcas = replace_asn($srcip, $srcas);
|
||||
$dstas = replace_asn($dstip, $dstas);
|
||||
}
|
||||
|
||||
# Outbound packets have our AS number as the source (GatewayAsSource),
|
||||
# while inbound packets have 0 as the destination (empty AsPath).
|
||||
# Transit packets have "foreign" AS numbers for both source and
|
||||
|
Loading…
x
Reference in New Issue
Block a user