677
697
# create new iptables chain in the 'filter' table
678
698
$ipt_obj->create_chain('filter', 'CUSTOM');
700
# translate a network into the same representation that iptables or
701
# ip6tables uses (e.g. '10.1.2.3/24' is properly represented as '10.1.2.0/24',
702
# and '0000:0000:00AA:0000:0000:AA00:0000:0001/64' = '0:0:aa::/64')
703
$normalized_net = $ipt_obj->normalize_net('10.1.2.3/24');
680
705
# add rule to jump packets from the INPUT chain into CUSTOM at the
681
706
# 4th rule position
682
707
$ipt_obj->add_jump_rule('filter', 'INPUT', 4, 'CUSTOM');
684
# find rule that allows all traffic from 10.1.2.3 to 192.168.1.2
685
($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.3', '192.168.1.2',
686
'filter', 'INPUT', 'ACCEPT', {});
709
# find rule that allows all traffic from 10.1.2.0/24 to 192.168.1.2
710
($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.0/24', '192.168.1.2',
711
'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
688
# find rule that allows all TCP port 80 traffic from 10.1.2.3 to
713
# find rule that allows all TCP port 80 traffic from 10.1.2.0/24 to
690
($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.3', '192.168.1.2',
691
'filter', 'INPUT', 'ACCEPT', {'protocol' => 'tcp', 's_port' => 0,
715
($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.0/24', '192.168.1.2',
716
'filter', 'INPUT', 'ACCEPT', {'normalize' => 1, 'protocol' => 'tcp',
717
's_port' => 0, 'd_port' => 80});
694
719
# add rule at the 5th rule position to allow all traffic from
695
# 10.1.2.3 to 192.168.1.2 via the INPUT chain in the filter table
696
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.3',
720
# 10.1.2.0/24 to 192.168.1.2 via the INPUT chain in the filter table
721
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.0/24',
697
722
'192.168.1.2', 5, 'filter', 'INPUT', 'ACCEPT', {});
699
724
# add rule at the 4th rule position to allow all traffic from
700
# 10.1.2.3 to 192.168.1.2 over TCP port 80 via the CUSTOM chain
725
# 10.1.2.0/24 to 192.168.1.2 over TCP port 80 via the CUSTOM chain
701
726
# in the filter table
702
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.3',
727
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.0/24',
703
728
'192.168.1.2', 4, 'filter', 'CUSTOM', 'ACCEPT',
704
729
{'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
706
731
# append rule at the end of the CUSTOM chain in the filter table to
707
# allow all traffic from 10.1.2.3 to 192.168.1.2 via port 80
708
($rv, $out_ar, $errs_ar) = $ipt_obj->append_ip_rule('10.1.2.3',
732
# allow all traffic from 10.1.2.0/24 to 192.168.1.2 via port 80
733
($rv, $out_ar, $errs_ar) = $ipt_obj->append_ip_rule('10.1.2.0/24',
709
734
'192.168.1.2', 'filter', 'CUSTOM', 'ACCEPT',
710
735
{'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
737
# for each of the examples above, here are ip6tables analogs
738
# (requires instantiating the IPTables::ChainMgr object with
739
# /sbin/ip6tables): find rule that allows all traffic from fe80::200:f8ff:fe21:67cf
741
($rv, $rule_num) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf', '0:0:aa::/64',
742
'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
744
# find rule that allows all TCP port 80 traffic from fe80::200:f8ff:fe21:67c to 0:0:aa::/64
745
($rv, $rule_num) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf', '0:0:aa::/64',
746
'filter', 'INPUT', 'ACCEPT', {'normalize' => 1, 'protocol' => 'tcp',
747
's_port' => 0, 'd_port' => 80});
749
# add rule at the 5th rule position to allow all traffic from
750
# fe80::200:f8ff:fe21:67c to 0:0:aa::/64 via the INPUT chain in the filter table
751
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('fe80::200:f8ff:fe21:67cf',
752
'0:0:aa::/64', 5, 'filter', 'INPUT', 'ACCEPT', {});
754
# add rule at the 4th rule position to allow all traffic from
755
# fe80::200:f8ff:fe21:67c to 0:0:aa::/64 over TCP port 80 via the CUSTOM chain
756
# in the filter table
757
($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('fe80::200:f8ff:fe21:67cf',
758
'0:0:aa::/64', 4, 'filter', 'CUSTOM', 'ACCEPT',
759
{'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
761
# append rule at the end of the CUSTOM chain in the filter table to
762
# allow all traffic from fe80::200:f8ff:fe21:67c to 0:0:aa::/64 via port 80
763
($rv, $out_ar, $errs_ar) = $ipt_obj->append_ip_rule('fe80::200:f8ff:fe21:67cf',
764
'0:0:aa::/64', 'filter', 'CUSTOM', 'ACCEPT',
765
{'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
712
767
# run an arbitrary iptables command and collect the output
713
768
($rv, $out_ar, $errs_ar) = $ipt_obj->run_ipt_cmd(
714
769
'/sbin/iptables -v -n -L');
716
771
=head1 DESCRIPTION
718
The C<IPTables::ChainMgr> package provide an interface to manipulate iptables
719
policies on Linux systems through the direct execution of iptables commands.
720
Although making a perl extension of libiptc provided by the iptables project is
721
possible (and has been done by the IPTables::libiptc module available from CPAN),
722
it is also easy enough to just execute iptables commands directly in order to
723
both parse and change the configuration of the policy. Further, this simplifies
724
installation since the only external requirement is (in the spirit of scripting)
725
to be able to point IPTables::ChainMgr at an installed iptables binary instead
773
The C<IPTables::ChainMgr> package provides an interface to manipulate iptables
774
and ip6tables policies on Linux systems through the direct execution of
775
iptables/ip6tables commands. Although making a perl extension of libiptc
776
provided by the iptables project is possible (and has been done by the
777
IPTables::libiptc module available from CPAN), it is also easy enough to just
778
execute iptables/ip6tables commands directly in order to both parse and change
779
the configuration of the policy. Further, this simplifies installation since
780
the only external requirement is (in the spirit of scripting) to be able to
781
point IPTables::ChainMgr at an installed iptables or ip6tables binary instead
726
782
of having to compile against a library.
737
793
This function tests whether or not a chain (e.g. 'INPUT') exists within the
738
794
specified table (e.g. 'filter'). This is most useful to test whether
739
a custom chain has been added to the running iptables policy. The return values
740
are (as with many IPTables::ChainMgr functions) an array of three things: a
741
numeric value, and both the stdout and stderr of the iptables command in the
742
form of array references. So, an example invocation of the chain_exists()
795
a custom chain has been added to the running iptables/ip6tables policy. The
796
return values are (as with many IPTables::ChainMgr functions) an array of
797
three things: a numeric value, and both the stdout and stderr of the iptables
798
or ip6tables command in the form of array references. So, an example
799
invocation of the chain_exists() function would be:
745
801
($rv, $out_ar, $errs_ar) = $ipt_obj->chain_exists('filter', 'CUSTOM');
747
803
If $rv is 1, then the CUSTOM chain exists in the filter table, and 0 otherwise.
748
804
The $out_ar array reference contains the output of the command "/sbin/iptables -t filter -v -n -L CUSTOM",
749
805
which will contain the rules in the CUSTOM chain (if it exists) or nothing (if not).
750
The $errs_ar array reference contains the stderr of the iptables command.
806
The $errs_ar array reference contains the stderr of the iptables command. As
807
with all IPTables::ChainMgr functions, if the IPTables::ChainMgr object was
808
instantiated with the ip6tables binary path, then the above command would
809
become "/sbin/ip6tables -t filter -v -n -L CUSTOM".
752
811
=item create_chain($table, $chain)
788
848
matches the $src, $dst, $target, and (optionally) any %extended_info
789
849
criteria. The return values are the rule number in the chain (or zero
790
850
if it doesn't exist), and the total number of rules in the chain. Below
791
are two examples; the first is to find an ACCEPT rule for 10.1.2.3 to
851
are four examples; the first is to find an ACCEPT rule for 10.1.2.0/24 to
792
852
communicate with 192.168.1.2 in the INPUT chain, and the second is the
793
same except that the rule is restricted to TCP port 80:
853
same except that the rule is restricted to TCP port 80. The third and
854
forth examples illustrate ip6tables analogs of the first two examples
855
with source IP fe80::200:f8ff:fe21:67cf/128 and destination network: 0:0:aa::/64
795
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.3',
796
'192.168.1.2', 'filter', 'INPUT', 'ACCEPT', {});
857
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24',
858
'192.168.1.2', 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
798
860
print "matched rule $rulenum out of $chain_rules rules\n";
801
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.3',
863
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.0/24',
802
864
'192.168.1.2', 'filter', 'INPUT', 'ACCEPT',
803
{'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
865
{'normalize' => 1, 'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
867
print "matched rule $rulenum out of $chain_rules rules\n";
870
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf/128',
871
'0:0:aa::/64', 'filter', 'INPUT', 'ACCEPT', {'normalize' => 1});
873
print "matched rule $rulenum out of $chain_rules rules\n";
876
($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('fe80::200:f8ff:fe21:67cf/128',
877
'0:0:aa::/64', 'filter', 'INPUT', 'ACCEPT',
878
{'normalize' => 1, 'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
805
880
print "matched rule $rulenum out of $chain_rules rules\n";