]> git.ipfire.org Git - people/stevee/guardian.git/blame - modules/IPtables.pm
Allow to configure the firewall action which will be performed.
[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
e9c558fe
SS
9# Array of supported block actions.
10my @supported_actions = ("DROP", "REJECT");
11
b08d4dde
SS
12# The path to the iptables executeable.
13my $iptables = "/usr/sbin/iptables";
14
15# The used firewall chain.
16my $chain = "INPUT";
17
18#
19## The DoBlock subroutine.
20#
21## This subroutine is called, when a given address should be locked by
22## using IPtables.
23#
24## Guardian is using the "append" option from IPtables, which will add the new rule
25## to the end of the chain to prevent from possible race-conditions when adding/deleting
26## rules at the same time.
27#
28sub DoBlock (@) {
29 my ($address, $action) = @_;
30
31 # If no action has been given, default to "DROP".
32 unless($action) {
33 $action = "DROP";
34 }
35
e9c558fe
SS
36 # Check if the given action is supported.
37 my $error = &_check_action($action);
38
39 # Abort and return the recieved error.
40 if ($error) {
41 return $error;
42 }
43
b08d4dde
SS
44 # Call iptables to block the given address.
45 system("$iptables --wait -A $chain -s $address -j $action");
46}
47
48#
49## The DoUnblock subroutine.
50#
51## This subroutine can be used to delete all firewall rules (unblock)
52## of a previously blocked address.
53#
54## To do this a subroutine will be called, which is collecting all rule
55## positions in the firewall chain for the given address, which returns
56## them in reversed order. This list of rules will be deleted one-by-one
57## so multiple entries (if present) for the address will be deleted.
58#
59## This approach also eliminates the exact rule argument processing again
60## for dropping it. So it is not neccessary to know the additional arguments
61## like firewall action (DROP, REJECT) etc.
62#
63sub DoUnblock ($) {
64 my ($address) = @_;
65
66 # Get rulepositions for the specified address.
67 my @rules = &_get_rules_positions_by_address($address);
68
69 # Loop through the rules array and drop the firewall rules.
70 foreach my $rule (@rules) {
71 # Call iptables to delete the rule.
72 system("$iptables --wait -D $chain $rule");
73 }
74}
75
76#
77## The DoFlush subroutine.
78#
79## Call this subroutine to entirely flush the IPtables chain.
80#
81sub DoFlush () {
82 # Call iptalbes and flush the chain.
83 system("$iptables --wait -F $chain");
84}
85
86#
87## Get rules subroutine.
88#
89## This subroutine is used to get the rule position of the active
90## firewall rules for a given address. Those position will be collected
91## and returned in reversed order.
92#
93sub _get_rules_positions_by_address ($) {
94 my ($address) = @_;
95
96 # Array to store the rule positions.
97 my @rules;
98
99 # Call iptables and list all firewall rules.
100 open(RULES, "$iptables --wait -L $chain -n -v --line-numbers |");
101
102 # Read input line by line.
103 foreach my $line (<RULES>) {
104 # Skip descriptive line.
105 next if ($line =~ /^Chain/);
106 next if ($line =~ /^ pkts/);
107
108 # Generate array, based on the line content
109 # (seperator is a single or multiple space's)
110 my @comps = split(/\s{1,}/, $line);
111 my ($pos, $pkts, $bytes, $target, $prot, $opt, $in, $out, $source, $destination) = @comps;
112
113 # Compare the current source address with the given one.
114 # If they are equal, the rule position will be added to the
115 # rules array.
116 if ($address eq $source) {
117 push(@rules, $pos);
118 }
119 }
120
121 # Reverse the array.
122 my @reversed_rules = reverse @rules;
123
124 # Return the reversed array.
125 return @reversed_rules;
126}
127
e9c558fe
SS
128#
129## The _check_action function.
130#
131## This private function is used to check if the given action is supported by
132## the firewall engine.
133#
134sub _check_action ($) {
135 my $action = $_[0];
136
137 # Check if the recieved action is part of the supported_actions array.
138 foreach my $item (@supported_actions) {
139 # Exit the loop and return "nothing" if we found a match.
140 if($item eq $action) {
141 return;
142 }
143 }
144
145 # If we got here, the given action is not part of the array of supported
146 # actions. Return an error message.
147 return "Unsupported action: $action";
148}
149
b08d4dde 1501;