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
|
- libdbd-sqlite3-perl
|
||||||
- one or more routers than can generate NetFlow v8/v9 AS aggregation records
|
- one or more routers than can generate NetFlow v8/v9 AS aggregation records
|
||||||
or sFlow samples
|
or sFlow samples
|
||||||
|
- ip2as.pm, for additional lookup (https://github.com/JackSlateur/perl-ip2as)
|
||||||
|
|
||||||
Considerations
|
Considerations
|
||||||
-------------
|
-------------
|
||||||
|
@ -12,6 +12,7 @@ use IO::Socket;
|
|||||||
use RRDs;
|
use RRDs;
|
||||||
use Getopt::Std;
|
use Getopt::Std;
|
||||||
use Scalar::Util qw(looks_like_number);
|
use Scalar::Util qw(looks_like_number);
|
||||||
|
use ip2as;
|
||||||
|
|
||||||
my %knownlinks;
|
my %knownlinks;
|
||||||
my %link_samplingrates;
|
my %link_samplingrates;
|
||||||
@ -39,7 +40,7 @@ my $v10_templates = {};
|
|||||||
my $sflow_server_port = 6343;
|
my $sflow_server_port = 6343;
|
||||||
|
|
||||||
use vars qw/ %opt /;
|
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".
|
my $usage = "$0 [-rpPka]\n".
|
||||||
"\t-r <path to RRD files>\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(-P <sFlow UDP listen port - default $sflow_server_port, use 0 to disable sFlow)\n".
|
||||||
"\t-k <path to known links file>\n".
|
"\t-k <path to known links file>\n".
|
||||||
"\t-a <your own AS number> - only required for sFlow\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 $rrdpath = $opt{'r'};
|
||||||
my $knownlinksfile = $opt{'k'};
|
my $knownlinksfile = $opt{'k'};
|
||||||
my $myas_opt = $opt{'a'};
|
my $myas_opt = $opt{'a'};
|
||||||
my $peerasstats = $opt{'n'};
|
my $peerasstats = $opt{'n'};
|
||||||
|
my $mapping = $opt{'m'};
|
||||||
|
|
||||||
die("$usage") if (!defined($rrdpath) || !defined($knownlinksfile));
|
die("$usage") if (!defined($rrdpath) || !defined($knownlinksfile));
|
||||||
|
|
||||||
@ -129,6 +132,13 @@ if ($sflow_server_port > 0) {
|
|||||||
|
|
||||||
my ($him,$datagram,$flags);
|
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
|
# main datagram receive loop
|
||||||
while (1) {
|
while (1) {
|
||||||
while (my @ready = $sel->can_read) {
|
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 {
|
sub parse_netflow_v5 {
|
||||||
my $datagram = shift;
|
my $datagram = shift;
|
||||||
my $ipaddr = shift;
|
my $ipaddr = shift;
|
||||||
@ -173,8 +195,14 @@ sub parse_netflow_v5 {
|
|||||||
for (my $i = 0; $i < $count; $i++) {
|
for (my $i = 0; $i < $count; $i++) {
|
||||||
my $flowrec = substr($datagram, $v5_header_len + ($i*$v5_flowrec_len), $v5_flowrec_len);
|
my $flowrec = substr($datagram, $v5_header_len + ($i*$v5_flowrec_len), $v5_flowrec_len);
|
||||||
my @flowdata = unpack("NNNnnNNNNnnccccnnccN", $flowrec);
|
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";
|
my $srcip = join '.', unpack 'C4', pack 'N', $flowdata[0];
|
||||||
handleflow($ipaddr, $flowdata[6], $flowdata[15], $flowdata[16], $flowdata[3], $flowdata[4], 4, 'netflow');
|
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),
|
# Outbound packets have our AS number as the source (GatewayAsSource),
|
||||||
# while inbound packets have 0 as the destination (empty AsPath).
|
# while inbound packets have 0 as the destination (empty AsPath).
|
||||||
# Transit packets have "foreign" AS numbers for both source and
|
# Transit packets have "foreign" AS numbers for both source and
|
||||||
|
Loading…
x
Reference in New Issue
Block a user