]> git.ipfire.org Git - people/stevee/guardian.git/blame - modules/IPtables.pm
Introduce "IPtables" module.
[people/stevee/guardian.git] / modules / IPtables.pm
CommitLineData
b08d4dde
SS
1package Guardian::IPtables;
2use strict;
3use warnings;
4
5use Exporter qw(import);
6
7our @EXPORT = qw(DoBlock DoUnblock DoFlush);
8
9# The path to the iptables executeable.
10my $iptables = "/usr/sbin/iptables";
11
12# The used firewall chain.
13my $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#
25sub 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#
52sub 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#
70sub 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#
82sub _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
1171;