From d7a14d01e120d7350f449a2694eb10feedede2d6 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 21 Mar 2014 12:40:55 +0100 Subject: [PATCH 01/15] firewall: rules.pl: Fix rules with other NAT port. --- config/firewall/rules.pl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 50fff3f09..420f7767a 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -246,7 +246,7 @@ sub buildrules { } # Prepare protocol options (like ICMP types, ports, etc...). - my @protocol_options = &get_protocol_options($hash, $key, $protocol); + my @protocol_options = &get_protocol_options($hash, $key, $protocol, 0); # Check if this protocol knows ports. my $protocol_has_ports = ($protocol ~~ @PROTOCOLS_WITH_PORTS); @@ -271,7 +271,6 @@ sub buildrules { # Append protocol. if ($protocol ne "all") { - push(@options, ("-p", $protocol)); push(@options, @protocol_options); } @@ -313,7 +312,11 @@ sub buildrules { &add_dnat_mangle_rules($nat_address, @options); } - my @nat_options = @options; + my @nat_options = (); + if ($protocol ne "all") { + my @nat_protocol_options = &get_protocol_options($hash, $key, $protocol, 1); + push(@nat_options, @nat_protocol_options); + } push(@nat_options, @source_options); push(@nat_options, ("-d", $nat_address)); @@ -701,8 +704,16 @@ sub get_protocol_options { my $hash = shift; my $key = shift; my $protocol = shift; + my $nat_options_wanted = shift; my @options = (); + # Nothing to do if no protocol is specified. + if ($protocol eq "all") { + return @options; + } else { + push(@options, ("-p", $protocol)); + } + # Process source ports. my $use_src_ports = ($$hash{$key}[7] eq "ON"); my $src_ports = $$hash{$key}[10]; @@ -720,7 +731,7 @@ sub get_protocol_options { my $dst_ports = $$hash{$key}[15]; if (($dst_ports_mode eq "TGT_PORT") && $dst_ports) { - if ($use_dnat && $$hash{$key}[30]) { + if ($nat_options_wanted && $use_dnat && $$hash{$key}[30]) { $dst_ports = $$hash{$key}[30]; } push(@options, &format_ports($dst_ports, "dst")); From 4e54e3c6f531f356424c366c6c886efeceb5b8ae Mon Sep 17 00:00:00 2001 From: Alexander Marx Date: Thu, 20 Mar 2014 17:27:53 +0100 Subject: [PATCH 02/15] Firewall: Move some functions from rules.pl to firewall-lib.pl --- config/firewall/firewall-lib.pl | 268 +++++++++++++++++++++++++++++- config/firewall/rules.pl | 280 +------------------------------- 2 files changed, 271 insertions(+), 277 deletions(-) diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index fc8055507..6f04b0cab 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -35,6 +35,8 @@ my %ipsecconf=(); my %ipsecsettings=(); my %netsettings=(); my %ovpnsettings=(); +my %defaultNetworks=(); +my %aliases=(); require '/var/ipfire/general-functions.pl'; @@ -103,8 +105,6 @@ sub get_srvgrp_prot return $back; } - - sub get_srv_port { my $val=shift; @@ -253,5 +253,269 @@ sub get_host_ip } } } +# Functions used by rules.pl +sub get_addresses { + my $hash = shift; + my $key = shift; + my $type = shift; + + my @addresses = (); + my $addr_type; + my $value; + my $group_name; + + if ($type eq "src") { + $addr_type = $$hash{$key}[3]; + $value = $$hash{$key}[4]; + + } elsif ($type eq "tgt") { + $addr_type = $$hash{$key}[5]; + $value = $$hash{$key}[6]; + } + + if ($addr_type ~~ ["cust_grp_src", "cust_grp_tgt"]) { + foreach my $grp (sort {$a <=> $b} keys %customgrp) { + if ($customgrp{$grp}[0] eq $value) { + my @address = &get_address($customgrp{$grp}[3], $customgrp{$grp}[2], $type); + + if (@address) { + push(@addresses, @address); + } + } + } + } else { + my @address = &get_address($addr_type, $value, $type); + + if (@address) { + push(@addresses, @address); + } + } + + return @addresses; +} +sub get_address { + my $key = shift; + my $value = shift; + my $type = shift; + + my @ret = (); + + # If the user manually typed an address, we just check if it is a MAC + # 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"); + } else { + push(@ret, $value); + } + + # If a default network interface (GREEN, BLUE, etc.) is selected, we + # try to get the corresponding address of the network. + } elsif ($key ~~ ["std_net_src", "std_net_tgt", "Standard Network"]) { + my $external_interface = &get_external_interface(); + + my $network_address = &get_std_net_ip($value, $external_interface); + if ($network_address) { + push(@ret, $network_address); + } + + # 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); + } + + # 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); + } + + # 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); + } + + # 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); + } + + # 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); + } + + # 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); + } + + # The firewall's own IP addresses. + } elsif ($key ~~ ["ipfire", "ipfire_src"]) { + # ALL + if ($value eq "ALL") { + push(@ret, "0/0"); + + # GREEN + } elsif ($value eq "GREEN") { + push(@ret, $defaultNetworks{"GREEN_ADDRESS"}); + + # BLUE + } elsif ($value eq "BLUE") { + push(@ret, $defaultNetworks{"BLUE_ADDRESS"}); + + # ORANGE + } elsif ($value eq "ORANGE") { + push(@ret, $defaultNetworks{"ORANGE_ADDRESS"}); + + # RED + } elsif ($value ~~ ["RED", "RED1"]) { + my $address = &get_external_address(); + if ($address) { + push(@ret, $address); + } + + # Aliases + } else { + my %alias = &get_alias($value); + if (%alias) { + push(@ret, $alias{"IPT"}); + } + } + + # If nothing was selected, we assume "any". + } else { + push(@ret, "0/0"); + } + + return @ret; +} +sub get_external_interface() { + open(IFACE, "/var/ipfire/red/iface") or return ""; + my $iface = ; + close(IFACE); + + return $iface; +} +sub get_external_address() { + open(ADDR, "/var/ipfire/red/local-ipaddress") or return ""; + my $address = ; + close(ADDR); + + return $address; +} +sub get_alias { + my $id = shift; + + foreach my $alias (sort keys %aliases) { + if ($id eq $alias) { + return $aliases{$alias}; + } + } +} +sub get_nat_address { + my $zone = shift; + my $source = shift; + + # Any static address of any zone. + if ($zone eq "AUTO") { + if ($source) { + my $firewall_ip = &get_internal_firewall_ip_address($source, 1); + if ($firewall_ip) { + return $firewall_ip; + } + + $firewall_ip = &get_matching_firewall_address($source, 1); + if ($firewall_ip) { + return $firewall_ip; + } + } + + return &get_external_address(); + + } elsif ($zone eq "RED" || $zone eq "GREEN" || $zone eq "ORANGE" || $zone eq "BLUE") { + return $defaultNetworks{$zone . "_ADDRESS"}; + + } elsif ($zone eq "Default IP") { + return &get_external_address(); + + } else { + return &get_alias($zone); + } + + print_error("Could not find NAT address"); +} +sub get_internal_firewall_ip_addresses { + my $use_orange = shift; + + my @zones = ("GREEN", "BLUE"); + if ($use_orange) { + push(@zones, "ORANGE"); + } + + my @addresses = (); + for my $zone (@zones) { + next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); + + my $zone_address = $defaultNetworks{$zone . "_ADDRESS"}; + push(@addresses, $zone_address); + } + + return @addresses; +} +sub get_matching_firewall_address { + my $addr = shift; + my $use_orange = shift; + + my ($address, $netmask) = split("/", $addr); + + my @zones = ("GREEN", "BLUE"); + if ($use_orange) { + push(@zones, "ORANGE"); + } + + foreach my $zone (@zones) { + next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); + + my $zone_subnet = $defaultNetworks{$zone . "_NETADDRESS"}; + my $zone_mask = $defaultNetworks{$zone . "_NETMASK"}; + + if (&General::IpInSubnet($address, $zone_subnet, $zone_mask)) { + return $defaultNetworks{$zone . "_ADDRESS"}; + } + } + + return 0; +} +sub get_internal_firewall_ip_address { + my $subnet = shift; + my $use_orange = shift; + + my ($net_address, $net_mask) = split("/", $subnet); + if ((!$net_mask) || ($net_mask ~~ ["32", "255.255.255.255"])) { + return 0; + } + + my @addresses = &get_internal_firewall_ip_addresses($use_orange); + foreach my $zone_address (@addresses) { + if (&General::IpInSubnet($zone_address, $net_address, $net_mask)) { + return $zone_address; + } + } + + return 0; +} + return 1; diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 420f7767a..12c0c2b23 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -170,10 +170,10 @@ sub buildrules { } # Collect all sources. - my @sources = &get_addresses($hash, $key, "src"); + my @sources = &fwlib::get_addresses($hash, $key, "src"); # Collect all destinations. - my @destinations = &get_addresses($hash, $key, "tgt"); + my @destinations = &fwlib::get_addresses($hash, $key, "tgt"); # Check if logging should be enabled. my $LOG = ($$hash{$key}[17] eq 'ON'); @@ -298,7 +298,7 @@ sub buildrules { # Process NAT rules. if ($NAT) { - my $nat_address = &get_nat_address($$hash{$key}[29], $source); + my $nat_address = &fwlib::get_nat_address($$hash{$key}[29], $source); # Skip NAT rules if the NAT address is unknown # (i.e. no internet connection has been established, yet). @@ -307,7 +307,7 @@ sub buildrules { # Destination NAT if ($NAT_MODE eq "DNAT") { # Make port-forwardings useable from the internal networks. - my @internal_addresses = &get_internal_firewall_ip_addresses(1); + my @internal_addresses = &fwlib::get_internal_firewall_ip_addresses(1); unless ($nat_address ~~ @internal_addresses) { &add_dnat_mangle_rules($nat_address, @options); } @@ -372,65 +372,6 @@ sub buildrules { } } -sub get_external_interface() { - open(IFACE, "/var/ipfire/red/iface") or return ""; - my $iface = ; - close(IFACE); - - return $iface; -} - -sub get_external_address() { - open(ADDR, "/var/ipfire/red/local-ipaddress") or return ""; - my $address = ; - close(ADDR); - - return $address; -} - -sub get_alias { - my $id = shift; - - foreach my $alias (sort keys %aliases) { - if ($id eq $alias) { - return $aliases{$alias}; - } - } -} - -sub get_nat_address { - my $zone = shift; - my $source = shift; - - # Any static address of any zone. - if ($zone eq "AUTO") { - if ($source) { - my $firewall_ip = &get_internal_firewall_ip_address($source, 1); - if ($firewall_ip) { - return $firewall_ip; - } - - $firewall_ip = &get_matching_firewall_address($source, 1); - if ($firewall_ip) { - return $firewall_ip; - } - } - - return &get_external_address(); - - } elsif ($zone eq "RED" || $zone eq "GREEN" || $zone eq "ORANGE" || $zone eq "BLUE") { - return $defaultNetworks{$zone . "_ADDRESS"}; - - } elsif ($zone eq "Default IP") { - return &get_external_address(); - - } else { - return &get_alias($zone); - } - - print_error("Could not find NAT address"); -} - # Formats the given timestamp into the iptables format which is "hh:mm" UTC. sub format_time { my $val = shift; @@ -496,155 +437,6 @@ sub p2pblock { } } -sub get_addresses { - my $hash = shift; - my $key = shift; - my $type = shift; - - my @addresses = (); - my $addr_type; - my $value; - my $group_name; - - if ($type eq "src") { - $addr_type = $$hash{$key}[3]; - $value = $$hash{$key}[4]; - - } elsif ($type eq "tgt") { - $addr_type = $$hash{$key}[5]; - $value = $$hash{$key}[6]; - } - - if ($addr_type ~~ ["cust_grp_src", "cust_grp_tgt"]) { - foreach my $grp (sort {$a <=> $b} keys %customgrp) { - if ($customgrp{$grp}[0] eq $value) { - my @address = &get_address($customgrp{$grp}[3], $customgrp{$grp}[2], $type); - - if (@address) { - push(@addresses, @address); - } - } - } - } else { - my @address = &get_address($addr_type, $value, $type); - - if (@address) { - push(@addresses, @address); - } - } - - return @addresses; -} - -sub get_address { - my $key = shift; - my $value = shift; - my $type = shift; - - my @ret = (); - - # If the user manually typed an address, we just check if it is a MAC - # 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"); - } else { - push(@ret, $value); - } - - # If a default network interface (GREEN, BLUE, etc.) is selected, we - # try to get the corresponding address of the network. - } elsif ($key ~~ ["std_net_src", "std_net_tgt", "Standard Network"]) { - my $external_interface = &get_external_interface(); - - my $network_address = &fwlib::get_std_net_ip($value, $external_interface); - if ($network_address) { - push(@ret, $network_address); - } - - # Custom networks. - } elsif ($key ~~ ["cust_net_src", "cust_net_tgt", "Custom Network"]) { - my $network_address = &fwlib::get_net_ip($value); - if ($network_address) { - push(@ret, $network_address); - } - - # Custom hosts. - } elsif ($key ~~ ["cust_host_src", "cust_host_tgt", "Custom Host"]) { - my $host_address = &fwlib::get_host_ip($value, $type); - if ($host_address) { - push(@ret, $host_address); - } - - # OpenVPN networks. - } elsif ($key ~~ ["ovpn_net_src", "ovpn_net_tgt", "OpenVPN static network"]) { - my $network_address = &fwlib::get_ovpn_net_ip($value, 1); - if ($network_address) { - push(@ret, $network_address); - } - - # OpenVPN hosts. - } elsif ($key ~~ ["ovpn_host_src", "ovpn_host_tgt", "OpenVPN static host"]) { - my $host_address = &fwlib::get_ovpn_host_ip($value, 33); - if ($host_address) { - push(@ret, $host_address); - } - - # OpenVPN N2N. - } elsif ($key ~~ ["ovpn_n2n_src", "ovpn_n2n_tgt", "OpenVPN N-2-N"]) { - my $network_address = &fwlib::get_ovpn_n2n_ip($value, 11); - if ($network_address) { - push(@ret, $network_address); - } - - # IPsec networks. - } elsif ($key ~~ ["ipsec_net_src", "ipsec_net_tgt", "IpSec Network"]) { - my $network_address = &fwlib::get_ipsec_net_ip($value, 11); - if ($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"); - - # GREEN - } elsif ($value eq "GREEN") { - push(@ret, $defaultNetworks{"GREEN_ADDRESS"}); - - # BLUE - } elsif ($value eq "BLUE") { - push(@ret, $defaultNetworks{"BLUE_ADDRESS"}); - - # ORANGE - } elsif ($value eq "ORANGE") { - push(@ret, $defaultNetworks{"ORANGE_ADDRESS"}); - - # RED - } elsif ($value ~~ ["RED", "RED1"]) { - my $address = &get_external_address(); - if ($address) { - push(@ret, $address); - } - - # Aliases - } else { - my %alias = &get_alias($value); - if (%alias) { - push(@ret, $alias{"IPT"}); - } - } - - # If nothing was selected, we assume "any". - } else { - push(@ret, "0/0"); - } - - return @ret; -} - sub get_protocols { my $hash = shift; my $key = shift; @@ -839,50 +631,12 @@ sub make_log_limit_options { return @options; } -sub get_internal_firewall_ip_addresses { - my $use_orange = shift; - - my @zones = ("GREEN", "BLUE"); - if ($use_orange) { - push(@zones, "ORANGE"); - } - - my @addresses = (); - for my $zone (@zones) { - next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); - - my $zone_address = $defaultNetworks{$zone . "_ADDRESS"}; - push(@addresses, $zone_address); - } - - return @addresses; -} - -sub get_internal_firewall_ip_address { - my $subnet = shift; - my $use_orange = shift; - - my ($net_address, $net_mask) = split("/", $subnet); - if ((!$net_mask) || ($net_mask ~~ ["32", "255.255.255.255"])) { - return 0; - } - - my @addresses = &get_internal_firewall_ip_addresses($use_orange); - foreach my $zone_address (@addresses) { - if (&General::IpInSubnet($zone_address, $net_address, $net_mask)) { - return $zone_address; - } - } - - return 0; -} - sub firewall_is_in_subnet { my $subnet = shift; # ORANGE is missing here, because nothing may ever access # the firewall from this network. - my $address = &get_internal_firewall_ip_address($subnet, 0); + my $address = &fwlib::get_internal_firewall_ip_address($subnet, 0); if ($address) { return 1; @@ -891,27 +645,3 @@ sub firewall_is_in_subnet { return 0; } -sub get_matching_firewall_address { - my $addr = shift; - my $use_orange = shift; - - my ($address, $netmask) = split("/", $addr); - - my @zones = ("GREEN", "BLUE"); - if ($use_orange) { - push(@zones, "ORANGE"); - } - - foreach my $zone (@zones) { - next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); - - my $zone_subnet = $defaultNetworks{$zone . "_NETADDRESS"}; - my $zone_mask = $defaultNetworks{$zone . "_NETMASK"}; - - if (&General::IpInSubnet($address, $zone_subnet, $zone_mask)) { - return $defaultNetworks{$zone . "_ADDRESS"}; - } - } - - return 0; -} From fd169d0adc87c82253b0655d94ea8213e9aaabe4 Mon Sep 17 00:00:00 2001 From: Alexander Marx Date: Fri, 21 Mar 2014 08:28:24 +0100 Subject: [PATCH 03/15] Firewall: DNAT - Show right DNAT interface in ruletable Now: When using a hostgroup as source there are all corresponding DNAT interfaces shown in ruletable depending on the entries in the group. When in DNAT area "-automatic" is selected, the DNAT interfaces are shown as IP-Addresses, else they are shown as "ORANGE","GREEN","BLUE"... BUGFIX: When there is a MAC address used in a sourcegroup, the rules could not be set. Now MAC addresses get allways the public interface as DNAT --- config/firewall/firewall-lib.pl | 34 ++++++++++++++++++++------------- html/cgi-bin/firewall.cgi | 21 +++++++++++++++++++- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index 6f04b0cab..a82fc90b4 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -51,11 +51,12 @@ my $configipsec = "${General::swroot}/vpn/config"; my $configovpn = "${General::swroot}/ovpn/settings"; my $val; my $field; +my $netsettings = "${General::swroot}/ethernet/settings"; &General::readhash("/var/ipfire/ethernet/settings", \%netsettings); &General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings); &General::readhash("${General::swroot}/vpn/settings", \%ipsecsettings); - +&General::readhash("$netsettings", \%defaultNetworks); &General::readhasharray("$confignet", \%customnetwork); &General::readhasharray("$confighost", \%customhost); @@ -253,8 +254,8 @@ sub get_host_ip } } } -# Functions used by rules.pl -sub get_addresses { +sub get_addresses +{ my $hash = shift; my $key = shift; my $type = shift; @@ -293,7 +294,8 @@ sub get_addresses { return @addresses; } -sub get_address { +sub get_address +{ my $key = shift; my $value = shift; my $type = shift; @@ -401,21 +403,24 @@ sub get_address { return @ret; } -sub get_external_interface() { +sub get_external_interface() +{ open(IFACE, "/var/ipfire/red/iface") or return ""; my $iface = ; close(IFACE); return $iface; } -sub get_external_address() { +sub get_external_address() +{ open(ADDR, "/var/ipfire/red/local-ipaddress") or return ""; my $address = ; close(ADDR); return $address; } -sub get_alias { +sub get_alias +{ my $id = shift; foreach my $alias (sort keys %aliases) { @@ -424,13 +429,14 @@ sub get_alias { } } } -sub get_nat_address { +sub get_nat_address +{ my $zone = shift; my $source = shift; # Any static address of any zone. if ($zone eq "AUTO") { - if ($source) { + if ($source && ($source !~ m/mac/i )) { my $firewall_ip = &get_internal_firewall_ip_address($source, 1); if ($firewall_ip) { return $firewall_ip; @@ -456,7 +462,8 @@ sub get_nat_address { print_error("Could not find NAT address"); } -sub get_internal_firewall_ip_addresses { +sub get_internal_firewall_ip_addresses +{ my $use_orange = shift; my @zones = ("GREEN", "BLUE"); @@ -474,7 +481,8 @@ sub get_internal_firewall_ip_addresses { return @addresses; } -sub get_matching_firewall_address { +sub get_matching_firewall_address +{ my $addr = shift; my $use_orange = shift; @@ -498,7 +506,8 @@ sub get_matching_firewall_address { return 0; } -sub get_internal_firewall_ip_address { +sub get_internal_firewall_ip_address +{ my $subnet = shift; my $use_orange = shift; @@ -517,5 +526,4 @@ sub get_internal_firewall_ip_address { return 0; } - return 1; diff --git a/html/cgi-bin/firewall.cgi b/html/cgi-bin/firewall.cgi index 436bdafd0..d69d8217f 100644 --- a/html/cgi-bin/firewall.cgi +++ b/html/cgi-bin/firewall.cgi @@ -989,6 +989,12 @@ sub deleterule &base; } } +sub del_double +{ + my %all=(); + @all{@_}=1; + return (keys %all); +} sub disable_rule { my $key1=shift; @@ -2551,9 +2557,22 @@ END END #Is this a DNAT rule? + my $natstring; if ($$hash{$key}[31] eq 'dnat' && $$hash{$key}[28] eq 'ON'){ if ($$hash{$key}[29] eq 'Default IP'){$$hash{$key}[29]=$Lang::tr{'red1'};} - print "Firewall ($$hash{$key}[29])"; + if ($$hash{$key}[29] eq 'AUTO'){ + my @src_addresses=&fwlib::get_addresses(\%$hash,$key,'src'); + my @nat_ifaces; + foreach my $val (@src_addresses){ + my ($ip,$sub)=split("/",$val); + push (@nat_ifaces,&fwlib::get_nat_address($$hash{$key}[29],$ip)); + } + @nat_ifaces=&del_double(@nat_ifaces); + $natstring = join(', ', @nat_ifaces); + }else{ + $natstring = $$hash{$key}[29]; + } + print "$Lang::tr{'firewall'} ($natstring)"; if($$hash{$key}[30] ne ''){ $$hash{$key}[30]=~ tr/|/,/; print": $$hash{$key}[30]"; From c71499d8d9296124cd08467efa938375e0bccb20 Mon Sep 17 00:00:00 2001 From: Alexander Marx Date: Fri, 21 Mar 2014 12:20:50 +0100 Subject: [PATCH 04/15] Firewall: Rename defaultNetworks to netsettings --- config/firewall/firewall-lib.pl | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index a82fc90b4..ae2a46228 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -35,7 +35,6 @@ my %ipsecconf=(); my %ipsecsettings=(); my %netsettings=(); my %ovpnsettings=(); -my %defaultNetworks=(); my %aliases=(); require '/var/ipfire/general-functions.pl'; @@ -56,7 +55,6 @@ my $netsettings = "${General::swroot}/ethernet/settings"; &General::readhash("/var/ipfire/ethernet/settings", \%netsettings); &General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings); &General::readhash("${General::swroot}/vpn/settings", \%ipsecsettings); -&General::readhash("$netsettings", \%defaultNetworks); &General::readhasharray("$confignet", \%customnetwork); &General::readhasharray("$confighost", \%customhost); @@ -371,15 +369,15 @@ sub get_address # GREEN } elsif ($value eq "GREEN") { - push(@ret, $defaultNetworks{"GREEN_ADDRESS"}); + push(@ret, $netsettings{"GREEN_ADDRESS"}); # BLUE } elsif ($value eq "BLUE") { - push(@ret, $defaultNetworks{"BLUE_ADDRESS"}); + push(@ret, $netsettings{"BLUE_ADDRESS"}); # ORANGE } elsif ($value eq "ORANGE") { - push(@ret, $defaultNetworks{"ORANGE_ADDRESS"}); + push(@ret, $netsettings{"ORANGE_ADDRESS"}); # RED } elsif ($value ~~ ["RED", "RED1"]) { @@ -451,7 +449,7 @@ sub get_nat_address return &get_external_address(); } elsif ($zone eq "RED" || $zone eq "GREEN" || $zone eq "ORANGE" || $zone eq "BLUE") { - return $defaultNetworks{$zone . "_ADDRESS"}; + return $netsettings{$zone . "_ADDRESS"}; } elsif ($zone eq "Default IP") { return &get_external_address(); @@ -473,9 +471,9 @@ sub get_internal_firewall_ip_addresses my @addresses = (); for my $zone (@zones) { - next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); + next unless (exists $netsettings{$zone . "_ADDRESS"}); - my $zone_address = $defaultNetworks{$zone . "_ADDRESS"}; + my $zone_address = $netsettings{$zone . "_ADDRESS"}; push(@addresses, $zone_address); } @@ -494,13 +492,13 @@ sub get_matching_firewall_address } foreach my $zone (@zones) { - next unless (exists $defaultNetworks{$zone . "_ADDRESS"}); + next unless (exists $netsettings{$zone . "_ADDRESS"}); - my $zone_subnet = $defaultNetworks{$zone . "_NETADDRESS"}; - my $zone_mask = $defaultNetworks{$zone . "_NETMASK"}; + my $zone_subnet = $netsettings{$zone . "_NETADDRESS"}; + my $zone_mask = $netsettings{$zone . "_NETMASK"}; if (&General::IpInSubnet($address, $zone_subnet, $zone_mask)) { - return $defaultNetworks{$zone . "_ADDRESS"}; + return $netsettings{$zone . "_ADDRESS"}; } } From 896eb2d69354221b2a13770b60a61c5b454126a7 Mon Sep 17 00:00:00 2001 From: Alexander Marx Date: Fri, 21 Mar 2014 12:54:12 +0100 Subject: [PATCH 05/15] Firewall: Allow DNAT with target firewall --- html/cgi-bin/firewall.cgi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/html/cgi-bin/firewall.cgi b/html/cgi-bin/firewall.cgi index d69d8217f..164e7cbac 100644 --- a/html/cgi-bin/firewall.cgi +++ b/html/cgi-bin/firewall.cgi @@ -584,8 +584,10 @@ sub checktarget } } }else{ - $errormessage=$Lang::tr{'fwdfw dnat error'}."
"; - return $errormessage; + if ($fwdfwsettings{'grp2'} ne 'ipfire'){ + $errormessage=$Lang::tr{'fwdfw dnat error'}."
"; + return $errormessage; + } } } if ($fwdfwsettings{'tgt_addr'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'tgt_addr'} ne ''){ @@ -2564,8 +2566,7 @@ END my @src_addresses=&fwlib::get_addresses(\%$hash,$key,'src'); my @nat_ifaces; foreach my $val (@src_addresses){ - my ($ip,$sub)=split("/",$val); - push (@nat_ifaces,&fwlib::get_nat_address($$hash{$key}[29],$ip)); + push (@nat_ifaces,&fwlib::get_nat_address($$hash{$key}[29],$val)); } @nat_ifaces=&del_double(@nat_ifaces); $natstring = join(', ', @nat_ifaces); From c0ce920610c15e9a3639dbaadb29feea1747ac34 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 21 Mar 2014 13:28:00 +0100 Subject: [PATCH 06/15] firewall: rules.pl: Allow REDIRECT rules. --- config/firewall/rules.pl | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 12c0c2b23..d9c9b5cc0 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -175,6 +175,9 @@ sub buildrules { # Collect all destinations. my @destinations = &fwlib::get_addresses($hash, $key, "tgt"); + # True if the destination is the firewall itself. + my $destination_is_firewall = ($$hash{$key}[5] eq "ipfire"); + # Check if logging should be enabled. my $LOG = ($$hash{$key}[17] eq 'ON'); @@ -320,21 +323,38 @@ sub buildrules { push(@nat_options, @source_options); push(@nat_options, ("-d", $nat_address)); - my ($dnat_address, $dnat_mask) = split("/", $destination); - @destination_options = ("-d", $dnat_address); - + my $dnat_port; if ($protocol_has_ports) { - my $dnat_port = &get_dnat_target_port($hash, $key); + $dnat_port = &get_dnat_target_port($hash, $key); + } - if ($dnat_port) { - $dnat_address .= ":$dnat_port"; + my @nat_action_options = (); + + # Use iptables REDIRECT + my $use_redirect = ($destination_is_firewall && !$destination && $protocol_has_ports && $dnat_port); + if ($use_redirect) { + push(@nat_action_options, ("-j", "REDIRECT", "--to-ports", $dnat_port)); + + # Use iptables DNAT + } else { + my ($dnat_address, $dnat_mask) = split("/", $destination); + @destination_options = ("-d", $dnat_address); + + if ($protocol_has_ports) { + my $dnat_port = &get_dnat_target_port($hash, $key); + + if ($dnat_port) { + $dnat_address .= ":$dnat_port"; + } } + + push(@nat_action_options, ("-j", "DNAT", "--to-destination", $dnat_address)); } if ($LOG) { run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options @log_limit_options -j LOG --log-prefix 'DNAT '"); } - run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options -j DNAT --to-destination $dnat_address"); + run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options @nat_action_options"); # Source NAT } elsif ($NAT_MODE eq "SNAT") { From f98bb538e59279bb0768a15fc7d95267f4d61c74 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 21 Mar 2014 13:33:08 +0100 Subject: [PATCH 07/15] firewall: rules.pl: Catch invalid configurations. --- config/firewall/rules.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index d9c9b5cc0..a131c54a8 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -337,6 +337,11 @@ sub buildrules { # Use iptables DNAT } else { + if ($destination_is_firewall && !$destination) { + $destination = &fwlib::get_external_address(); + } + next unless ($destination); + my ($dnat_address, $dnat_mask) = split("/", $destination); @destination_options = ("-d", $dnat_address); From 51cf3f8be548e3bb3bff19bab7c27dbb56e6e426 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 21 Mar 2014 13:39:03 +0100 Subject: [PATCH 08/15] firewall: rules.pl: Honour time constraints for NAT rules as well. --- config/firewall/rules.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index a131c54a8..f25983ce5 100755 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -322,6 +322,7 @@ sub buildrules { } push(@nat_options, @source_options); push(@nat_options, ("-d", $nat_address)); + push(@nat_options, @time_options); my $dnat_port; if ($protocol_has_ports) { From af433268e063cbcb435b4770027906d897d9bb6f Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Sun, 23 Mar 2014 17:39:47 +0100 Subject: [PATCH 09/15] graphs.pl: fix links position in chrome for android. --- config/cfgroot/graphs.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 4942c98c8..487a4dd93 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -92,7 +92,7 @@ sub makegraphbox { print "".$Lang::tr{'month'}.""; print " - "; print "".$Lang::tr{'year'}.""; - print ""; + print "
"; print ""; } From f763ff3224dec67963bd47ef176085d7dd310fc0 Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Mon, 24 Mar 2014 13:28:29 +0100 Subject: [PATCH 10/15] kernel: update to 3.10.34. --- lfs/linux | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lfs/linux b/lfs/linux index 687de3634..9f82ab0d5 100644 --- a/lfs/linux +++ b/lfs/linux @@ -24,10 +24,10 @@ include Config -VER = 3.10.33 +VER = 3.10.34 RPI_PATCHES = linux-3.10.27-grsec-943b563 -GRS_PATCHES = grsecurity-2.9.1-3.10.33-ipfire1.patch.xz +GRS_PATCHES = grsecurity-2.9.1-3.10.34-ipfire1.patch.xz THISAPP = linux-$(VER) DL_FILE = linux-$(VER).tar.xz @@ -36,7 +36,7 @@ DIR_APP = $(DIR_SRC)/$(THISAPP) CFLAGS = CXXFLAGS = -PAK_VER = 38 +PAK_VER = 39 DEPS = "" VERSUFIX=ipfire$(KCFG) @@ -74,9 +74,9 @@ $(DL_FILE) = $(URL_IPFIRE)/$(DL_FILE) rpi-patches-$(RPI_PATCHES).patch.xz = $(URL_IPFIRE)/rpi-patches-$(RPI_PATCHES).patch.xz $(GRS_PATCHES) = $(URL_IPFIRE)/$(GRS_PATCHES) -$(DL_FILE)_MD5 = 01865f9c129f3c7eee51e25b3781a364 +$(DL_FILE)_MD5 = 30991b495a3d75196d5608072d2e62e6 rpi-patches-$(RPI_PATCHES).patch.xz_MD5 = 8cf81f48408306d93ccee59b58af2e92 -$(GRS_PATCHES)_MD5 = c99be0018e8bc55fb2e2b8f0ea9783d5 +$(GRS_PATCHES)_MD5 = b490f7f3bf48387ab2eb60212fcf0c11 install : $(TARGET) From 5c8167f5766250bdc3b57e6242e487fb467f895f Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Tue, 25 Mar 2014 12:59:37 +0100 Subject: [PATCH 11/15] iwlwifi: use noibss flags only on radar detection channels. --- lfs/linux | 1 + ...34-iwlwifi-noibss_only_on_radar_chan.patch | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/patches/linux-3.10.34-iwlwifi-noibss_only_on_radar_chan.patch diff --git a/lfs/linux b/lfs/linux index 9f82ab0d5..1f91c0b72 100644 --- a/lfs/linux +++ b/lfs/linux @@ -136,6 +136,7 @@ endif # Wlan Patches cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/compat-drivers-3.8.3-ath_ignore_eeprom_regdomain.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.34-iwlwifi-noibss_only_on_radar_chan.patch # mISDN Patches cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/mISDN_hfc-s_add_id.patch diff --git a/src/patches/linux-3.10.34-iwlwifi-noibss_only_on_radar_chan.patch b/src/patches/linux-3.10.34-iwlwifi-noibss_only_on_radar_chan.patch new file mode 100644 index 000000000..cc76fe6ea --- /dev/null +++ b/src/patches/linux-3.10.34-iwlwifi-noibss_only_on_radar_chan.patch @@ -0,0 +1,23 @@ +diff -Naur linux-3.10.34.org/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c linux-3.10.34/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +--- linux-3.10.34.org/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c 2014-03-24 05:42:03.000000000 +0100 ++++ linux-3.10.34/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c 2014-03-25 09:08:28.548634788 +0100 +@@ -613,14 +613,16 @@ + /* set no-HT40, will enable as appropriate later */ + channel->flags = IEEE80211_CHAN_NO_HT40; + ++ ++ if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) { ++ channel->flags |= IEEE80211_CHAN_RADAR; ++ + if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) + channel->flags |= IEEE80211_CHAN_NO_IBSS; + + if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) + channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; +- +- if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) +- channel->flags |= IEEE80211_CHAN_RADAR; ++} + + /* Initialize regulatory-based run-time data */ + channel->max_power = From 57c209d558e0b410d5f42493d328d2c06cef20ac Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Tue, 25 Mar 2014 13:03:56 +0100 Subject: [PATCH 12/15] wlanap.cgi: fix detection of not useable channels. --- html/cgi-bin/wlanap.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/cgi-bin/wlanap.cgi b/html/cgi-bin/wlanap.cgi index 5b2490da0..16b3fea24 100644 --- a/html/cgi-bin/wlanap.cgi +++ b/html/cgi-bin/wlanap.cgi @@ -265,7 +265,7 @@ if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ my $wiphy = `iw dev $wlanapsettings{'INTERFACE'} info | grep wiphy | cut -d" " -f2`; chomp $wiphy; -@channellist_cmd = `iw phy phy$wiphy info | grep " MHz \\\[" | grep -v "(disabled)" | grep -v "no IBSS)" 2>/dev/null`; +@channellist_cmd = `iw phy phy$wiphy info | grep " MHz \\\[" | grep -v "(disabled)" | grep -v "no IBSS" | grep -v "passive scanning"" 2>/dev/null`; # get available channels my @temp; From 91eb94ee2f95c8d0e5ca709ea8e1480959581f7c Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Tue, 25 Mar 2014 13:15:43 +0100 Subject: [PATCH 13/15] wlanap: fix typo. --- html/cgi-bin/wlanap.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/cgi-bin/wlanap.cgi b/html/cgi-bin/wlanap.cgi index 16b3fea24..bbf25462d 100644 --- a/html/cgi-bin/wlanap.cgi +++ b/html/cgi-bin/wlanap.cgi @@ -265,7 +265,7 @@ if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ my $wiphy = `iw dev $wlanapsettings{'INTERFACE'} info | grep wiphy | cut -d" " -f2`; chomp $wiphy; -@channellist_cmd = `iw phy phy$wiphy info | grep " MHz \\\[" | grep -v "(disabled)" | grep -v "no IBSS" | grep -v "passive scanning"" 2>/dev/null`; +@channellist_cmd = `iw phy phy$wiphy info | grep " MHz \\\[" | grep -v "(disabled)" | grep -v "no IBSS" | grep -v "passive scanning" 2>/dev/null`; # get available channels my @temp; From 6a79396ce6dba66f4f8cce26a743be3496a8902c Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Tue, 25 Mar 2014 19:11:03 +0100 Subject: [PATCH 14/15] hostapd: change setting of the regdomain. the regdomain is only updated if it was really changed but after boot the system believe it is "00" World but it is not correctly set at some cards. So we set a region and set it back to "00" before the real region was set. --- lfs/hostapd | 2 +- src/initscripts/init.d/hostapd | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lfs/hostapd b/lfs/hostapd index 36343de37..5560a4277 100644 --- a/lfs/hostapd +++ b/lfs/hostapd @@ -32,7 +32,7 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = hostapd -PAK_VER = 28 +PAK_VER = 29 DEPS = "" diff --git a/src/initscripts/init.d/hostapd b/src/initscripts/init.d/hostapd index c0b11e6af..8f59a7f16 100644 --- a/src/initscripts/init.d/hostapd +++ b/src/initscripts/init.d/hostapd @@ -75,7 +75,10 @@ case "${1}" in fi fi - # First reset to World (00) and then set new country + # First set to any country then reset to World (00) + # and then set new country because the card is only + # reprogrammed if the region was changed. + /usr/sbin/iw reg set DE /usr/sbin/iw reg set 00 /usr/sbin/iw reg set $COUNTRY From 513c321ebedcf0865863b95ccd453f155f7703ed Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Wed, 26 Mar 2014 08:35:00 +0100 Subject: [PATCH 15/15] wlanap.cgi: fix missing line from wlan info. --- html/cgi-bin/entropy.cgi | 0 html/cgi-bin/wlanap.cgi | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 html/cgi-bin/entropy.cgi diff --git a/html/cgi-bin/entropy.cgi b/html/cgi-bin/entropy.cgi old mode 100755 new mode 100644 diff --git a/html/cgi-bin/wlanap.cgi b/html/cgi-bin/wlanap.cgi index bbf25462d..50806ac78 100644 --- a/html/cgi-bin/wlanap.cgi +++ b/html/cgi-bin/wlanap.cgi @@ -512,7 +512,7 @@ if ( $wlanapsettings{'DRIVER'} eq 'MADWIFI' ){ @status = `wlanconfig $wlanapsettings{'INTERFACE'} list`; } if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ - @status = `iw dev $wlanapsettings{'INTERFACE'} info && iw dev $wlanapsettings{'INTERFACE'} station dump`; + @status = `iw dev $wlanapsettings{'INTERFACE'} info && iw dev $wlanapsettings{'INTERFACE'} station dump && echo ""`; } print <