From: Michael Tremer Date: Sat, 12 Apr 2014 13:16:08 +0000 (+0200) Subject: firewall: Fix creation of automatic rules for the firewall. X-Git-Url: http://git.ipfire.org/?p=people%2Fteissler%2Fipfire-2.x.git;a=commitdiff_plain;h=aa5f4b65685421555cf09eccb068890926512abd firewall: Fix creation of automatic rules for the firewall. If the firewall is part of a local network (e.g. GREEN), we automatically add rules that grant/forbid access for the firewall, too. This has been broken for various default policies other than ALLOWED. --- diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index 9f546a9ef..c4a19e5d8 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -520,6 +520,9 @@ sub get_internal_firewall_ip_address return 0; } + # Convert net mask into correct format for &General::IpInSubnet(). + $net_mask = &General::iporsubtodec($net_mask); + my @addresses = &get_internal_firewall_ip_addresses($use_orange); foreach my $zone_address (@addresses) { if (&General::IpInSubnet($zone_address, $net_address, $net_mask)) { diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 92f1c0a30..5bd7412e7 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -47,6 +47,7 @@ my @PROTOCOLS_WITH_PORTS = ("tcp", "udp"); my @VALID_TARGETS = ("ACCEPT", "DROP", "REJECT"); my %fwdfwsettings=(); +my %fwoptions = (); my %defaultNetworks=(); my %configfwdfw=();; my %customgrp=(); @@ -63,6 +64,7 @@ my $configgrp = "${General::swroot}/fwhosts/customgroups"; my $netsettings = "${General::swroot}/ethernet/settings"; &General::readhash("${General::swroot}/firewall/settings", \%fwdfwsettings); +&General::readhash("${General::swroot}/optionsfw/settings", \%fwoptions); &General::readhash("$netsettings", \%defaultNetworks); &General::readhasharray($configfwdfw, \%configfwdfw); &General::readhasharray($configinput, \%configinputfw); @@ -71,6 +73,14 @@ my $netsettings = "${General::swroot}/ethernet/settings"; my @log_limit_options = &make_log_limit_options(); +my $POLICY_INPUT_ALLOWED = 0; +my $POLICY_FORWARD_ALLOWED = ($fwdfwsettings{"POLICY"} eq "MODE2"); +my $POLICY_OUTPUT_ALLOWED = ($fwdfwsettings{"POLICY1"} eq "MODE2"); + +my $POLICY_INPUT_ACTION = $fwoptions{"FWPOLICY2"}; +my $POLICY_FORWARD_ACTION = $fwoptions{"FWPOLICY"}; +my $POLICY_OUTPUT_ACTION = $fwoptions{"FWPOLICY1"}; + # MAIN &main(); @@ -131,20 +141,47 @@ sub flush { } sub preparerules { - if (! -z "${General::swroot}/firewall/config"){ - &buildrules(\%configfwdfw); - } if (! -z "${General::swroot}/firewall/input"){ &buildrules(\%configinputfw); } if (! -z "${General::swroot}/firewall/outgoing"){ &buildrules(\%configoutgoingfw); } + if (! -z "${General::swroot}/firewall/config"){ + &buildrules(\%configfwdfw); + } } sub buildrules { my $hash = shift; + # Search for targets that need to be specially handled when adding + # forwarding rules. Additional rules will automatically get inserted + # into the INPUT/OUTPUT chains for these targets. + my @special_input_targets = (); + if (!$POLICY_FORWARD_ALLOWED) { + push(@special_input_targets, "ACCEPT"); + } + + if ($POLICY_INPUT_ACTION eq "DROP") { + push(@special_input_targets, "REJECT"); + } elsif ($POLICY_INPUT_ACTION eq "REJECT") { + push(@special_input_targets, "DROP"); + } + + my @special_output_targets = (); + if ($POLICY_OUTPUT_ALLOWED) { + push(@special_output_targets, ("DROP", "REJECT")); + } else { + push(@special_output_targets, "ACCEPT"); + + if ($POLICY_OUTPUT_ACTION eq "DROP") { + push(@special_output_targets, "REJECT"); + } elsif ($POLICY_OUTPUT_ACTION eq "REJECT") { + push(@special_output_targets, "DROP"); + } + } + foreach my $key (sort {$a <=> $b} keys %$hash) { # Skip disabled rules. next unless ($$hash{$key}[2] eq 'ON'); @@ -297,11 +334,16 @@ sub buildrules { # Add time constraint options. push(@options, @time_options); - my $firewall_is_in_source_subnet = 0; + my $firewall_is_in_source_subnet = 1; if ($source) { $firewall_is_in_source_subnet = &firewall_is_in_subnet($source); } + my $firewall_is_in_destination_subnet = 1; + if ($destination) { + $firewall_is_in_destination_subnet = &firewall_is_in_subnet($destination); + } + # Process NAT rules. if ($NAT) { my $nat_address = &fwlib::get_nat_address($$hash{$key}[29], $source); @@ -380,14 +422,6 @@ sub buildrules { } push(@options, @source_options); - - if ($firewall_is_in_source_subnet && ($fwdfwsettings{"POLICY"} eq "MODE1") && ($chain eq $CHAIN_FORWARD)) { - if ($LOG && !$NAT) { - run("$IPTABLES -A $CHAIN_INPUT @options @log_limit_options -j LOG --log-prefix '$CHAIN_INPUT '"); - } - run("$IPTABLES -A $CHAIN_INPUT @options -j $target"); - } - push(@options, @destination_options); # Insert firewall rule. @@ -395,6 +429,27 @@ sub buildrules { run("$IPTABLES -A $chain @options @log_limit_options -j LOG --log-prefix '$chain '"); } run("$IPTABLES -A $chain @options -j $target"); + + # Handle forwarding rules and add corresponding rules for firewall access. + if ($chain eq $CHAIN_FORWARD) { + # If the firewall is part of the destination subnet and access to the destination network + # is granted/forbidden for any network that the firewall itself is part of, we grant/forbid access + # for the firewall, too. + if ($firewall_is_in_destination_subnet && ($target ~~ @special_input_targets)) { + if ($LOG && !$NAT) { + run("$IPTABLES -A $CHAIN_INPUT @options @log_limit_options -j LOG --log-prefix '$CHAIN_INPUT '"); + } + run("$IPTABLES -A $CHAIN_INPUT @options -j $target"); + } + + # Likewise. + if ($firewall_is_in_source_subnet && ($target ~~ @special_output_targets)) { + if ($LOG && !$NAT) { + run("$IPTABLES -A $CHAIN_OUTPUT @options @log_limit_options -j LOG --log-prefix '$CHAIN_OUTPUT '"); + } + run("$IPTABLES -A $CHAIN_OUTPUT @options -j $target"); + } + } } } } @@ -675,4 +730,3 @@ sub firewall_is_in_subnet { return 0; } -