From 40fa6ddeaca6b2b6ea02109efd07d31daa72da59 Mon Sep 17 00:00:00 2001 From: Erik Fonnesbeck Date: Fri, 20 Apr 2012 02:38:58 -0600 Subject: [PATCH] Allow optionally using the type of NAT reflection implementation used for 1:1 mappings with port forwards as well, in addition to allowing the old type, which is still useful in its own way. --- etc/inc/filter.inc | 103 ++++++++++++++++----- usr/local/www/firewall_nat_edit.php | 9 +- usr/local/www/system_advanced_firewall.php | 58 ++++++++---- 3 files changed, 125 insertions(+), 45 deletions(-) diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc index 472be3e9e1..bac63d7a4a 100644 --- a/etc/inc/filter.inc +++ b/etc/inc/filter.inc @@ -1052,10 +1052,13 @@ function filter_generate_reflection_nat($rule, &$route_table, $nat_ifs, $protoco } } + if(!empty($natrules)) + $natrules .= "\n"; + return $natrules; } -function filter_generate_reflection($rule, $nordr, $rdr_ifs, $srcaddr, $dstaddr_port, &$starting_localhost_port, &$reflection_txt) { +function filter_generate_reflection_proxy($rule, $nordr, $rdr_ifs, $srcaddr, $dstaddr_port, &$starting_localhost_port, &$reflection_txt) { global $FilterIflist, $config; // Initialize natrules holder string @@ -1676,10 +1679,27 @@ function filter_nat_rules_generate() { continue; /* unresolvable alias */ } + if(is_alias($rule['target'])) + $target_ip = filter_expand_alias($rule['target']); + else if(is_ipaddr($rule['target'])) + $target_ip = $rule['target']; + else if(is_ipaddr($FilterIflist[$rule['target']]['ip'])) + $target_ip = $FilterIflist[$rule['target']]['ip']; + else + $target_ip = $rule['target']; + $target_ip = trim($target_ip); + if($rule['associated-rule-id'] == "pass") $rdrpass = "pass "; else $rdrpass = ""; + + if (isset($rule['nordr'])) { + $nordr = "no "; + $rdrpass = ""; + } else + $nordr = ""; + if(!$rule['interface']) $natif = "wan"; else @@ -1690,33 +1710,65 @@ function filter_nat_rules_generate() { $srcaddr = filter_generate_address($rule, 'source', true); $dstaddr = filter_generate_address($rule, 'destination', true); + $srcaddr = trim($srcaddr); + $dstaddr = trim($dstaddr); if(!$dstaddr) $dstaddr = $FilterIflist[$natif]['ip']; - $natif = $FilterIflist[$natif]['if']; + $dstaddr_port = explode(" ", $dstaddr); + if(empty($dstaddr_port[0]) || strtolower(trim($dstaddr_port[0])) == "port") + continue; // Skip port forward if no destination address found + $dstaddr_reflect = $dstaddr; + if(isset($rule['destination']['any'])) { + /* With reflection enabled, destination of 'any' has side effects + * that most people would not expect, so change it on reflection rules. */ + $dstaddr_reflect = $FilterIflist[$natif]['ip']; + if(!empty($FilterIflist[$natif]['sn'])) + $dstaddr_reflect = gen_subnet($dstaddr_reflect, $FilterIflist[$natif]['sn']) . '/' . $FilterIflist[$natif]['sn']; - if (isset($rule['nordr'])) { - $nordr = "no "; - $rdrpass = ""; - } else - $nordr = ""; - - if((!isset($config['system']['disablenatreflection']) || $rule['natreflection'] == "enable") - && $rule['natreflection'] != "disable") { - $nat_if_list = filter_get_reflection_interfaces($natif); - } else { - $nat_if_list = array(); + if($dstaddr_port[2]) + $dstaddr_reflect .= " port " . $dstaddr_port[2]; } - if($srcaddr <> "" && $dstaddr <> "" && $natif) { - $srcaddr = trim($srcaddr); - $dstaddr = trim($dstaddr); + $natif = $FilterIflist[$natif]['if']; - $natrules .= "{$nordr}rdr {$rdrpass}on {$natif} proto {$protocol} from {$srcaddr} to {$dstaddr}" . ($nordr == "" ? " -> {$target}{$localport}" : ""); + $reflection_type = "none"; + if($rule['natreflection'] != "disable" && $dstaddr_port[0] != "0.0.0.0") { + if($rule['natreflection'] == "enable") + $reflection_type = "proxy"; + else if($rule['natreflection'] == "purenat") + $reflection_type = "purenat"; + else if(!isset($config['system']['disablenatreflection'])) { + if(isset($config['system']['enablenatreflectionpurenat'])) + $reflection_type = "purenat"; + else + $reflection_type = "proxy"; + } + } + + if($reflection_type != "none") + $nat_if_list = filter_get_reflection_interfaces($natif); + else + $nat_if_list = array(); + + $localport_nat = $localport; + if(empty($localport_nat) && $dstaddr_port[2]) + $localport_nat = " port " . $dstaddr_port[2]; + + if($srcaddr <> "" && $dstaddr <> "" && $natif) { + $rdr_if_list = $natif; + if($reflection_type == "purenat" || isset($rule['nordr'])) { + $nat_if_list = array_merge(array($natif), $nat_if_list); + $rdr_if_list = implode(" ", $nat_if_list); + if(count($nat_if_list) > 1) + $rdr_if_list = "{ {$rdr_if_list} }"; + } + + $natrules .= "{$nordr}rdr {$rdrpass}on {$rdr_if_list} proto {$protocol} from {$srcaddr} to {$dstaddr}" . ($nordr == "" ? " -> {$target}{$localport}" : ""); /* Does this rule redirect back to a internal host? */ - if(isset($rule['destination']['any']) && !interface_has_gateway($rule['interface']) && !isset($rule['nordr'])) { + if(isset($rule['destination']['any']) && !isset($rule['nordr']) && !isset($config['system']['enablenatreflectionhelper']) && !interface_has_gateway($rule['interface'])) { $rule_interface_ip = find_interface_ip($natif); $rule_interface_subnet = find_interface_subnet($natif); if(!empty($rule_interface_ip) && !empty($rule_interface_subnet)) { @@ -1726,11 +1778,18 @@ function filter_nat_rules_generate() { $natrules .= "nat on {$natif} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$dstport[0]} -> ({$natif})\n"; } } - $natrules .= filter_generate_reflection($rule, $nordr, $nat_if_list, $srcaddr, $dstaddr, $starting_localhost_port, $reflection_rules); - $natrules .= "\n"; - foreach ($reflection_rules as $txtline) - fwrite($inetd_fd, $txtline); + if($reflection_type == "proxy" && !isset($rule['nordr'])) { + $natrules .= filter_generate_reflection_proxy($rule, $nordr, $nat_if_list, $srcaddr, $dstaddr, $starting_localhost_port, $reflection_rules); + $nat_if_list = array($natif); + + foreach ($reflection_rules as $txtline) + fwrite($inetd_fd, $txtline); + } + + $natrules .= "\n"; + if(!isset($rule['nordr'])) + $natrules .= filter_generate_reflection_nat($rule, $route_table, $nat_if_list, $protocol, "{$target}{$localport_nat}", $target_ip); } } } diff --git a/usr/local/www/firewall_nat_edit.php b/usr/local/www/firewall_nat_edit.php index 83cfd73e71..d0ab5ba2ae 100755 --- a/usr/local/www/firewall_nat_edit.php +++ b/usr/local/www/firewall_nat_edit.php @@ -330,7 +330,7 @@ if ($_POST) { else unset($natent['nosync']); - if ($_POST['natreflection'] == "enable" || $_POST['natreflection'] == "disable") + if ($_POST['natreflection'] == "enable" || $_POST['natreflection'] == "purenat" || $_POST['natreflection'] == "disable") $natent['natreflection'] = $_POST['natreflection']; else unset($natent['natreflection']); @@ -783,9 +783,10 @@ include("fbegin.inc"); ?> diff --git a/usr/local/www/system_advanced_firewall.php b/usr/local/www/system_advanced_firewall.php index a8dcae1d01..9678fd8a07 100644 --- a/usr/local/www/system_advanced_firewall.php +++ b/usr/local/www/system_advanced_firewall.php @@ -59,10 +59,7 @@ $pconfig['maximumtableentries'] = $config['system']['maximumtableentries']; $pconfig['disablereplyto'] = isset($config['system']['disablereplyto']); $pconfig['disablenegate'] = isset($config['system']['disablenegate']); $pconfig['disablenatreflection'] = $config['system']['disablenatreflection']; -if (!isset($config['system']['enablebinatreflection'])) - $pconfig['disablebinatreflection'] = "yes"; -else - $pconfig['disablebinatreflection'] = ""; +$pconfig['enablebinatreflection'] = $config['system']['enablebinatreflection']; $pconfig['reflectiontimeout'] = $config['system']['reflectiontimeout']; $pconfig['bypassstaticroutes'] = isset($config['filter']['bypassstaticroutes']); $pconfig['disablescrub'] = isset($config['system']['disablescrub']); @@ -121,15 +118,21 @@ if ($_POST) { $config['system']['maximumstates'] = $_POST['maximumstates']; $config['system']['maximumtableentries'] = $_POST['maximumtableentries']; - if($_POST['disablenatreflection'] == "yes") - $config['system']['disablenatreflection'] = $_POST['disablenatreflection']; - else + if($_POST['natreflection'] == "proxy") { unset($config['system']['disablenatreflection']); + unset($config['system']['enablenatreflectionpurenat']); + } else if($_POST['natreflection'] == "purenat") { + unset($config['system']['disablenatreflection']); + $config['system']['enablenatreflectionpurenat'] = "yes"; + } else { + $config['system']['disablenatreflection'] = "yes"; + unset($config['system']['enablenatreflectionpurenat']); + } - if($_POST['disablebinatreflection'] == "yes") - unset($config['system']['enablebinatreflection']); - else + if($_POST['enablebinatreflection'] == "yes") $config['system']['enablebinatreflection'] = "yes"; + else + unset($config['system']['enablebinatreflection']); if($_POST['disablereplyto'] == "yes") $config['system']['disablereplyto'] = $_POST['disablereplyto']; @@ -380,33 +383,50 @@ function update_description(itemnum) { - + - /> - + +
+ +

+ +

+ +

+
- + +
+ - + - /> - + /> + +

+ +

+ -   + />
- +