]> git.ipfire.org Git - people/stevee/guardian.git/blob - modules/IPtables.pm
Introduce "IPtables" module.
[people/stevee/guardian.git] / modules / IPtables.pm
1 package Guardian::IPtables;
2 use strict;
3 use warnings;
4
5 use Exporter qw(import);
6
7 our @EXPORT = qw(DoBlock DoUnblock DoFlush);
8
9 # The path to the iptables executeable.
10 my $iptables = "/usr/sbin/iptables";
11
12 # The used firewall chain.
13 my $chain = "INPUT";
14
15 #
16 ## The DoBlock subroutine.
17 #
18 ## This subroutine is called, when a given address should be locked by
19 ## using IPtables.
20 #
21 ## Guardian is using the "append" option from IPtables, which will add the new rule
22 ## to the end of the chain to prevent from possible race-conditions when adding/deleting
23 ## rules at the same time.
24 #
25 sub DoBlock (@) {
26 my ($address, $action) = @_;
27
28 # If no action has been given, default to "DROP".
29 unless($action) {
30 $action = "DROP";
31 }
32
33 # Call iptables to block the given address.
34 system("$iptables --wait -A $chain -s $address -j $action");
35 }
36
37 #
38 ## The DoUnblock subroutine.
39 #
40 ## This subroutine can be used to delete all firewall rules (unblock)
41 ## of a previously blocked address.
42 #
43 ## To do this a subroutine will be called, which is collecting all rule
44 ## positions in the firewall chain for the given address, which returns
45 ## them in reversed order. This list of rules will be deleted one-by-one
46 ## so multiple entries (if present) for the address will be deleted.
47 #
48 ## This approach also eliminates the exact rule argument processing again
49 ## for dropping it. So it is not neccessary to know the additional arguments
50 ## like firewall action (DROP, REJECT) etc.
51 #
52 sub DoUnblock ($) {
53 my ($address) = @_;
54
55 # Get rulepositions for the specified address.
56 my @rules = &_get_rules_positions_by_address($address);
57
58 # Loop through the rules array and drop the firewall rules.
59 foreach my $rule (@rules) {
60 # Call iptables to delete the rule.
61 system("$iptables --wait -D $chain $rule");
62 }
63 }
64
65 #
66 ## The DoFlush subroutine.
67 #
68 ## Call this subroutine to entirely flush the IPtables chain.
69 #
70 sub DoFlush () {
71 # Call iptalbes and flush the chain.
72 system("$iptables --wait -F $chain");
73 }
74
75 #
76 ## Get rules subroutine.
77 #
78 ## This subroutine is used to get the rule position of the active
79 ## firewall rules for a given address. Those position will be collected
80 ## and returned in reversed order.
81 #
82 sub _get_rules_positions_by_address ($) {
83 my ($address) = @_;
84
85 # Array to store the rule positions.
86 my @rules;
87
88 # Call iptables and list all firewall rules.
89 open(RULES, "$iptables --wait -L $chain -n -v --line-numbers |");
90
91 # Read input line by line.
92 foreach my $line (<RULES>) {
93 # Skip descriptive line.
94 next if ($line =~ /^Chain/);
95 next if ($line =~ /^ pkts/);
96
97 # Generate array, based on the line content
98 # (seperator is a single or multiple space's)
99 my @comps = split(/\s{1,}/, $line);
100 my ($pos, $pkts, $bytes, $target, $prot, $opt, $in, $out, $source, $destination) = @comps;
101
102 # Compare the current source address with the given one.
103 # If they are equal, the rule position will be added to the
104 # rules array.
105 if ($address eq $source) {
106 push(@rules, $pos);
107 }
108 }
109
110 # Reverse the array.
111 my @reversed_rules = reverse @rules;
112
113 # Return the reversed array.
114 return @reversed_rules;
115 }
116
117 1;