209 lines
5.7 KiB
Perl
209 lines
5.7 KiB
Perl
#!/usr/bin/perl -w
|
|
use strict;
|
|
|
|
my $RULESDIR = "rules";
|
|
my $STATUSFILE = "$RULESDIR/status";
|
|
|
|
unless (-f $STATUSFILE) {
|
|
print ">> NO STATUS FILE!\nI will reset Firewall to defaults and write a new minimal status file. After that I'll proceed as normal.\n";
|
|
open FILE, ">$STATUSFILE";
|
|
printf FILE "RUNNING 0";
|
|
close FILE;
|
|
stop();
|
|
print "Reset done successfully. Proceeding...\n";
|
|
}
|
|
|
|
my @GLOBAL_CHAINS = qw/INPUT OUTPUT/;
|
|
|
|
my @FILES;
|
|
my @files = glob("$RULESDIR/*");
|
|
foreach my $global (@GLOBAL_CHAINS) {
|
|
foreach my $file (@files) {
|
|
if ($file =~ /^.*\/$global[0-9_]*_[ a-zA-Z0-9_-]*$/) {
|
|
push (@FILES, $file);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
my $ACTION = $ARGV[0];
|
|
unless ($ARGV[0]) { wrong_syntax(); }
|
|
if ($ACTION =~ /^start$/) { if (running() == 0) { start(); } else { print ">> FIREWALL ALREADY STARTED!\n"; } exit 0; }
|
|
elsif ($ACTION =~ /^stop$/) { if (running()) { stop(); } else { print ">> FIREWALL ALREADY STOPPED!\n"; } exit 0; }
|
|
elsif ($ACTION =~ /^reload$/) { if (running()) { stop(); start(); } else { start(); } exit 0; }
|
|
elsif ($ACTION =~ /^restart$/) { if (running()) { stop(); start(); } else { start(); } exit 0; }
|
|
elsif ($ACTION =~ /^status$/) { if (running()) { print ">> FIREWALL RUNNING!\n"; } else { print ">> FIREWALL NOT RUNNING!\n"; } exit 0; }
|
|
elsif ($ACTION =~ /^detail$/) { my @d=`iptables -nvL`; print @d; exit 0; }
|
|
else { wrong_syntax(); exit 0; }
|
|
|
|
sub running {
|
|
if(read_status_file("RUNNING")) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
sub read_status_file {
|
|
my $para = $_[0];
|
|
open FILE, "<$STATUSFILE";
|
|
my @lines = <FILE>;
|
|
close FILE;
|
|
my $value="";
|
|
foreach my $line (@lines) {
|
|
$line = format_lines($line);
|
|
next if($line =~ /^#/);
|
|
if ($line =~ /^$para/) {
|
|
(undef, $value) = split / /, $line;
|
|
}
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
sub write_status_file {
|
|
my ($para, $value) = @_;
|
|
my $file = "$STATUSFILE";
|
|
my $written = 0;
|
|
|
|
open FILE, "<$STATUSFILE";
|
|
my @lines = <FILE>;
|
|
close FILE;
|
|
|
|
open FILE, ">$file";
|
|
foreach my $line (@lines) {
|
|
$line = format_lines($line);
|
|
my ($old_para, $old_value) = split / /, $line;
|
|
if ($old_para eq $para) {
|
|
printf FILE "$para $value\n";
|
|
$written = 1;
|
|
} else {
|
|
printf FILE "$line\n";
|
|
}
|
|
}
|
|
printf FILE "$para $value\n" unless ($written);
|
|
close FILE;
|
|
}
|
|
|
|
|
|
sub start {
|
|
print ">> STARTING FIREWALL!\n";
|
|
# policy INPUT und OUTPUT auf DROP
|
|
my $iptables;
|
|
foreach my $chain (@GLOBAL_CHAINS) {
|
|
$iptables = "iptables -P $chain DROP";
|
|
#print "$iptables\n";
|
|
`$iptables`;
|
|
}
|
|
# Dateien parsen
|
|
foreach my $file (@FILES) {
|
|
# Regeln erstellen
|
|
process_chainfile ($file);
|
|
}
|
|
write_status_file("RUNNING", "1");
|
|
}
|
|
|
|
|
|
sub stop {
|
|
print ">> STOPPING FIREWALL!\n";
|
|
my $iptables = "iptables -F";
|
|
`$iptables`;
|
|
$iptables = "iptables -X";
|
|
`$iptables`;
|
|
foreach my $chain (@GLOBAL_CHAINS) {
|
|
$iptables = "iptables -P $chain ACCEPT";
|
|
`$iptables`;
|
|
}
|
|
write_status_file("RUNNING", "0");
|
|
}
|
|
|
|
|
|
sub wrong_syntax {
|
|
print "Syntax:\n $0 [start|stop|restart|reload|detail]\n";
|
|
exit 1;
|
|
}
|
|
|
|
|
|
sub process_chainfile {
|
|
my $file = $_[0];
|
|
my ($chain, $nr, $comment) = split /_/, $file;
|
|
my @tmp = split /\//, $chain;
|
|
$chain = $tmp[-1];
|
|
open FILE, "<$file";
|
|
my @lines = <FILE>;
|
|
close FILE;
|
|
create_chain("$chain-$nr", $chain, "$comment");
|
|
foreach my $line (@lines) {
|
|
$line = format_lines($line);
|
|
next if($line =~ /^#/);
|
|
next if($line =~ /^$/); # action prot sip sport dip dport comment
|
|
# deny tcp www.agadmin.de 123 localhost 456 #testregel 1
|
|
my ($action, $proto, $s_ip, $s_port, $d_ip, $d_port, undef, $comment) = $line =~ /([a-z0-9]*) ([!a-z0-9]*) ([!a-z0-9\/.]*) ([a-z0-9]*) ([!a-z0-9\/\.]*) ([a-z0-9]*)( (#.*))/i;
|
|
#print "$action, $proto, $s_ip, $s_port, $d_ip, $d_port, $comment\n";
|
|
$comment =~ s/#//;
|
|
create_rule("$chain-$nr", $s_ip, $s_port, $d_ip, $d_port, $proto, $action, "$comment");
|
|
}
|
|
}
|
|
|
|
sub create_chain {
|
|
my ($chain, $parent_chain, $comment) = @_;
|
|
my $iptables = "iptables -N $chain ";
|
|
`$iptables`;
|
|
$iptables = "iptables -A $parent_chain -j $chain -m comment --comment \"$comment\"";
|
|
`$iptables`;
|
|
}
|
|
|
|
sub create_rule {
|
|
my ($chain, $source_ip, $source_port, $dest_ip, $dest_port, $proto, $action, $comment) = @_;
|
|
my $iptables;
|
|
$source_port = 0 if($source_port =~ /any/i);
|
|
$dest_port = 0 if($dest_port =~ /any/i);
|
|
$source_ip = "0.0.0.0/0" if($source_ip =~ /any/i);
|
|
$dest_ip = "0.0.0.0/0" if($dest_ip =~ /any/i);
|
|
$action = "ACCEPT" if($action =~ /permit/i);
|
|
$action = "DROP" if($action =~ /deny/i);
|
|
|
|
$iptables = "iptables -A $chain ";
|
|
my $neg;
|
|
if ($proto) {
|
|
if ($proto =~ /^!/) {
|
|
$iptables .= "! ";
|
|
}
|
|
$proto =~ s/!//;
|
|
$iptables .= "-p $proto ";
|
|
}
|
|
|
|
if ($source_ip) {
|
|
if ($source_ip =~ /^!/) {
|
|
$iptables .= "! ";
|
|
}
|
|
$source_ip =~ s/!//;
|
|
$iptables .= "-s $source_ip ";
|
|
}
|
|
|
|
$iptables .= "--sport $source_port " if ($source_port);
|
|
|
|
if ($dest_ip) {
|
|
if ($dest_ip =~ /^!/) {
|
|
$iptables .= "! ";
|
|
}
|
|
$dest_ip =~ s/!//;
|
|
$iptables .= "-d $dest_ip ";
|
|
}
|
|
|
|
$iptables .= "--dport $dest_port " if ($dest_port);
|
|
$iptables .= "-j $action ";
|
|
$iptables .= "-m comment --comment \"$comment\"";
|
|
print "$iptables\n";
|
|
`$iptables`;
|
|
}
|
|
|
|
|
|
sub format_lines {
|
|
my $line = $_[0];
|
|
chomp $line;
|
|
$line =~ s/^\s+|\s+$//g ;
|
|
$line =~ s/(\s)+/ /g;
|
|
#$line =~ tr/[a-z]/[A-Z]/;
|
|
return $line;
|
|
}
|