#!/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 = ; 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 = ; 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 = ; 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; }