Files
2024-10-14 00:08:40 +02:00

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;
}