--On Thursday, June 28, 2007 09:52:50 AM -0700 Atom Powers
<atom.powers@gmail.com> wrote:
> I know people must be doing something to manage iptables, but I
> haven''t been able to find anything yet. ( My google-fu must be
weak
> today. )
>
> What are you using to manage your iptables?
We''re using puppet to add iptables rule fragments into a directory call
/etc/iptables.d. Puppet manages that directory (purges unknown files) and
when it adds or deletes something out of there, it run a script call
rebuild-iptables that creates a new iptables rule file:
modules/iptables/manifests/init.pp:
# $Id: iptables.pp 949 2007-02-24 08:35:18Z digant $
#
# Handles iptables concerns. See also ipt_fragment definition
define ipt_fragment($ensure) {
case $ensure {
absent: {
file { "/etc/iptables.d/$name":
ensure => absent,
}
}
present: {
file {
"/etc/iptables.d/$name":
source =>
"puppet://puppet/iptables/fragments/$name",
notify => Exec[rebuild_iptables];
}
}
}
}
class iptables {
package { "iptables":
ensure => present
}
exec { "rebuild_iptables":
command => "/usr/sbin/rebuild-iptables",
refreshonly => true,
require => Package["stanford-server"]
}
file { "/etc/iptables.d":
ensure => directory,
purge => true,
notify => Exec["rebuild_iptables"],
}
}
/usr/sbin/rebuild-iptables:
#!/usr/bin/perl -w
our $ID = q$Id: rebuild-iptables 344 2006-10-04 02:48:30Z digant $;
#
# rebuild-iptables -- Construct an iptables rules file from fragments.
#
# Written by Russ Allbery <rra@stanford.edu>
# Adapted by Digant C Kasundra <digant@stanford.edu>
# Copyright 2005, 2006 Board of Trustees, Leland Stanford Jr. University
#
# Constructs an iptables rules file from the prefix, standard, and suffix
# files in the iptables configuration area, adding any additional modules
# specified in the command line, and prints the resulting iptables rules to
# standard output (suitable for saving into /var/lib/iptables or some other
# appropriate location on the system).
##############################################################################
# Modules and declarations
##############################################################################
require 5.006;
use strict;
use Getopt::Long qw(GetOptions);
# Path to the iptables template area.
our $TEMPLATE = ''/afs/ir/service/jumpstart/data/iptables'';
##############################################################################
# Installation
##############################################################################
# Return the prefix
sub prefix {
my $data;
( $data = <<''END_OF_PREFIX'' ) =~ s/^\s+//gm;
*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT
:SUL -
-A INPUT -j SUL
-A SUL -i lo -j ACCEPT
END_OF_PREFIX
return $data;
}
# Return the suffix
sub suffix {
my $data;
( $data = <<''END_OF_SUFFIX'' ) =~ s/^\s+//gm;
# Rejects all remaining connections with port-unreachable errors.
-A SUL -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j REJECT
--reject-with icmp-port-unreachable
-A SUL -p udp -j REJECT --reject-with icmp-port-unreachable
COMMIT
END_OF_SUFFIX
return $data;
}
# Read in a file, processing includes as required. Returns the contents of
# the file as an array.
sub read_iptables {
my ($file) = @_;
my @data;
$file = $TEMPLATE . ''/'' . $file unless $file =~ m%^\.?/%;
local *MODULE;
open (MODULE, ''<'', $file) or die "$0: cannot open
$file: $!\n";
local $_;
while (<MODULE>) {
if (/^\s*include\s+(\S+)$/) {
my $included = $1;
$included = $TEMPLATE . ''/'' . $included
unless $included =~ m%^\.?/%;
if ($file eq $included) {
die "$0: include loop in $file, line $.\n";
}
push (@data, "\n");
push (@data, read_iptables ($included));
push (@data, "\n");
} elsif (/^\s*include\s/) {
die "$0: malformed include line in $file, line $.\n";
} else {
push (@data, $_);
}
}
close MODULE;
return @data;
}
# Write a file carefully.
sub write_iptables {
my ($file, @data) = @_;
open (NEW, "> $file.new") or die "$0: cannot create
$file.new: $!\n";
print NEW @data or die "$0: cannot write to $file.new:
$!\n";
close NEW or die "$0: cannot flush $file.new:
$!\n";
rename ("$file.new", $file)
or die "$0: cannot install new $file: $!\n";
}
# Install iptables on a Red Hat system. Takes the array containing the new
# iptables data.
sub install_redhat {
my (@data) = @_;
write_iptables (''/etc/sysconfig/iptables'', @data);
system("/sbin/service", "iptables",
"restart");
}
# Install iptables on a Debian system. Take the array containing the new
# iptables data.
sub install_debian {
my (@data) = @_;
unless (-d ''/etc/iptables'') {
mkdir (''/etc/iptables'', 0755)
or die "$0: cannot mkdir /etc/iptables: $!\n";
}
write_iptables ("/etc/iptables/general", @data);
system("/sbin/iptables-restore < /etc/iptables/general");
}
##############################################################################
# Main routine
##############################################################################
# Fix things up for error reporting.
$| = 1;
my $fullpath = $0;
$0 =~ s%.*/%%;
# Parse command-line options.
my ($help, $version);
Getopt::Long::config (''bundling'',
''no_ignore_case'');
GetOptions (''h|help'' => \$help,
''v|version'' => \$version) or exit 1;
if ($help) {
print "Feeding myself to perldoc, please wait....\n";
exec (''perldoc'', ''-t'', $fullpath);
} elsif ($version) {
my $version = join ('' '', (split ('' '',
$ID))[1..3]);
$version =~ s/,v\b//;
$version =~ s/(\S+)$/($1)/;
$version =~ tr%/%-%;
print $version, "\n";
exit;
}
my @modules;
if ( -d ''/etc/iptables.d'' ) {
@modules = </etc/iptables.d/*>;
}
# Concatenate everything together.
my @data;
push (@data, prefix());
push (@data, "\n");
for my $module (@modules) {
push (@data, read_iptables ($module));
push (@data, "\n");
}
push (@data, suffix());
if (-f ''/etc/debian_version'') {
install_debian (@data);
} elsif (-f ''/etc/redhat-release'') {
install_redhat (@data);
} else {
die "$0: cannot figure out whether this is Red Hat or Debian\n";
}
exit 0;
__END__
##############################################################################
# Documentation
##############################################################################
=head1 NAME
rebuild-iptables - Construct an iptables rules file from fragments
=head1 SYNOPSIS
rebuild-iptables [B<-hv>]
=head1 DESCRIPTION
B<rebuild-iptables> constructs an iptables configuration file by
concatenating
various modules found in F</etc/iptables.d>. The resulting iptables
configuration file is written to the appropriate file for either Red Hat or
Debian (determined automatically) and iptables is restarted.
Each module is just a text file located in the directory mentioned above
that
contains one or more iptables configuration lines (basically the arguments
to
an B<iptables> invocation), possibly including comments.
Along with the modules in the directory specified, a standard prefix and
suffix
is added.
Normally, the contents of each module are read in verbatim, but a module may
also contain the directive:
include <module>
on a separate line, where <module> is the path to another module to
include,
specified the same way as modules given on the command line (hence, either a
file name relative to F</afs/ir/service/jumpstart/data/iptables> or an
absolute path). Such a line will be replaced with the contents of the named
file. Be careful when using this directive to not create loops; files
including themselves will be detected, but more complex loops will not and
will result in infinite output.
=head1 OPTIONS
=over 4
=item B<-h>, B<--help>
Print out this documentation (which is done simply by feeding the script to
C<perldoc -t>).
=item B<-v>, B<--version>
Print out the version of B<rebuild-iptables> and exit.
=back
=head1 FILES
=over 4
=item B<-h>, B<--help>
Print out this documentation (which is done simply by feeding the script to
C<perldoc -t>).
=item B<-v>, B<--version>
Print out the version of B<rebuild-iptables> and exit.
=back
=head1 FILES
=over 4
=item F</etc/iptables.d>
The default module location.
=item F</etc/debian_version>
If this file exists, the system is assumed to be a Debian system for
determining the installation location when B<-i> is used.
=item F</etc/iptables/general>
The install location of the generated configuration file on Debian.
=item F</etc/redhat-release>
If this file exists, the system is assumed to be a Red Hat system for
determining the installation location when B<-i> is used.
=item F</etc/sysconfig/iptables>
The install location of the generated configuration file on Red Hat.
=back
=head1 AUTHOR
Russ Allbery <rra@stanford.edu>
Digant C Kasundra <digant@stanford.edu>
=head1 SEE ALSO
iptables(8)
=cut
--
Digant C Kasundra <digant@stanford.edu>
Technical Lead, ITS Unix Systems and Applications, Stanford University