����JFIF��x�x����'
| Server IP : 78.140.185.180 / Your IP : 216.73.216.168 Web Server : LiteSpeed System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64 User : builderbox ( 1072) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /proc/1630575/root/proc/self/root/proc/self/root/lib64/nagios/plugins/extra/ |
Upload File : |
#! /usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;
use JSON::PP qw(decode_json);
use IPC::Open3 qw(open3);
use Symbol qw(gensym);
use constant REFERENCE_FILE => '/etc/icinga2/plinc/fw_rules';
sub usage {
print sprintf( <<"EOF", REFERENCE_FILE );
Usage:
$0 --backend iptables|nft [-i 'rule1' -i 'rule2' -i 'rule3'] [--save]
-b|--backend use the specified firewall
-s|--save save current rules to %s
-i|--ignore ignor firewall rule
support usage placeholder %%word (eq (\\S+\\h*)+ regexp)
Examples:
$0 -b iptables -i 'iptables -t filter -A custom-out -s %%word -d %%word -j ACCEPT' -i 'ip6tables -t nat'
$0 -b nft -i 'element inet filter tor %%word' -i 'set inet %%word tor'
$0 -b nft -i 'element inet filter custom-out6 %%word'
EOF
exit 1;
}
my $type;
my $is_save;
my @criteria;
GetOptions(
'backend=s' => \$type,
'save' => \$is_save,
'ignore=s' => \@criteria,
) or usage;
usage unless ( defined $type );
my $get_rules = {
'iptables' => \&iptables_h,
'nft' => \&nftables_h,
}->{$type};
my @rules = filter_rules( \@criteria, $get_rules->() );
if ($is_save) {
save_rules(@rules);
}
else {
compare( load_rules(), \@rules );
}
sub compare {
my ( $reference_rules, $actual_rules ) = @_;
my %h;
$h{$_}-- for @$reference_rules;
$h{$_}++ for @$actual_rules;
my @diff = sort
map { $h{$_} > 0 ? "added : $_" : $h{$_} < 0 ? "deleted: $_" : () }
keys %h;
if (@diff) {
print "[Critical]: Firewall has changed\n";
print "$_\n" for @diff;
exit 2;
}
else {
print "Checked rules: " . scalar keys %h;
}
}
sub filter_rules {
my ( $criteria, @rules ) = @_;
return @rules unless @$criteria;
my @regexps = map {s/\\\%word/(\\S+\\h*)+/gr}
map {quotemeta} @$criteria;
grep {
my $rule = $_;
my $is_match = sub {
grep { return 1 if $rule =~ /^$_$/ } @regexps;
}
->();
not $is_match;
} @rules;
}
sub nftables_h {
my @ruleset = @{ decode_json(`nft -js list ruleset`)->{nftables} };
my %raw_rules_cache;
my @tables = map { parse_nft_table($_) } filter_nft( 'table', @ruleset );
my @sets
= map { parse_nft_set_elements($_) } filter_nft( 'set', @ruleset );
my @chains = map { parse_nft_chain($_) } filter_nft( 'chain', @ruleset );
my @rules = map {
my $rule_name = "$_->{family} $_->{table} $_->{chain}";
$raw_rules_cache{$rule_name} = join( "\n",
@{ ( sec_run( 'nft', '-ats', "list chain $rule_name" ) )[0] } )
unless defined $raw_rules_cache{$rule_name};
parse_nft_rule( $_, $raw_rules_cache{$rule_name} );
} filter_nft( 'rule', @ruleset );
return ( @tables, @sets, @chains, @rules );
}
sub filter_nft {
my ( $key, @ruleset ) = @_;
return map { $_->{$key} }
grep { defined $_->{$key} } @ruleset;
}
sub parse_nft_table {
return "table $_[0]->{family} $_[0]->{name}";
}
sub parse_nft_rule {
my ( $rule, $raw_rules ) = @_;
my ($raw_rule) = $raw_rules =~ /\s*(.+) # handle $rule->{handle}\s+/;
return "rule $rule->{family} $rule->{table} $rule->{chain} $raw_rule";
}
sub parse_nft_chain {
my ($chain) = @_;
my @parsed_chain = map {
my ( $key, $value ) = %{$_};
defined $chain->{$key}
? sprintf( $value, $chain->{$key} )
: ();
} (
{ family => '%s' },
{ table => '%s' },
{ name => '%s {' },
{ type => 'type %s' },
{ hook => 'hook %s' },
{ prio => 'priority %s;' },
{ policy => 'policy %s;' },
);
return "chain @parsed_chain }";
}
sub parse_nft_set_elements {
my %parser = (
prefix => sub {"$_[0]->{addr}/$_[0]->{len}"},
elem => sub { $_[0]->{val} },
range => sub { join '-', @{ $_[0] } },
_string => sub { $_[0] },
);
return map {
my $set = $_;
my $set_name = "$set->{family} $set->{table} $set->{name}";
my @elements = map {
my ( $key, $value )
= ref $_ eq 'HASH'
? %$_
: ( _string => $_ );
"element $set_name " . $parser{$key}->($value);
} @{ $set->{elem} };
( "set $set_name", @elements );
} @_;
}
sub iptables_h {
map {
my $x = $_;
open FH, '<', "/proc/net/${x}_tables_names" or die $!;
my @tables = <FH>;
chomp(@tables);
close FH;
map {
my $table = $_;
my ($ruleset) = sec_run( "${x}tables", '-t', $table, '-S' );
map { "${x}tables -t $table $_"; } @$ruleset;
} @tables;
} qw(ip ip6);
}
sub save_rules {
my @rules = @_;
open( my $fh, '>', REFERENCE_FILE ) or die $!;
chomp @rules;
print $fh "$_\n" for @rules;
close $fh;
}
sub load_rules {
open( my $fh, '<', REFERENCE_FILE ) or die $!;
my @rules = <$fh>;
close $fh;
chomp @rules;
return \@rules;
}
sub sec_run {
my ( $cmd, @args ) = @_;
my $pid = open3( undef, my $out, my $err = gensym, $cmd, @args )
or die "$!";
my @stdout = <$out>;
my @stderr = <$err>;
close $out;
chomp @stdout;
close $err;
waitpid( $pid, 0 );
die "Failed run: $cmd @args\n@stderr" if $? >> 8 != 0;
return ( \@stdout, \@stderr );
}