From: Stefan Schantl Date: Tue, 19 Jan 2016 11:43:28 +0000 (+0100) Subject: Introduce "IPtables" module. X-Git-Tag: 2.0~49 X-Git-Url: http://git.ipfire.org/?p=people%2Fstevee%2Fguardian.git;a=commitdiff_plain;h=b08d4ddeccf26a38e581291567230018bdf76010 Introduce "IPtables" module. This module is used to allow any interaction of guardian with an IPtables based firewall backed. Signed-off-by: Stefan Schantl --- diff --git a/modules/IPtables.pm b/modules/IPtables.pm new file mode 100644 index 0000000..e3c3d1b --- /dev/null +++ b/modules/IPtables.pm @@ -0,0 +1,117 @@ +package Guardian::IPtables; +use strict; +use warnings; + +use Exporter qw(import); + +our @EXPORT = qw(DoBlock DoUnblock DoFlush); + +# The path to the iptables executeable. +my $iptables = "/usr/sbin/iptables"; + +# The used firewall chain. +my $chain = "INPUT"; + +# +## The DoBlock subroutine. +# +## This subroutine is called, when a given address should be locked by +## using IPtables. +# +## Guardian is using the "append" option from IPtables, which will add the new rule +## to the end of the chain to prevent from possible race-conditions when adding/deleting +## rules at the same time. +# +sub DoBlock (@) { + my ($address, $action) = @_; + + # If no action has been given, default to "DROP". + unless($action) { + $action = "DROP"; + } + + # Call iptables to block the given address. + system("$iptables --wait -A $chain -s $address -j $action"); +} + +# +## The DoUnblock subroutine. +# +## This subroutine can be used to delete all firewall rules (unblock) +## of a previously blocked address. +# +## To do this a subroutine will be called, which is collecting all rule +## positions in the firewall chain for the given address, which returns +## them in reversed order. This list of rules will be deleted one-by-one +## so multiple entries (if present) for the address will be deleted. +# +## This approach also eliminates the exact rule argument processing again +## for dropping it. So it is not neccessary to know the additional arguments +## like firewall action (DROP, REJECT) etc. +# +sub DoUnblock ($) { + my ($address) = @_; + + # Get rulepositions for the specified address. + my @rules = &_get_rules_positions_by_address($address); + + # Loop through the rules array and drop the firewall rules. + foreach my $rule (@rules) { + # Call iptables to delete the rule. + system("$iptables --wait -D $chain $rule"); + } +} + +# +## The DoFlush subroutine. +# +## Call this subroutine to entirely flush the IPtables chain. +# +sub DoFlush () { + # Call iptalbes and flush the chain. + system("$iptables --wait -F $chain"); +} + +# +## Get rules subroutine. +# +## This subroutine is used to get the rule position of the active +## firewall rules for a given address. Those position will be collected +## and returned in reversed order. +# +sub _get_rules_positions_by_address ($) { + my ($address) = @_; + + # Array to store the rule positions. + my @rules; + + # Call iptables and list all firewall rules. + open(RULES, "$iptables --wait -L $chain -n -v --line-numbers |"); + + # Read input line by line. + foreach my $line () { + # Skip descriptive line. + next if ($line =~ /^Chain/); + next if ($line =~ /^ pkts/); + + # Generate array, based on the line content + # (seperator is a single or multiple space's) + my @comps = split(/\s{1,}/, $line); + my ($pos, $pkts, $bytes, $target, $prot, $opt, $in, $out, $source, $destination) = @comps; + + # Compare the current source address with the given one. + # If they are equal, the rule position will be added to the + # rules array. + if ($address eq $source) { + push(@rules, $pos); + } + } + + # Reverse the array. + my @reversed_rules = reverse @rules; + + # Return the reversed array. + return @reversed_rules; +} + +1;