diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index c4a19e5d8..9b3f2bff4 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -217,7 +217,7 @@ sub get_std_net_ip }elsif($val eq 'BLUE'){ return "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}"; }elsif($val eq 'RED'){ - return "0.0.0.0/0 -o $con"; + return "0.0.0.0/0"; }elsif($val =~ /OpenVPN/i){ return "$ovpnsettings{'DOVPN_SUBNET'}"; }elsif($val =~ /IPsec/i){ @@ -226,6 +226,23 @@ sub get_std_net_ip return ; } } +sub get_interface +{ + my $net=shift; + if($net eq "$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}"){ + return "$netsettings{'GREEN_DEV'}"; + } + if($net eq "$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}"){ + return "$netsettings{'ORANGE_DEV'}"; + } + if($net eq "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}"){ + return "$netsettings{'BLUE_DEV'}"; + } + if($net eq "0.0.0.0/0"){ + return "$netsettings{'RED_DEV'}"; + } + return ""; +} sub get_net_ip { my $val=shift; @@ -305,9 +322,9 @@ sub get_address # address. Otherwise, we assume that it is an IP address. if ($key ~~ ["src_addr", "tgt_addr"]) { if (&General::validmac($value)) { - push(@ret, "-m mac --mac-source $value"); + push(@ret, ["-m mac --mac-source $value", ""]); } else { - push(@ret, $value); + push(@ret, [$value, ""]); } # If a default network interface (GREEN, BLUE, etc.) is selected, we @@ -316,88 +333,90 @@ sub get_address my $external_interface = &get_external_interface(); my $network_address = &get_std_net_ip($value, $external_interface); + if ($network_address) { - push(@ret, $network_address); + my $interface = &get_interface($network_address); + push(@ret, [$network_address, $interface]); } # Custom networks. } elsif ($key ~~ ["cust_net_src", "cust_net_tgt", "Custom Network"]) { my $network_address = &get_net_ip($value); if ($network_address) { - push(@ret, $network_address); + push(@ret, [$network_address, ""]); } # Custom hosts. } elsif ($key ~~ ["cust_host_src", "cust_host_tgt", "Custom Host"]) { my $host_address = &get_host_ip($value, $type); if ($host_address) { - push(@ret, $host_address); + push(@ret, [$host_address, ""]); } # OpenVPN networks. } elsif ($key ~~ ["ovpn_net_src", "ovpn_net_tgt", "OpenVPN static network"]) { my $network_address = &get_ovpn_net_ip($value, 1); if ($network_address) { - push(@ret, $network_address); + push(@ret, [$network_address, ""]); } # OpenVPN hosts. } elsif ($key ~~ ["ovpn_host_src", "ovpn_host_tgt", "OpenVPN static host"]) { my $host_address = &get_ovpn_host_ip($value, 33); if ($host_address) { - push(@ret, $host_address); + push(@ret, [$host_address, ""]); } # OpenVPN N2N. } elsif ($key ~~ ["ovpn_n2n_src", "ovpn_n2n_tgt", "OpenVPN N-2-N"]) { my $network_address = &get_ovpn_n2n_ip($value, 11); if ($network_address) { - push(@ret, $network_address); + push(@ret, [$network_address, ""]); } # IPsec networks. } elsif ($key ~~ ["ipsec_net_src", "ipsec_net_tgt", "IpSec Network"]) { my $network_address = &get_ipsec_net_ip($value, 11); if ($network_address) { - push(@ret, $network_address); + push(@ret, [$network_address, ""]); } # The firewall's own IP addresses. } elsif ($key ~~ ["ipfire", "ipfire_src"]) { # ALL if ($value eq "ALL") { - push(@ret, "0/0"); + push(@ret, ["0/0", ""]); # GREEN } elsif ($value eq "GREEN") { - push(@ret, $netsettings{"GREEN_ADDRESS"}); + push(@ret, [$netsettings{"GREEN_ADDRESS"}, ""]); # BLUE } elsif ($value eq "BLUE") { - push(@ret, $netsettings{"BLUE_ADDRESS"}); + push(@ret, [$netsettings{"BLUE_ADDRESS"}, ""]); # ORANGE } elsif ($value eq "ORANGE") { - push(@ret, $netsettings{"ORANGE_ADDRESS"}); + push(@ret, [$netsettings{"ORANGE_ADDRESS"}, ""]); # RED } elsif ($value ~~ ["RED", "RED1"]) { my $address = &get_external_address(); if ($address) { - push(@ret, $address); + push(@ret, [$address, ""]); } # Aliases } else { my $alias = &get_alias($value); if ($alias) { - push(@ret, $alias); + push(@ret, [$alias, ""]); } } # If nothing was selected, we assume "any". } else { - push(@ret, "0/0"); + push(@ret, ["0/0", ""]); } return @ret; diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index c0ddcb2d6..887c05265 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -291,24 +291,28 @@ sub buildrules { foreach my $src (@sources) { # Skip invalid source. - next unless ($src); + next unless (@$src[0]); # Sanitize source. - my $source = $src; + my $source = @$src[0]; if ($source ~~ @ANY_ADDRESSES) { $source = ""; } + my $source_intf = @$src[1]; + foreach my $dst (@destinations) { # Skip invalid rules. - next if (!$dst || ($dst eq "none")); + next if (!@$dst[0] || (@$dst[0] eq "none")); # Sanitize destination. - my $destination = $dst; + my $destination = @$dst[0]; if ($destination ~~ @ANY_ADDRESSES) { $destination = ""; } + my $destination_intf = @$dst[1]; + # Array with iptables arguments. my @options = (); @@ -325,12 +329,20 @@ sub buildrules { push(@source_options, ("-s", $source)); } + if ($source_intf) { + push(@source_options, ("-i", $source_intf)); + } + # Prepare destination options. my @destination_options = (); if ($destination) { push(@destination_options, ("-d", $destination)); } + if ($destination_intf) { + push(@destination_options, ("-o", $destination_intf)); + } + # Add time constraint options. push(@options, @time_options); @@ -364,7 +376,7 @@ sub buildrules { # Make port-forwardings useable from the internal networks. my @internal_addresses = &fwlib::get_internal_firewall_ip_addresses(1); unless ($nat_address ~~ @internal_addresses) { - &add_dnat_mangle_rules($nat_address, @nat_options); + &add_dnat_mangle_rules($nat_address, $source_intf, @nat_options); } push(@nat_options, @source_options); @@ -681,6 +693,7 @@ sub get_dnat_target_port { sub add_dnat_mangle_rules { my $nat_address = shift; + my $interface = shift; my @options = @_; my $mark = 0; @@ -691,6 +704,8 @@ sub add_dnat_mangle_rules { next unless (exists $defaultNetworks{$zone . "_NETADDRESS"}); next unless (exists $defaultNetworks{$zone . "_NETMASK"}); + next if ($interface && $interface ne $defaultNetworks{$zone . "_DEV"}); + my @mangle_options = @options; my $netaddress = $defaultNetworks{$zone . "_NETADDRESS"}; diff --git a/html/cgi-bin/firewall.cgi b/html/cgi-bin/firewall.cgi index e6ae5272a..2539d102c 100644 --- a/html/cgi-bin/firewall.cgi +++ b/html/cgi-bin/firewall.cgi @@ -1064,7 +1064,6 @@ print<