From c3de1fc555a1bd6cd460fe511286a91bb73ba43d Mon Sep 17 00:00:00 2001 From: Jordi Sanfeliu Date: Mon, 16 Feb 2015 18:00:45 +0100 Subject: [PATCH] Added support for IPv6 in 'ports' graph using protocols 'tcp6', 'upd6' and/or 'all6'. Note that 'ip6tables' command line is needed. #67 --- lib/Monitorix.pm | 39 +++++++++++++++++++++++++++ lib/port.pm | 55 ++++++++++++++++++++++++++------------- man/man5/monitorix.conf.5 | 8 ++++-- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/lib/Monitorix.pm b/lib/Monitorix.pm index 1c4fc72..514f815 100644 --- a/lib/Monitorix.pm +++ b/lib/Monitorix.pm @@ -317,6 +317,8 @@ sub flush_accounting_rules { logger("Flushing out iptables rules.") if $debug; { my @names; + + # IPv4 if(open(IN, "iptables -t $table -nxvL INPUT --line-numbers |")) { my @rules; while() { @@ -351,6 +353,43 @@ sub flush_accounting_rules { foreach(@names) { system("iptables -t $table -X $_"); } + + # IPv6 + undef(@names); + if(open(IN, "ip6tables -t $table -nxvL INPUT --line-numbers |")) { + my @rules; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /monitorix_IN/ || /monitorix_OUT/ || /monitorix_nginx_IN/) { + push(@rules, $rule); + push(@names, $name); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("ip6tables -t $table -D INPUT $_"); + $num++; + } + } + if(open(IN, "ip6tables -t $table -nxvL OUTPUT --line-numbers |")) { + my @rules; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /monitorix_IN/ || /monitorix_OUT/ || /monitorix_nginx_IN/) { + push(@rules, $rule); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("ip6tables -t $table -D OUTPUT $_"); + $num++; + } + } + foreach(@names) { + system("ip6tables -t $table -X $_"); + } } if(open(IN, "iptables -t $table -nxvL FORWARD --line-numbers |")) { my @rules; diff --git a/lib/port.pm b/lib/port.pm index 04f3113..7c25dd9 100644 --- a/lib/port.pm +++ b/lib/port.pm @@ -33,6 +33,7 @@ sub port_init { my ($package, $config, $debug) = @_; my $rrd = $config->{base_lib} . $package . ".rrd"; my $port = $config->{port}; + my $cmd; my $info; my @ds; @@ -140,16 +141,21 @@ sub port_init { } if($pl[$n] && $np) { my $p = trim(lc((split(',', $port->{desc}->{$pl[$n]}))[1])) || "all"; + $cmd = "iptables"; + if(grep {$_ eq $p} ("tcp6", "udp6", "all6")) { + $cmd = "ip6tables"; + $p =~ s/6//; + } my $conn = trim(lc((split(',', $port->{desc}->{$pl[$n]}))[2])); if($conn eq "in" || $conn eq "in/out") { - system("iptables -t $table -N monitorix_IN_$n 2>/dev/null"); - system("iptables -t $table -I INPUT -p $p --sport 1024:65535 --dport $np -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j monitorix_IN_$n -c 0 0"); - system("iptables -t $table -I OUTPUT -p $p --sport $np --dport 1024:65535 -m conntrack --ctstate ESTABLISHED,RELATED -j monitorix_IN_$n -c 0 0"); + system("$cmd -t $table -N monitorix_IN_$n 2>/dev/null"); + system("$cmd -t $table -I INPUT -p $p --sport 1024:65535 --dport $np -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j monitorix_IN_$n -c 0 0"); + system("$cmd -t $table -I OUTPUT -p $p --sport $np --dport 1024:65535 -m conntrack --ctstate ESTABLISHED,RELATED -j monitorix_IN_$n -c 0 0"); } if($conn eq "out" || $conn eq "in/out") { - system("iptables -t $table -N monitorix_OUT_$n 2>/dev/null"); - system("iptables -t $table -I INPUT -p $p --sport $np --dport 1024:65535 -m conntrack --ctstate ESTABLISHED,RELATED -j monitorix_OUT_$n -c 0 0"); - system("iptables -t $table -I OUTPUT -p $p --sport 1024:65535 --dport $np -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j monitorix_OUT_$n -c 0 0"); + system("$cmd -t $table -N monitorix_OUT_$n 2>/dev/null"); + system("$cmd -t $table -I INPUT -p $p --sport $np --dport 1024:65535 -m conntrack --ctstate ESTABLISHED,RELATED -j monitorix_OUT_$n -c 0 0"); + system("$cmd -t $table -I OUTPUT -p $p --sport 1024:65535 --dport $np -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j monitorix_OUT_$n -c 0 0"); } if($conn ne "in" && $conn ne "out" && $conn ne "in/out") { logger("$myself: Invalid connection type '$conn'; must be 'in', 'out' or 'in/out'."); @@ -166,6 +172,7 @@ sub port_init { if($pl[$n] && $np) { my $p = lc((split(',', $port->{desc}->{$pl[$n]}))[1]) || "all"; # in/out not supported yet FIXME + $p =~ s/6//; # tcp6, udp6, ... not supported system("ipfw -q add $port->{rule} count $p from me $np to any"); system("ipfw -q add $port->{rule} count $p from any to me $np"); } @@ -194,21 +201,29 @@ sub port_update { my $rrdata = "N"; if($config->{os} eq "Linux") { + my @data; + my $l; + open(IN, "iptables -t $table -nxvL INPUT |"); - while() { + @data = ; + close(IN); + open(IN, "ip6tables -t $table -nxvL INPUT |"); + push(@data, ); + close(IN); + for($l = 0; $l < scalar(@data); $l++) { for($n = 0; $n < $port->{max}; $n++) { $i_in[$n] = 0 unless $i_in[$n]; $o_in[$n] = 0 unless $o_in[$n]; - if(/ monitorix_IN_$n /) { - my (undef, $bytes) = split(' ', $_); + if($data[$l] =~ / monitorix_IN_$n /) { + my (undef, $bytes) = split(' ', $data[$l]); chomp($bytes); $i_in[$n] = $bytes - ($config->{port_hist_i_in}[$n] || 0); $i_in[$n] = 0 unless $i_in[$n] != $bytes; $config->{port_hist_i_in}[$n] = $bytes; $i_in[$n] /= 60; } - if(/ monitorix_OUT_$n /) { - my (undef, $bytes) = split(' ', $_); + if($data[$l] =~ / monitorix_OUT_$n /) { + my (undef, $bytes) = split(' ', $data[$l]); chomp($bytes); $o_in[$n] = $bytes - ($config->{port_hist_o_in}[$n] || 0); $o_in[$n] = 0 unless $o_in[$n] != $bytes; @@ -217,22 +232,26 @@ sub port_update { } } } - close(IN); open(IN, "iptables -t $table -nxvL OUTPUT |"); - while() { + @data = ; + close(IN); + open(IN, "ip6tables -t $table -nxvL OUTPUT |"); + push(@data, ); + close(IN); + for($l = 0; $l < scalar(@data); $l++) { for($n = 0; $n < $port->{max}; $n++) { $o_out[$n] = 0 unless $o_out[$n]; $i_out[$n] = 0 unless $i_out[$n]; - if(/ monitorix_OUT_$n /) { - my (undef, $bytes) = split(' ', $_); + if($data[$l] =~ / monitorix_OUT_$n /) { + my (undef, $bytes) = split(' ', $data[$l]); chomp($bytes); $o_out[$n] = $bytes - ($config->{port_hist_o_out}[$n] || 0); $o_out[$n] = 0 unless $o_out[$n] != $bytes; $config->{port_hist_o_out}[$n] = $bytes; $o_out[$n] /= 60; } - if(/ monitorix_IN_$n /) { - my (undef, $bytes) = split(' ', $_); + if($data[$l] =~ / monitorix_IN_$n /) { + my (undef, $bytes) = split(' ', $data[$l]); chomp($bytes); $i_out[$n] = $bytes - ($config->{port_hist_i_out}[$n] || 0); $i_out[$n] = 0 unless $i_out[$n] != $bytes; @@ -241,7 +260,6 @@ sub port_update { } } } - close(IN); } if(grep {$_ eq $config->{os}} ("FreeBSD", "OpenBSD", "NetBSD")) { my @pl = split(',', $port->{list}); @@ -476,6 +494,7 @@ sub port_cgi { $pl[$n] = trim($pl[$n]); my $pn = trim((split(',', $port->{desc}->{$pl[$n]}))[0]); my $pp = trim((split(',', $port->{desc}->{$pl[$n]}))[1]); + $pp =~ s/6//; my $prig = trim((split(',', $port->{desc}->{$pl[$n]}))[3]); my $plim = trim((split(',', $port->{desc}->{$pl[$n]}))[4]); @riglim = @{setup_riglim($prig, $plim)}; diff --git a/man/man5/monitorix.conf.5 b/man/man5/monitorix.conf.5 index 8497621..7c0737e 100644 --- a/man/man5/monitorix.conf.5 +++ b/man/man5/monitorix.conf.5 @@ -1258,7 +1258,7 @@ It will receive the following three parameters: Default value: \fI/path/to/script.sh\fP .RE .SS Network port traffic (port.rrd) -This graph requires the \fIiptables\fP(8) command on Linux systems and the \fIipfw\fP command on *BSD systems. +This graph requires the \fIiptables\fP(8) command and optionally the \fIip6tables\fP(8) command on Linux systems and the \fIipfw\fP command on *BSD systems. .P .BI max .RS @@ -1283,13 +1283,17 @@ If you see a red color in the background of a network port graph, it means that .P .BI desc .RS -This is the option where each network port specified in \fBlist\fP is described. Each port definition consists of five parameters separated by comma: the port description, the network protocol, the connection type (\fIin\fP, \fIout\fP or \fIin/out\fP) and the rigid and limit values. +This is the option where each network port specified in \fBlist\fP is described. Each port definition consists of five parameters separated by comma: the port description, the network protocol (\fItcp\fP, \fIudp\fP or \fIall\fP for all protocols), the connection type (\fIin\fP, \fIout\fP or \fIin/out\fP) and the rigid and limit values. +.P +There is also support (Linux only) for IPv6 network ports activity by using protocol names as \fItcp6\fP, \fIudp6\fP and \fIall6\fP. .P An example would be: .RS .br 25 = SMTP, tcp, in/out, 0, 1000 +.br + 25 = SMTP, tcp6, in/out, 0, 1000 .br 80 = HTTP, tcp, in, 0, 1000 .br