1IPTables::ChainMgr(3) User Contributed Perl DocumentationIPTables::ChainMgr(3)
2
3
4
6 IPTables::ChainMgr - Perl extension for manipulating iptables and
7 ip6tables policies
8
10 use IPTables::ChainMgr;
11
12 my $ipt_bin = '/sbin/iptables'; # can set this to /sbin/ip6tables
13
14 my %opts = (
15 'use_ipv6' => 0, # can set to 1 to force ip6tables usage
16 'ipt_rules_file' => '', # optional file path from
17 # which to read iptables rules
18 'debug' => 0,
19 'verbose' => 0
20
21 ### advanced options
22 'ipt_alarm' => 5, ### max seconds to wait for iptables execution.
23 'ipt_exec_style' => 'waitpid', ### can be 'waitpid',
24 ### 'system', or 'popen'.
25 'ipt_exec_sleep' => 1, ### add in time delay between execution of
26 ### iptables commands (default is 0).
27 );
28
29 my $ipt_obj = IPTables::ChainMgr->new(%opts)
30 or die "[*] Could not acquire IPTables::ChainMgr object";
31
32 my $rv = 0;
33 my $out_ar = [];
34 my $errs_ar = [];
35
36 # check to see if the 'CUSTOM' chain exists in the filter table
37 ($rv, $out_ar, $errs_ar) = $ipt_obj->chain_exists('filter', 'CUSTOM');
38 if ($rv) {
39 print "CUSTOM chain exists.\n";
40
41 ### flush all rules from the chain
42 $ipt_obj->flush_chain('filter', 'CUSTOM');
43
44 ### now delete the chain (along with any jump rule in the
45 ### INPUT chain)
46 $ipt_obj->delete_chain('filter', 'INPUT', 'CUSTOM');
47 }
48
49 # set the policy on the FORWARD table to DROP
50 $ipt_obj->set_chain_policy('filter', 'FORWARD', 'DROP');
51
52 # create new iptables chain in the 'filter' table
53 $ipt_obj->create_chain('filter', 'CUSTOM');
54
55 # translate a network into the same representation that iptables or
56 # ip6tables uses (e.g. '10.1.2.3/24' is properly represented as '10.1.2.0/24',
57 # and '0000:0000:00AA:0000:0000:AA00:0000:0001/64' = '0:0:aa::/64')
58 $normalized_net = $ipt_obj->normalize_net('10.1.2.3/24');
59
60 # add rule to jump packets from the INPUT chain into CUSTOM at the
61 # 4th rule position
62 $ipt_obj->add_jump_rule('filter', 'INPUT', 4, 'CUSTOM');
63
64 # find rule that allows all traffic from 10.1.2.0/24 to 192.168.1.2
65 ($rule_num, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24', '192.168.1.2',
66 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
67
68 # find rule that allows all TCP port 80 traffic from 10.1.2.0/24 to
69 # 192.168.1.1
70 ($rule_num, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24', '192.168.1.2',
71 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1, 'protocol' => 'tcp',
72 's_port' => 0, 'd_port' => 80});
73
74 # add rule at the 5th rule position to allow all traffic from
75 # 10.1.2.0/24 to 192.168.1.2 via the INPUT chain in the filter table
76 ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.0/24',
77 '192.168.1.2', 5, 'filter', 'INPUT', 'ACCEPT', {});
78
79 # add rule at the 4th rule position to allow all traffic from
80 # 10.1.2.0/24 to 192.168.1.2 over TCP port 80 via the CUSTOM chain
81 # in the filter table
82 ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.0/24',
83 '192.168.1.2', 4, 'filter', 'CUSTOM', 'ACCEPT',
84 {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
85
86 # append rule at the end of the CUSTOM chain in the filter table to
87 # allow all traffic from 10.1.2.0/24 to 192.168.1.2 via port 80
88 ($rv, $out_ar, $errs_ar) = $ipt_obj->append_ip_rule('10.1.2.0/24',
89 '192.168.1.2', 'filter', 'CUSTOM', 'ACCEPT',
90 {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
91
92 # for each of the examples above, here are ip6tables analogs
93 # (requires instantiating the IPTables::ChainMgr object with
94 # /sbin/ip6tables): find rule that allows all traffic from fe80::200:f8ff:fe21:67cf
95 # to 0:0:aa::/64
96 ($rule_num, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf', '0:0:aa::/64',
97 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
98
99 # find rule that allows all TCP port 80 traffic from fe80::200:f8ff:fe21:67c to 0:0:aa::/64
100 ($rule_num, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf', '0:0:aa::/64',
101 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1, 'protocol' => 'tcp',
102 's_port' => 0, 'd_port' => 80});
103
104 # add rule at the 5th rule position to allow all traffic from
105 # fe80::200:f8ff:fe21:67c to 0:0:aa::/64 via the INPUT chain in the filter table
106 ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('fe80::200:f8ff:fe21:67cf',
107 '0:0:aa::/64', 5, 'filter', 'INPUT', 'ACCEPT', {});
108
109 # add rule at the 4th rule position to allow all traffic from
110 # fe80::200:f8ff:fe21:67c to 0:0:aa::/64 over TCP port 80 via the CUSTOM chain
111 # in the filter table
112 ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('fe80::200:f8ff:fe21:67cf',
113 '0:0:aa::/64', 4, 'filter', 'CUSTOM', 'ACCEPT',
114 {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
115
116 # append rule at the end of the CUSTOM chain in the filter table to
117 # allow all traffic from fe80::200:f8ff:fe21:67c to 0:0:aa::/64 via port 80
118 ($rv, $out_ar, $errs_ar) = $ipt_obj->append_ip_rule('fe80::200:f8ff:fe21:67cf',
119 '0:0:aa::/64', 'filter', 'CUSTOM', 'ACCEPT',
120 {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
121
122 # run an arbitrary iptables command and collect the output
123 ($rv, $out_ar, $errs_ar) = $ipt_obj->run_ipt_cmd(
124 '/sbin/iptables -v -n -L');
125
127 The "IPTables::ChainMgr" package provides an interface to manipulate
128 iptables and ip6tables policies on Linux systems through the direct
129 execution of iptables/ip6tables commands. Note that the 'firewalld'
130 infrastructure on Fedora21 is also supported through execution of the
131 'firewall-cmd' binary. Although making a perl extension of libiptc
132 provided by the Netfilter project is possible (and has been done by the
133 IPTables::libiptc module available from CPAN), it is also easy enough
134 to just execute iptables/ip6tables commands directly in order to both
135 parse and change the configuration of the policy. Further, this
136 simplifies installation since the only external requirement is (in the
137 spirit of scripting) to be able to point IPTables::ChainMgr at an
138 installed iptables or ip6tables binary instead of having to compile
139 against a library.
140
142 The IPTables::ChainMgr extension provides an object interface to the
143 following functions:
144
145 chain_exists($table, $chain)
146 This function tests whether or not a chain (e.g. 'INPUT') exists
147 within the specified table (e.g. 'filter'). This is most useful to
148 test whether a custom chain has been added to the running
149 iptables/ip6tables policy. The return values are (as with many
150 IPTables::ChainMgr functions) an array of three things: a numeric
151 value, and both the stdout and stderr of the iptables or ip6tables
152 command in the form of array references. So, an example invocation
153 of the chain_exists() function would be:
154
155 ($rv, $out_ar, $errs_ar) = $ipt_obj->chain_exists('filter', 'CUSTOM');
156
157 If $rv is 1, then the CUSTOM chain exists in the filter table, and
158 0 otherwise. The $out_ar array reference contains the output of
159 the command "/sbin/iptables -t filter -v -n -L CUSTOM", which will
160 contain the rules in the CUSTOM chain (if it exists) or nothing (if
161 not). The $errs_ar array reference contains the stderr of the
162 iptables command. As with all IPTables::ChainMgr functions, if the
163 IPTables::ChainMgr object was instantiated with the ip6tables
164 binary path, then the above command would become "/sbin/ip6tables
165 -t filter -v -n -L CUSTOM".
166
167 create_chain($table, $chain)
168 This function creates a chain within the specified table. Again,
169 three return values are given like so:
170
171 ($rv, $out_ar, $errs_ar) = $ipt_obj->create_chain('filter', 'CUSTOM');
172
173 Behind the scenes, the create_chain() function in the example above
174 runs the iptables command "/sbin/iptables -t filter -N CUSTOM", or
175 for ip6tables "/sbin/ip6tables -t filter -N CUSTOM".
176
177 flush_chain($table, $chain)
178 This function flushes all rules from chain in the specified table,
179 and three values are returned:
180
181 ($rv, $out_ar, $errs_ar) = $ipt_obj->flush_chain('filter', 'CUSTOM');
182
183 The flush_chain() function in the example above executes the
184 command "/sbin/iptables -t filter -F CUSTOM" or "/sbin/ip6tables -t
185 filter -F CUSTOM".
186
187 set_chain_policy($table, $chain, $target)
188 This function sets the policy of a built-in chain
189 (iptables/ip6tables does not allow this for non built-in chains) to
190 the specified target:
191
192 ($rv, $out_ar, $errs_ar) = $ipt_obj->set_chain_policy('filter', 'FORWARD', 'DROP');
193
194 In this example, the following command is executed behind the
195 scenes: "/sbin/iptables -t filter -P FORWARD DROP" or
196 "/sbin/ip6tables -t filter -P FORWARD DROP".
197
198 delete_chain($table, $jump_from_chain, $chain)
199 This function deletes a chain from the specified table along with
200 any jump rule to which packets are jumped into this chain:
201
202 ($rv, $out_ar, $errs_ar) = $ipt_obj->delete_chain('filter', 'INPUT', 'CUSTOM');
203
204 Internally a check is performed to see whether the chain exists
205 within the table, and global jump rules are removed from the jump
206 chain before deletion (a chain cannot be deleted until there are no
207 references to it). In the example above, the CUSTOM chain is
208 deleted after any jump rule to this chain from the INPUT chain is
209 also deleted.
210
211 find_ip_rule($src, $dst, $table, $chain, $target, %extended_info)
212 This function parses the specified chain to see if there is a rule
213 that matches the $src, $dst, $target, and (optionally) any
214 %extended_info criteria. The return values are the rule number in
215 the chain (or zero if it doesn't exist), and the total number of
216 rules in the chain. Below are four examples; the first is to find
217 an ACCEPT rule for 10.1.2.0/24 to communicate with 192.168.1.2 in
218 the INPUT chain, and the second is the same except that the rule is
219 restricted to TCP port 80. The third and forth examples illustrate
220 ip6tables analogs of the first two examples with source IP
221 fe80::200:f8ff:fe21:67cf/128 and destination network: 0:0:aa::/64
222
223 ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24',
224 '192.168.1.2', 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
225 if ($rulenum) {
226 print "matched rule $rulenum out of $chain_rules rules\n";
227 }
228
229 ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24',
230 '192.168.1.2', 'filter', 'INPUT', 'ACCEPT',
231 {'normalize' => 1, 'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
232 if ($rulenum) {
233 print "matched rule $rulenum out of $chain_rules rules\n";
234 }
235
236 ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf/128',
237 '0:0:aa::/64', 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
238 if ($rulenum) {
239 print "matched rule $rulenum out of $chain_rules rules\n";
240 }
241
242 ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf/128',
243 '0:0:aa::/64', 'filter', 'INPUT', 'ACCEPT',
244 {'normalize' => 1, 'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
245 if ($rulenum) {
246 print "matched rule $rulenum out of $chain_rules rules\n";
247 }
248
249 add_ip_rule($src, $dst, $rulenum, $table, $chain, $target,
250 %extended_info)
251 This function inserts a rule into the running iptables chain and
252 table at the specified rule number. Return values are success or
253 failure along with the iptables stdout and stderr.
254
255 append_ip_rule($src, $dst, $table, $chain, $target, %extended_info)
256 This function appends a rule at the end of the iptables chain in
257 the specified table. Return values are success or failure along
258 with the iptables stdout and stderr.
259
260 delete_ip_rule($src, $dst, $table, $chain, $target, %extended_info)
261 This function searches for and then deletes a matching rule within
262 the specified chain. Return values are success or failure along
263 with the iptables stdout and stderr.
264
265 add_jump_rule($table, $from_chain, $rulenum, $to_chain)
266 This function adds a jump rule (after making sure it doesn't
267 already exist) into the specified chain. The $rulenum variable
268 tells the function where within the calling chain the new jump rule
269 should be placed. Here is an example to force all packets
270 regardless of source or destination to be jumped to the CUSTOM
271 chain from the INPUT chain at rule 4:
272
273 ($rv, $out_ar, $errs_ar) = $ipt_obj->add_jump_rule('filter', 'INPUT', 4, 'CUSTOM');
274
275 normalize_net($net)
276 This function translates an IP/network into the same representation
277 that iptables or ip6tables uses upon listing a policy. The first
278 example shows an IPv4 network and how iptables lists it, and the
279 second is an IPv6 network:
280
281 print $ipt_obj->normalize_net('10.1.2.3/24'), "\n" # prints '10.1.2.0/24'
282 print $ipt_obj->normalize_net('0000:0000:00AA:0000:0000:AA00:0000:0001/64'), "\n" # prints '0:0:aa::/64'
283
284 run_ipt_cmd($cmd)
285 This function is a generic work horse function for executing
286 iptables commands, and is used internally by IPTables::ChainMgr
287 functions. It can also be used by a script that imports the
288 IPTables::ChainMgr extension to provide a consistent mechanism for
289 executing iptables. Three return values are given: success (1) or
290 failure (0) of the iptables command (yes, this backwards from the
291 normal exit status of Linux/*NIX binaries), and array references to
292 the iptables stdout and stderr. Here is an example to list all
293 rules in the user-defined chain "CUSTOM":
294
295 ($rv, $out_ar, $errs_ar) = $ipt_obj->run_ipt_cmd('/sbin/iptables -t filter -v -n -L CUSTOM');
296 if ($rv) {
297 print "rules:\n";
298 print for @$out_ar;
299 }
300
302 The IPTables::ChainMgr extension is closely associated with the
303 IPTables::Parse extension, and both are heavily used by the psad and
304 fwsnort projects to manipulate iptables policies based on various
305 criteria (see the psad(8) and fwsnort(8) man pages). As always, the
306 iptables(8) man page provides the best information on command line
307 execution and theory behind iptables.
308
309 Although there is no mailing that is devoted specifically to the
310 IPTables::ChainMgr extension, questions about the extension will be
311 answered on the following lists:
312
313 The psad mailing list: http://lists.sourceforge.net/lists/listinfo/psad-discuss
314 The fwsnort mailing list: http://lists.sourceforge.net/lists/listinfo/fwsnort-discuss
315
316 The latest version of the IPTables::ChainMgr extension can be found on
317 CPAN and also here:
318
319 http://www.cipherdyne.org/modules/
320
321 Source control is provided by git:
322
323 http://github.com/mrash/IPTables-ChaingMgr.git
324
326 Thanks to the following people:
327
328 Franck Joncourt <franck.mail@dthconnex.com>
329 Grant Ferley
330 Darien Kindlund
331
333 The IPTables::ChainMgr extension was written by Michael Rash
334 <mbr@cipherdyne.org> to support the psad and fwsnort projects. Please
335 send email to this address if there are any questions, comments, or bug
336 reports.
337
339 Copyright (C) 2005-2015 Michael Rash. All rights reserved.
340
341 This module is free software. You can redistribute it and/or modify it
342 under the terms of the Artistic License 2.0. More information can be
343 found here: http://www.perl.com/perl/misc/Artistic.html
344
345 This program is distributed "as is" in the hope that it will be useful,
346 but without any warranty; without even the implied warranty of
347 merchantability or fitness for a particular purpose.
348
349
350
351perl v5.36.0 2022-07-22 IPTables::ChainMgr(3)