r20567 - in /libiptables-chainmgr-perl: ./ branches/ branches/upstream/ branches/upstream/libiptables-chainmgr-perl/ branches/upstream/libiptables-chainmgr-perl/current/ branches/upstream/libiptables-chainmgr-perl/current/lib/ branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ branches/upstream/libiptables-chainmgr-perl/current/t/
thialme-guest at users.alioth.debian.org
thialme-guest at users.alioth.debian.org
Sun Jun 1 12:10:02 UTC 2008
Author: thialme-guest
Date: Sun Jun 1 12:10:01 2008
New Revision: 20567
URL: http://svn.debian.org/wsvn/?sc=1&rev=20567
Log:
[svn-inject] Installing original source of libiptables-chainmgr-perl
Added:
libiptables-chainmgr-perl/
libiptables-chainmgr-perl/branches/
libiptables-chainmgr-perl/branches/upstream/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Changes
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/MANIFEST
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Makefile.PL
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/README
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/VERSION
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ChainMgr.pm
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/
libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/IPTables-ChainMgr.t
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Changes
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Changes?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Changes (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Changes Sun Jun 1 12:10:01 2008
@@ -1,0 +1,8 @@
+Revision history for Perl extension IPTables::ChainMgr.
+
+0.7 Sat May 17 10:49:15 2008
+ - Added perldoc documentation for 0.7 release.
+
+0.01 Tue Feb 22 01:18:14 2005
+ - original version; created by h2xs 1.23 with options
+ -A -X -b 5.6.0 -n IPTables::ChainMgr
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/MANIFEST
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/MANIFEST?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/MANIFEST (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/MANIFEST Sun Jun 1 12:10:01 2008
@@ -1,0 +1,6 @@
+Changes
+Makefile.PL
+MANIFEST
+README
+t/IPTables-ChainMgr.t
+lib/IPTables/ChainMgr.pm
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Makefile.PL
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Makefile.PL?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Makefile.PL (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/Makefile.PL Sun Jun 1 12:10:01 2008
@@ -1,0 +1,12 @@
+use 5.006;
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ NAME => 'IPTables::ChainMgr',
+ VERSION_FROM => 'lib/IPTables/ChainMgr.pm', # finds $VERSION
+ PREREQ_PM => {}, # e.g., Module::Name => 1.1
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'lib/IPTables/ChainMgr.pm', # retrieve abstract from module
+ AUTHOR => 'Michael Rash <mbr at cipherdyne.org>') : ()),
+);
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/README
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/README?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/README (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/README Sun Jun 1 12:10:01 2008
@@ -1,0 +1,41 @@
+IPTables-ChainMgr version 0.01
+==============================
+
+The README is used to introduce the module and provide instructions on
+how to install the module, any machine dependencies it may have (for
+example C compilers and installed libraries) and any other information
+that should be provided before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts the
+README file from a module distribution so that people browsing the
+archive can use it get an idea of the modules uses. It is usually a
+good idea to provide version information here so that people can
+decide whether fixes for the module are worth downloading.
+
+INSTALLATION
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+ IPTables::Parse
+ Net::IPv4Addr
+
+COPYRIGHT AND LICENCE
+
+Put the correct copyright and licence information here.
+
+Copyright (C) 2005-2008 by Michael Rash
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.5 or,
+at your option, any later version of Perl 5 you may have available.
+
+
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/VERSION
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/VERSION?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/VERSION (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/VERSION Sun Jun 1 12:10:01 2008
@@ -1,0 +1,1 @@
+0.7
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ChainMgr.pm
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ChainMgr.pm?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ChainMgr.pm (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/lib/IPTables/ChainMgr.pm Sun Jun 1 12:10:01 2008
@@ -1,0 +1,726 @@
+#
+##############################################################################
+#
+# File: IPTables::ChainMgr.pm
+#
+# Purpose: Perl interface to add and delete rules to an iptables chain. The
+# most common application of this module is to create a custom chain
+# and then add blocking rules to it. Rule additions are (mostly)
+# guaranteed to be unique.
+#
+# Author: Michael Rash (mbr at cipherdyne.org)
+#
+# Version: 0.7
+#
+##############################################################################
+#
+# $Id: ChainMgr.pm 990 2008-02-02 19:01:21Z mbr $
+#
+
+package IPTables::ChainMgr;
+
+use 5.006;
+use POSIX ":sys_wait_h";
+use Carp;
+use IPTables::Parse;
+use Net::IPv4Addr 'ipv4_network';
+use strict;
+use warnings;
+use vars qw($VERSION);
+
+$VERSION = '0.5';
+
+sub new() {
+ my $class = shift;
+ my %args = @_;
+
+ my $self = {
+ _iptables => $args{'iptables'} || '/sbin/iptables',
+ _iptout => $args{'iptout'} || '/tmp/ipt.out',
+ _ipterr => $args{'ipterr'} || '/tmp/ipt.err',
+ _debug => $args{'debug'} || 0,
+ _verbose => $args{'verbose'} || 0,
+ };
+ croak "[*] $self->{'_iptables'} incorrect iptables path.\n"
+ unless -e $self->{'_iptables'};
+ croak "[*] $self->{'_iptables'} not executable.\n"
+ unless -x $self->{'_iptables'};
+ bless $self, $class;
+}
+
+sub chain_exists() {
+ my $self = shift;
+ my $table = shift || croak '[*] Must specify a table, e.g. "filter".';
+ my $chain = shift || croak '[*] Must specify a chain to create.';
+ my $iptables = $self->{'_iptables'};
+
+ ### see if the chain exists
+ return $self->run_ipt_cmd("$iptables -t $table -v -n -L $chain");
+}
+
+sub create_chain() {
+ my $self = shift;
+ my $table = shift || croak '[*] Must specify a table, e.g. "filter".';
+ my $chain = shift || croak '[*] Must specify a chain to create.';
+ my $iptables = $self->{'_iptables'};
+
+ ### see if the chain exists first
+ my ($rv, $out_aref, $err_aref) = $self->chain_exists($table, $chain);
+
+ ### the chain already exists
+ return 1, $out_aref, $err_aref if $rv;
+
+ ### create the chain
+ return $self->run_ipt_cmd("$iptables -t $table -N $chain");
+}
+
+sub flush_chain() {
+ my $self = shift;
+ my $table = shift || croak '[*] Must specify a table, e.g. "filter".';
+ my $chain = shift || croak '[*] Must specify a chain.';
+ my $iptables = $self->{'_iptables'};
+
+ ### flush the chain
+ return $self->run_ipt_cmd("$iptables -t $table -F $chain");
+}
+
+sub delete_chain() {
+ my $self = shift;
+ my $table = shift || croak '[*] Must specify a table, e.g. "filter".';
+ my $jump_from_chain = shift ||
+ croak '[*] Must specify a chain from which ',
+ 'packets were jumped to this chain';
+ my $del_chain = shift || croak '[*] Must specify a chain to delete.';
+ my $iptables = $self->{'_iptables'};
+
+ ### see if the chain exists first
+ my ($rv, $out_aref, $err_aref) = $self->chain_exists($table, $del_chain);
+
+ ### return true if the chain doesn't exist (it is not an error condition)
+ return 1, $out_aref, $err_aref unless $rv;
+
+ ### flush the chain
+ ($rv, $out_aref, $err_aref)
+ = $self->flush_chain($table, $del_chain, $iptables);
+
+ ### could not flush the chain
+ return 0, $out_aref, $err_aref unless $rv;
+
+ ### find and delete jump rules to this chain (we can't delete
+ ### the chain until there are no references to it)
+ my ($rulenum, $num_chain_rules)
+ = $self->find_ip_rule('0.0.0.0/0',
+ '0.0.0.0/0', $table, $jump_from_chain, $del_chain, {});
+
+ if ($rulenum) {
+ $self->run_ipt_cmd(
+ "$iptables -t $table -D $jump_from_chain $rulenum");
+ }
+
+ ### note that we try to delete the chain now regardless
+ ### of whether their were jump rules above (should probably
+ ### parse for the "0 references" under the -nL <chain> output).
+ return $self->run_ipt_cmd("$iptables -t $table -X $del_chain");
+}
+
+sub add_ip_rule() {
+ my $self = shift;
+ my $src = shift || croak '[-] Must specify a src address/network.';
+ my $dst = shift || croak '[-] Must specify a dst address/network.';
+ my $rulenum = shift || croak '[-] Must specify an insert rule number.';
+ my $table = shift || croak '[-] Must specify a table, e.g. "filter".';
+ my $chain = shift || croak '[-] Must specify a chain.';
+ my $target = shift ||
+ croak '[-] Must specify a iptables target, e.g. "DROP"';
+ ### optionally add port numbers and protocols, etc.
+ my $extended_href = shift || {};
+ my $iptables = $self->{'_iptables'};
+
+ ### normalize src/dst if necessary; this is because iptables
+ ### always reports network address for subnets
+ my $normalized_src = $self->normalize_net($src);
+ my $normalized_dst = $self->normalize_net($dst);
+
+ ### first check to see if this rule already exists
+ my ($rule_position, $num_chain_rules)
+ = $self->find_ip_rule($normalized_src, $normalized_dst, $table,
+ $chain, $target, $extended_href);
+
+ if ($rule_position) {
+ my $msg = '';
+ if ($extended_href) {
+ $msg = "Table: $table, chain: $chain, $normalized_src -> " .
+ "$normalized_dst ";
+ for my $key qw(protocol s_port d_port) {
+ $msg .= "$key $extended_href->{$key} "
+ if defined $extended_href->{$key};
+ }
+ $msg .= 'rule already exists.';
+ } else {
+ $msg = "Table: $table, chain: $chain, $normalized_src -> " .
+ "$normalized_dst rule already exists.";
+ }
+ return 1, [$msg], [];
+ }
+
+ ### we need to add the rule
+ my $ipt_cmd = '';
+ my $msg = '';
+ my $idx_err = '';
+
+ ### check to see if the insertion index ($rulenum) is too big
+ $rulenum = 1 if $rulenum <= 0;
+ if ($rulenum > $num_chain_rules+1) {
+ $idx_err = "Rule position $rulenum is past end of $chain " .
+ "chain ($num_chain_rules rules), compensating."
+ if $num_chain_rules > 0;
+ $rulenum = $num_chain_rules + 1;
+ }
+ $rulenum = 1 if $rulenum == 0;
+
+ if ($extended_href) {
+ $ipt_cmd = "$iptables -t $table -I $chain $rulenum ";
+ $ipt_cmd .= "-p $extended_href->{'protocol'} "
+ if defined $extended_href->{'protocol'};
+ $ipt_cmd .= "-s $normalized_src ";
+ $ipt_cmd .= "--sport $extended_href->{'s_port'} "
+ if defined $extended_href->{'s_port'};
+ $ipt_cmd .= "-d $normalized_dst ";
+ $ipt_cmd .= "--dport $extended_href->{'d_port'} "
+ if defined $extended_href->{'d_port'};
+ $ipt_cmd .= "-j $target";
+
+ $msg = "Table: $table, chain: $chain, added $normalized_src " .
+ "-> $normalized_dst ";
+ for my $key qw(protocol s_port d_port) {
+ $msg .= "$key $extended_href->{$key} "
+ if defined $extended_href->{$key};
+ }
+
+ ### for NAT
+ if (defined $extended_href->{'to_ip'} and
+ defined $extended_href->{'to_port'}) {
+ $ipt_cmd .= " --to $extended_href->{'to_ip'}:" .
+ "$extended_href->{'to_port'}";
+ $msg .= "$extended_href->{'to_ip'}:$extended_href->{'to_port'}";
+ }
+
+ $msg =~ s/\s*$//;
+ } else {
+ $ipt_cmd = "$iptables -t $table -I $chain $rulenum " .
+ "-s $normalized_src -d $normalized_dst -j $target";
+ $msg = "Table: $table, chain: $chain, added $normalized_src " .
+ "-> $normalized_dst";
+ }
+ my ($rv, $out_aref, $err_aref) = $self->run_ipt_cmd($ipt_cmd);
+ if ($rv) {
+ push @$out_aref, $msg if $msg;
+ }
+ push @$err_aref, $idx_err if $idx_err;
+ return $rv, $out_aref, $err_aref;
+}
+
+sub delete_ip_rule() {
+ my $self = shift;
+ my $src = shift || croak '[-] Must specify a src address/network.';
+ my $dst = shift || croak '[-] Must specify a dst address/network.';
+ my $table = shift || croak '[-] Must specify a table, e.g. "filter".';
+ my $chain = shift || croak '[-] Must specify a chain.';
+ my $target = shift ||
+ croak '[-] Must specify a iptables target, e.g. "DROP"';
+ ### optionally add port numbers and protocols, etc.
+ my $extended_href = shift || {};
+ my $iptables = $self->{'_iptables'};
+
+ ### normalize src/dst if necessary; this is because iptables
+ ### always reports network address for subnets
+ my $normalized_src = $self->normalize_net($src);
+ my $normalized_dst = $self->normalize_net($dst);
+
+ ### first check to see if this rule already exists
+ my ($rulenum, $num_chain_rules)
+ = $self->find_ip_rule($normalized_src,
+ $normalized_dst, $table, $chain, $target, $extended_href);
+
+ if ($rulenum) {
+ ### we need to delete the rule
+ return $self->run_ipt_cmd("$iptables -t $table -D $chain $rulenum");
+ }
+
+ my $extended_msg = '';
+ if ($extended_href) {
+ for my $key qw(protocol s_port d_port) {
+ $extended_msg .= "$key: $extended_href->{$key} "
+ if defined $extended_href->{$key};
+ }
+ ### for NAT
+ if (defined $extended_href->{'to_ip'} and
+ defined $extended_href->{'to_port'}) {
+ $extended_msg .= "$extended_href->{'to_ip'}:" .
+ "$extended_href->{'to_port'}";
+ }
+ }
+ $extended_msg =~ s/\s*$//;
+ return 0, [], ["Table: $table, chain: $chain, rule $normalized_src " .
+ "-> $normalized_dst $extended_msg does not exist."];
+}
+
+sub find_ip_rule() {
+ my $self = shift;
+ my $src = shift || croak '[*] Must specify source address.';
+ my $dst = shift || croak '[*] Must specify destination address.';
+ my $table = shift || croak '[*] Must specify iptables table.';
+ my $chain = shift || croak '[*] Must specify iptables chain.';
+ my $target = shift ||
+ croak '[*] Must specify iptables target (this may be a chain).';
+ ### optionally add port numbers and protocols, etc.
+ my $extended_href = shift || {};
+ my $iptables = $self->{'_iptables'};
+
+ my $ipt_parse = new IPTables::Parse('iptables' => $iptables)
+ or croak "[*] Could not acquire IPTables::Parse object";
+
+ my $chain_aref = $ipt_parse->chain_rules($table, $chain);
+
+ my $rulenum = 1;
+ for my $rule_href (@$chain_aref) {
+ if ($rule_href->{'target'} eq $target
+ and $rule_href->{'src'} eq $src
+ and $rule_href->{'dst'} eq $dst) {
+ if ($extended_href) {
+ my $found = 1;
+ for my $key qw(
+ protocol
+ s_port
+ d_port
+ to_ip
+ to_port
+ ) {
+ if (defined $extended_href->{$key}) {
+ unless ($extended_href->{$key}
+ eq $rule_href->{$key}) {
+ $found = 0
+ }
+ }
+ }
+ return $rulenum, $#$chain_aref+1 if $found;
+ } else {
+ if ($rule_href->{'protocol'} eq 'all') {
+ if ($target eq 'LOG' or $target eq 'ULOG') {
+ ### built-in LOG and ULOG target rules always
+ ### have extended information
+ return $rulenum, $#$chain_aref+1;
+ } elsif (not $rule_href->{'extended'}) {
+ ### don't want any additional criteria (such as
+ ### port numbers) in the rule. Note that we are
+ ### also not checking interfaces
+ return $rulenum, $#$chain_aref+1;
+ }
+ }
+ }
+ }
+ $rulenum++;
+ }
+ return 0, $#$chain_aref+1;
+}
+
+sub normalize_net() {
+ my $self = shift;
+ my $net = shift || croak '[*] Must specify net.';
+
+ ### regex to match an IP address
+ my $ip_re = '(?:\d{1,3}\.){3}\d{1,3}';
+
+ my $normalized_net = '';
+ if ($net =~ m|($ip_re)/($ip_re)|) {
+ my ($net_addr, $cidr) = ipv4_network($1, $2);
+ $normalized_net = "$net_addr/$cidr";
+ } elsif ($net =~ m|($ip_re)/(\d+)|) {
+ my ($net_addr, $cidr) = ipv4_network($1, $2);
+ $normalized_net = "$net_addr/$cidr";
+ } else {
+ ### it is a hostname or an individual IP
+ $normalized_net = $net;
+ }
+ return $normalized_net;
+}
+
+sub add_jump_rule() {
+ my $self = shift;
+ my $table = shift || croak '[-] Must specify a table, e.g. "filter".';
+ my $from_chain = shift || croak '[-] Must specify chain to jump from.';
+ my $rulenum = shift || croak '[-] Must specify jump rule chain position';
+ my $to_chain = shift || croak '[-] Must specify chain to jump to.';
+ my $iptables = $self->{'_iptables'};
+ my $idx_err = '';
+
+ if ($from_chain eq $to_chain) {
+ return 0, ["Identical from_chain and to_chain ($from_chain) " .
+ "not allowed."], [];
+ }
+
+ ### first check to see if the jump rule already exists
+ my ($rule_position, $num_chain_rules)
+ = $self->find_ip_rule('0.0.0.0/0', '0.0.0.0/0', $table,
+ $from_chain, $to_chain, {});
+
+ ### check to see if the insertion index ($rulenum) is too big
+ $rulenum = 1 if $rulenum <= 0;
+ if ($rulenum > $num_chain_rules+1) {
+ $idx_err = "Rule position $rulenum is past end of $from_chain " .
+ "chain ($num_chain_rules rules), compensating."
+ if $num_chain_rules > 0;
+ $rulenum = $num_chain_rules + 1;
+ }
+ $rulenum = 1 if $rulenum == 0;
+
+ if ($rule_position) {
+ ### the rule already exists
+ return 1,
+ ["Table: $table, chain: $to_chain, jump rule already exists."], [];
+ }
+
+ ### we need to add the rule
+ my ($rv, $out_aref, $err_aref) = $self->run_ipt_cmd(
+ "$iptables -t $table -I $from_chain $rulenum -j $to_chain");
+ push @$err_aref, $idx_err if $idx_err;
+ return $rv, $out_aref, $err_aref;
+}
+
+sub REAPER {
+ my $stiff;
+ while(($stiff = waitpid(-1,WNOHANG))>0){
+ # do something with $stiff if you want
+ }
+ local $SIG{'CHLD'} = \&REAPER;
+ return;
+}
+
+
+sub run_ipt_cmd() {
+ my $self = shift;
+ my $cmd = shift || croak '[*] Must specify an iptables command to run.';
+ my $iptables = $self->{'_iptables'};
+ my $iptout = $self->{'_iptout'};
+ my $ipterr = $self->{'_ipterr'};
+ my $debug = $self->{'_debug'};
+ my $verbose = $self->{'_verbose'};
+ croak "[*] $cmd does not look like an iptables command."
+ unless $cmd =~ m|^\s*iptables| or $cmd =~ m|^\S+/iptables|;
+
+ my $fh = *STDERR;
+ $fh = *STDOUT if $verbose;
+
+ if ($debug or $verbose) {
+ print $fh localtime() . " [+] IPTables::ChainMgr::run_ipt_cmd() $cmd\n";
+ }
+
+ my $ipt_pid;
+
+ local $SIG{'CHLD'} = \&REAPER;
+ if ($ipt_pid = fork()) {
+ local $SIG{'ALRM'} = sub {die "[*] iptables command timeout.\n"};
+ ### iptables should never take longer than 60 seconds to execute,
+ ### unless there is some absolutely enormous policy or the kernel
+ ### is exceedingly busy
+ alarm 60;
+ eval {
+ waitpid($ipt_pid, 0);
+ };
+ alarm 0;
+ if ($@) {
+ kill 9, $ipt_pid unless kill 15, $ipt_pid;
+ }
+ } else {
+ die "[*] Could not fork iptables: $!"
+ unless defined $ipt_pid;
+
+ ### exec the iptables command and preserve stdout and stderr
+ exec qq{$cmd > $iptout 2> $ipterr};
+ }
+
+ my $rv = 1;
+ my @stdout = ();
+ my @stderr = ();
+
+ if (-e $iptout) {
+ open F, "< $iptout" or croak "[*] Could not open $iptout";
+ @stdout = <F>;
+ close F;
+ }
+ if (-e $ipterr) {
+ open F, "< $ipterr" or croak "[*] Could not open $ipterr";
+ @stderr = <F>;
+ close F;
+
+ $rv = 0 if @stderr;
+ }
+
+ if ($debug or $verbose) {
+ print $fh localtime() . " iptables command stdout:\n";
+ for my $line (@stdout) {
+ if ($line =~ /\n$/) {
+ print $fh $line;
+ } else {
+ print $fh $line, "\n";
+ }
+ }
+ print $fh localtime() . " iptables command stderr:\n";
+ for my $line (@stderr) {
+ if ($line =~ /\n$/) {
+ print $fh $line;
+ } else {
+ print $fh $line, "\n";
+ }
+ }
+ }
+
+ return $rv, \@stdout, \@stderr;
+}
+
+1;
+
+__END__
+# Below is stub documentation for your module. You'd better edit it!
+
+=head1 NAME
+
+IPTables::ChainMgr - Perl extension for manipulating iptables policies
+
+=head1 SYNOPSIS
+
+ use IPTables::ChainMgr;
+
+ my %opts = (
+ 'iptables' => '/sbin/iptables',
+ 'iptout' => '/tmp/iptables.out',
+ 'ipterr' => '/tmp/iptables.err',
+ 'debug' => 0,
+ 'verbose' => 0
+ );
+
+ my $ipt_obj = new IPTables::ChainMgr(%opts)
+ or die "[*] Could not acquire IPTables::ChainMgr object";
+
+ my $rv = 0;
+ my $out_ar = [];
+ my $errs_ar = [];
+
+ # check to see if the 'CUSTOM' chain exists in the filter table
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->chain_exists('filter', 'CUSTOM');
+ if ($rv) {
+ print "CUSTOM chain exists.\n";
+
+ ### flush all rules from the chain
+ $ipt_obj->flush_chain('filter', 'CUSTOM');
+
+ ### now delete the chain
+ $ipt_obj->delete_chain('filter', 'CUSTOM');
+ }
+
+ # create new iptables chain in the 'filter' table
+ $ipt_obj->create_chain('filter', 'CUSTOM');
+
+ # add rule to jump packets from the INPUT chain into CUSTOM at the
+ # 4th rule position
+ $ipt_obj->add_jump_rule('filter', 'INPUT', 4, 'CUSTOM');
+
+ # find rule that allows all traffic from 10.1.2.3 to 192.168.1.2
+ ($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.3', '192.168.1.2',
+ 'filter', 'INPUT', 'ACCEPT', {});
+
+ # find rule that allows all TCP port 80 traffic from 10.1.2.3 to
+ # 192.168.1.1
+ ($rv, $rule_num) = $ipt_obj->find_ip_rule('10.1.2.3', '192.168.1.2',
+ 'filter', 'INPUT', 'ACCEPT', {'protocol' => 'tcp', 's_port' => 0,
+ 'd_port' => 80});
+
+ # add rule at the 5th rule position to allow all traffic from
+ # 10.1.2.3 to 192.168.1.2 via the INPUT chain in the filter table
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.3',
+ '192.168.1.2', 5, 'filter', 'INPUT', 'ACCEPT', {});
+
+ # add rule at the 4th rule position to allow all traffic from
+ # 10.1.2.3 to 192.168.1.2 via the CUSTOM chain in the filter table
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->add_ip_rule('10.1.2.3',
+ '192.168.1.2', 5, 'filter', 'CUSTOM', 'ACCEPT',
+ {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
+
+ # run an arbitrary iptables command and collect the output
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->run_ipt_cmd(
+ '/sbin/iptables -v -n -L');
+
+=head1 DESCRIPTION
+
+The C<IPTables::ChainMgr> package provide an interface to manipulate iptables
+policies on Linux systems through the direct execution of iptables commands.
+Although making a perl extension of libiptc provided by the iptables project is
+possible (and has been done by the FIXME module), it is easy to just execute
+iptables commands directly in order to both parse and change the configuration of
+the policy. Further, this simplifies installation since the only external
+requirement is (in the spirit of scripting) to be able to point IPTables::ChainMgr
+at an installed iptables binary instead of having to compile against a library.
+
+=head1 FUNCTIONS
+
+The IPTables::ChainMgr extension provides an object interface to the following
+functions:
+
+=over 4
+
+=item chain_exists($table, $chain)
+
+This function tests whether or not a chain (e.g. 'INPUT') exists within the
+specified table (e.g. 'filter'). This is most useful to test whether
+a custom chain has been added to the running iptables policy. The return values
+are (as with many IPTables::ChainMgr functions) an array of three things: a
+numeric value, and both the stdout and stderr of the iptables command in the
+form of array references. So, an example invocation of the chain_exists()
+function would be:
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->chain_exists('filter', 'CUSTOM');
+
+If $rv is 1, then the CUSTOM chain exists in the filter table, and 0 otherwise.
+The $out_ar array reference contains the output of the command "/sbin/iptables -t filter -v -n -L CUSTOM",
+which will contain the rules in the CUSTOM chain (if it exists) or nothing (if not).
+The $errs_ar array reference contains the stderr of the iptables command.
+
+=item create_chain($table, $chain)
+
+This function creates a chain within the specified table. Again, three return
+values are given like so:
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->create_chain('filter', 'CUSTOM');
+
+Behind the scenes, the create_chain() function in the example above runs the
+iptables command "/sbin/iptables -t filter -N CUSTOM".
+
+=item flush_chain($table, $chain)
+
+This function flushes all rules from chain in the specified table, and three
+values are returned:
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->flush_chain('filter', 'CUSTOM');
+
+The flush_chain() function in the example above executes the iptables command
+"/sbin/iptables -t filter -F CUSTOM"
+
+=item delete_chain($table, $chain)
+
+This function deletes a chain from the specified table:
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->delete_chain('filter', 'CUSTOM');
+
+Internally a check is performed to see whether the chain exists within
+the table, and global jump rules from other chains within the table that
+reference the specified chain are also deleted (a chain cannot be deleted
+until there are no references to it).
+
+=item find_ip_rule($src, $dst, $table, $chain, $target, %extended_info)
+
+This function parses the specified chain to see if there is a rule that
+matches the $src, $dst, $target, and (optionally) any %extended_info
+criteria. The return values are the rule number in the chain (or zero
+if it doesn't exist), and the total number of rules in the chain. Below
+are two examples; the first is to find an ACCEPT rule for 10.1.2.3 to
+communicate with 192.168.1.2 in the INPUT chain, and the second is the
+same except that the rule is restricted to TCP port 80:
+
+ ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.3',
+ '192.168.1.2', 'filter', 'INPUT', 'ACCEPT', {});
+ if ($rulenum) {
+ print "matched rule $rulenum out of $chain_rules rules\n";
+ }
+
+ ($rulenum, $chain_rules) = $ipt_obj->find_ip_rule('10.1.2.3',
+ '192.168.1.2', 'filter', 'INPUT', 'ACCEPT',
+ {'protocol' => 'tcp', 's_port' => 0, 'd_port' => 80});
+ if ($rulenum) {
+ print "matched rule $rulenum out of $chain_rules rules\n";
+ }
+
+=item add_ip_rule($src, $dst, $rulenum, $table, $chain, $target, %extended_info)
+
+This function inserts a rule into the running iptables chain and table at the
+specified rule number. Return values are success or failure along with the
+iptables stdout and stderr.
+
+=item delete_ip_rule($src, $dst, $table, $chain, $target, %extended_info)
+
+This function searches for and then deletes a matching rule within the
+specified chain. Return values are success or failure along with the
+iptables stdout and stderr.
+
+=item add_jump_rule($table, $from_chain, $rulenum, $to_chain)
+
+This function adds a jump rule (after making sure it doesn't already exist)
+into the specified chain. The $rulenum variable tells the function where
+within the calling chain the new jump rule should be placed. Here is an
+example to force all packets regardless of source or destination to be
+jumped to the CUSTOM chain from the INPUT chain at rule 4:
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->add_jump_rule('filter', 'INPUT', 4, 'CUSTOM');
+
+=item run_ipt_cmd($cmd)
+
+This function is a generic work horse function for executing iptables commands,
+and is used internally by IPTables::ChainMgr functions. It can also be used by
+a script that imports the IPTables::ChainMgr extension to provide a consistent
+mechanism for executing iptables. Three return values are given: success (1)
+or failure (0) of the iptables command (yes, this backwards from the normal
+exit status of Linux/*NIX binaries), and array references to the iptables stdout
+and stderr. Here is an example to list all rules in the user-defined chain
+"CUSTOM":
+
+ ($rv, $out_ar, $errs_ar) = $ipt_obj->run_ipt_cmd('/sbin/iptables -t filter -v -n -L CUSTOM');
+ if ($rv) {
+ print "rules:\n";
+ print for @$out_ar;
+ }
+
+=back
+
+
+=head1 SEE ALSO
+
+The IPTables::ChainMgr extension is closely associated with the IPTables::Parse
+extension, and both are heavily used by the psad, fwsnort, and fwknop projects
+to manipulate iptables policies based on various criteria (see the psad(8),
+fwsnort(8), and fwknop(8) man pages). As always, the iptables(8) provides the
+best information on command line execution and theory behind iptables.
+
+Although there is no mailing that is devoted specifically to the IPTables::ChainMgr
+extension, questions about the extension will be answered on the following
+lists:
+
+ The psad mailing list: http://lists.sourceforge.net/lists/listinfo/psad-discuss
+ The fwknop mailing list: http://lists.sourceforge.net/lists/listinfo/fwknop-discuss
+ The fwsnort mailing list: http://lists.sourceforge.net/lists/listinfo/fwsnort-discuss
+
+The latest version of the IPTables::ChainMgr extension can be found at:
+
+http://www.cipherdyne.org/modules/
+
+=head1 CREDITS
+
+Thanks to the following people:
+
+ Franck Joncourt <franck.mail at dthconnex.com>
+ Grant Ferley
+
+=head1 AUTHOR
+
+The IPTables::ChainMgr extension was written by Michael Rash F<E<lt>mbr at cipherdyne.orgE<gt>>
+to support the psad, fwknop, and fwsnort projects. Please send email to
+this address if there are any questions, comments, or bug reports.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2005-2008 by Michael Rash
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.5 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
Added: libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/IPTables-ChainMgr.t
URL: http://svn.debian.org/wsvn/libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/IPTables-ChainMgr.t?rev=20567&op=file
==============================================================================
--- libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/IPTables-ChainMgr.t (added)
+++ libiptables-chainmgr-perl/branches/upstream/libiptables-chainmgr-perl/current/t/IPTables-ChainMgr.t Sun Jun 1 12:10:01 2008
@@ -1,0 +1,6 @@
+### make sure we can load the module
+
+use Test;
+BEGIN { plan tests => 1 };
+use IPTables::ChainMgr;
+ok(1); # If we made it this far, we're ok.
More information about the Pkg-perl-cvs-commits
mailing list