DOSC TWiki snapshot as of mid-2005
I didn't like, or really understand :), the default redhat iptables script, so I started my own in perl. I have a feeling perl was wild overkill, but whatever. This understands a very simple configuration file; here is mine:
#####################BEGIN################## iptables "/sbin/iptables" tcp_public "22,113" udp_public "" tcp_dartmouth "913" udp_dartmouth "" tcp_reject_public "1080" udp_reject_public "" tcp_reject_dartmouth "445" udp_reject_dartmouth "" dartmouth "129.170.0.0/16" ntp_conf "/etc/ntp.conf" open_ntp true ################END####################The location for this is /etc/sysconfig/iptablesnew. This example allows connections to 22 and 113 tcp from anywhere, to 913 tcp from 129.170.0.0./16 only, and sends tcp rsts on 1080 from everywhere, and 445 from 129.170.0.0/16 only. It also makes appropriate rules for
server xxxxx lines in /etc/ntp.conf. The code is super super alpha and maybe doesn't even work; it's more for people to comment on/add to at this point.
Hint: set iptables to "/bin/echo" to test it.
Ok, the attachment mechanism baffles me so I'm going to post this thing directly:
########################BEGIN#########################
#!/usr/bin/perl
use strict;
use warnings;
sub true () {1};
sub false () {undef};
%ENV=();
usage() unless @ARGV == 1;
our $config_file = "/etc/sysconfig/iptablesnew";
our %config;
for (qw/iptables
tcp_public
udp_public
tcp_dartmouth
udp_dartmouth
tcp_reject_public
tcp_reject_dartmouth
udp_reject_public
udp_reject_dartmouth
dartmouth
ntp_conf
open_ntp/) {
no strict 'refs';
*$_ = \$config{$_};
}
our $iptables;
our $tcp_public;
our $udp_public;
our $tcp_dartmouth;
our $udp_dartmouth;
our $tcp_reject_public;
our $tcp_reject_dartmouth;
our $udp_reject_public;
our $udp_reject_dartmouth;
our $dartmouth;
our $ntp_conf;
our $open_ntp;
our %funcs = (
start => \&start,
stop => \&stop,
restart => \&restart,
#save => \&save
);
our $command = shift;
#($command) = $command =~ /(.*)/;
usage() unless exists $funcs{$command};
load();
exit $funcs{$command}->();
no strict 'vars';
sub start {
flush();
print "Starting iptables: ";
my @lines = (
"$iptables -N ALF",
"$iptables -N ALF-TCP",
"$iptables -N ALF-UDP",
"$iptables -N ALF-ICMP",
"$iptables -N ALF-OTHER",
"$iptables -A INPUT -j ALF",
"$iptables -A ALF -m state --state ESTABLISHED,RELATED -j ACCEPT",
"$iptables -A ALF -i lo -j ACCEPT",
"$iptables -A ALF -p tcp -j ALF-TCP",
"$iptables -A ALF -p udp -j ALF-UDP",
"$iptables -A ALF -p icmp -j ALF-ICMP",
"$iptables -A ALF -j ALF-OTHER",
);
my $alf_tcp = "-A ALF-TCP -p tcp --syn";
push @lines, "$iptables $alf_tcp -m multiport --dports $tcp_public -j ACCEPT"
if $tcp_public;
push @lines, "$iptables $alf_tcp -s $dartmouth -m multiport --dports $tcp_dartmouth -j ACCEPT"
if $tcp_dartmouth;
push @lines, "$iptables $alf_tcp -m multiport --dports $tcp_reject_public -j REJECT --reject-with tcp-reset"
if $tcp_reject_public;
push @lines, "$iptables $alf_tcp -s $dartmouth -m multiport --dports $tcp_reject_dartmouth -j REJECT --reject-with tcp-reset"
if $tcp_reject_public;
push @lines, "$iptables $alf_tcp -j DROP";
my $alf_udp = "-A ALF-UDP -p udp";
push @lines, "$iptables $alf_udp -m multiport --dports $udp_public -j ACCEPT"
if $udp_public;
push @lines, "$iptables $alf_udp -s $dartmouth -m multiport --dports $udp_dartmouth -j ACCEPT"
if $udp_dartmouth;
if ($open_ntp) {
for my $server (parse_ntp()) {
push @lines, "$iptables $alf_udp -s $server --sport ntp --dport ntp -j ACCEPT";
}
}
push @lines, "$iptables $alf_udp -m multiport --dports $udp_reject_public -j REJECT"
if $udp_reject_public;
push @lines, "$iptables $alf_udp -s $dartmouth -m multiport --dports $udp_reject_dartmouth -j REJECT"
if $udp_reject_dartmouth;
push @lines, "$iptables $alf_udp -j DROP";
push @lines, (
"$iptables -A ALF-ICMP -j DROP",
"$iptables -A ALF-OTHER -j DROP",
);
lockme();
my $ret = 0;
for (@lines) {
system $_;
$ret += $? >> 8;
}
if ($ret == 0) {
success();
return 0;
} else {
failure();
return 1;
}
}
sub parse_ntp {
open(IN, '<', $ntp_conf) or return;
my @ret;
while (<IN>) {
push @ret, $1 if (/^\s*?server\s+?(\S+)/);
}
close IN;
return @ret;
}
sub flush {
open (IN, '<', "/proc/net/ip_tables_names") or warn "Can't open /proc/net/ip_tables_names: $!\n", return 1;
my @tables = <IN>;
close IN;
print "Flushing rulesets: ";
my $ret = 0;
for (@tables) {
chomp;
system $iptables, '-t', $_, '-F';
$ret = $? >> 8;
last unless $ret == 0;
system $iptables, '-t', $_, '-X';
$ret = $? >> 8;
last unless $ret == 0;
}
$ret == 0 ? success() : failure();
return $ret;
}
sub stop {
unlock();
flush() == 0 ? 0 : 1;
}
sub restart {
if (stop() == 0) {
return start();
} else {
return 1;
}
}
sub success {
system("source /etc/init.d/functions; success");
print "\n";
}
sub failure {
system("source /etc/init.d/functions; failure");
print "\n";
}
sub lockme {
open(OUT, '>>', "/var/lock/subsys/iptables");
close OUT;
}
sub unlock {
unlink "/var/lock/subsys/iptables";
}
sub usage {
warn "Usage: $0 {start|stop|restart}\n";
exit 1;
}
sub load {
print "Reading iptables configuration: ";
open(IN, '<', $config_file)
or failure(), die "$0: Can't open $config_file for reading: $!\n";
while (<IN>) {
chomp;
next if /^\s*$/;
next if /^\s*#/;
my ($k, $v) = split ' ', $_, 2;
next unless defined $k && defined $v;
$config{$k} = eval $v;
failure(), die "$0: Reading $config_file: $@\n"
if $@;
}
close IN;
success();
}
############################END######################
AlexFerguson - 21 Mar 2003