Introduce "IPtables" module.
authorStefan Schantl <stefan.schantl@ipfire.org>
Tue, 19 Jan 2016 11:43:28 +0000 (12:43 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Tue, 19 Jan 2016 11:43:28 +0000 (12:43 +0100)
This module is used to allow any interaction of guardian with
an IPtables based firewall backed.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
modules/IPtables.pm [new file with mode: 0644]

diff --git a/modules/IPtables.pm b/modules/IPtables.pm
new file mode 100644 (file)
index 0000000..e3c3d1b
--- /dev/null
@@ -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 (<RULES>) {
+               # 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;