From 59ecde4930ac6580db3634664341546fd5328374 Mon Sep 17 00:00:00 2001 From: Renato Botelho Date: Thu, 29 Apr 2010 08:21:17 -0300 Subject: Improve NAT Port Forwarding New features available are: * Now you can disable a rule * You can define "no rdr" rules * Source type, address and port, with an option "not" for exceptions * Destination type, address and port, with an option "not" for exceptions Implemented by: Carlos Eduardo Ramos Renato Botelho Vinicius Coque Reviewed by: cmb and efonne Sponsored by: BluePex Security Solutions --- etc/inc/filter.inc | 858 +++++++++++++++++++++++---------------------- etc/inc/globals.inc | 2 +- etc/inc/pfsense-utils.inc | 6 +- etc/inc/upgrade_config.inc | 31 ++ 4 files changed, 466 insertions(+), 431 deletions(-) (limited to 'etc') diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc index aec0757..cba2ae2 100644 --- a/etc/inc/filter.inc +++ b/etc/inc/filter.inc @@ -34,9 +34,10 @@ POSSIBILITY OF SUCH DAMAGE. pfSense_BUILDER_BINARIES: /sbin/sysctl /sbin/kldload /usr/sbin/tcpdump /sbin/pfctl /bin/rm - pfSense_BUILDER_BINARIES: /usr/sbin/inetd + pfSense_BUILDER_BINARIES: /usr/sbin/inetd pfSense_MODULE: filter */ + /* DISABLE_PHP_LINT_CHECKING */ /* include all configuration functions */ @@ -58,17 +59,17 @@ function flowtable_configure() { return; // Figure out how many flows we should reserve // sized 2x larger than the number of unique connection destinations. - if($config['system']['maximumstates'] <> "" && is_numeric($config['system']['maximumstates'])) + if($config['system']['maximumstates'] <> "" && is_numeric($config['system']['maximumstates'])) $maxstates = $config['system']['maximumstates']; else - $maxstates = "150000"; + $maxstates = "150000"; // nmbflows cpu count * ($maxstates * 2) $cpus = trim(`/sbin/sysctl kern.smp.cpus | /usr/bin/cut -d' ' -f2`); $nmbflows = ($cpus*($maxstates*2)); // Is flowtable enabled? if($config['system']['flowtable']) $flowtable_enable = 1; - else + else $flowtable_enable = 0; // Flowtable currently only works on 8.0 if(get_freebsd_version() == "8") { @@ -76,13 +77,13 @@ function flowtable_configure() { mwexec("/sbin/sysctl net.inet.flowtable.nmbflows={$config['system']['maximumstates']}"); mwexec("/sbin/sysctl net.inet.ip.output_flowtable_size={$nmbflows}"); } - mwexec("/sbin/sysctl net.inet.flowtable.enable={$flowtable_enable}"); - } + mwexec("/sbin/sysctl net.inet.flowtable.enable={$flowtable_enable}"); + } } function filter_load_ipfw() { global $config; - + if(!is_module_loaded("ipfw.ko")) { mute_kernel_msgs(); mwexec("/sbin/kldload ipfw"); @@ -99,7 +100,7 @@ function filter_load_ipfw() { */ mwexec("/sbin/sysctl net.inet.ip.pfil.outbound=\"pf\""); } - + /* Set ipfw state limit */ if($config['system']['maximumstates'] <> "" && is_numeric($config['system']['maximumstates'])) { /* Set ipfw states to user defined maximum states in Advanced menu. */ @@ -175,22 +176,22 @@ function filter_configure_sync() { $GatewayGroupsList = return_gateway_groups_array(); /* generate aliases */ - if($g['booting'] == true) + if($g['booting'] == true) echo "."; update_filter_reload_status("Creating aliases"); $aliases = filter_generate_aliases(); /* generate nat rules */ - if($g['booting'] == true) + if($g['booting'] == true) echo "."; update_filter_reload_status("Generating NAT rules"); $natrules = filter_nat_rules_generate(); /* generate pfctl rules */ - if($g['booting'] == true) + if($g['booting'] == true) echo "."; update_filter_reload_status("Generating filter rules"); $pfrules = filter_rules_generate(); /* generate altq, limiter */ - if($g['booting'] == true) + if($g['booting'] == true) echo "."; update_filter_reload_status("Generating ALTQ queues"); $altq_queues = filter_generate_altq_queues(); @@ -222,27 +223,27 @@ function filter_configure_sync() { $rules .= "{$aliases} \n"; update_filter_reload_status("Setting up logging information"); $rules .= filter_setup_logging_interfaces(); - if($config['system']['optimization'] <> "") { + if($config['system']['optimization'] <> "") { $rules .= "set optimization {$config['system']['optimization']}\n"; if($config['system']['optimization'] == "conservative") { $rules .= "set timeout { udp.first 300, udp.single 150, udp.multiple 900 }\n"; } - } else { + } else { $rules .= "set optimization normal\n"; } if($config['system']['maximumstates'] <> "" && is_numeric($config['system']['maximumstates'])) { /* User defined maximum states in Advanced menu. */ $rules .= "set limit states {$config['system']['maximumstates']}\n"; } else { - $max_states = pfsense_default_state_size(); - $rules .= "set limit states {$max_states}\n"; + $max_states = pfsense_default_state_size(); + $rules .= "set limit states {$max_states}\n"; } $rules .= discover_pkg_rules("pfearly"); - + // Configure flowtable support if enabled. flowtable_configure(); - + $rules .= "\n"; $rules .= "set skip on pfsync0\n"; $rules .= "\n"; @@ -254,7 +255,7 @@ function filter_configure_sync() { $rules .= "{$altq_queues}\n"; $rules .= "{$natrules}\n"; $rules .= "{$pfrules}\n"; - + $rules .= discover_pkg_rules("pflate"); if(!file_put_contents("{$g['tmp_path']}/rules.debug", $rules, LOCK_EX)) { @@ -263,7 +264,7 @@ function filter_configure_sync() { return; } - /* + /* * XXX: This are not being used for now so just comment them out. $rules = "1"; // force to be diff from oldrules $oldrules = "2"; // force to be diff from rules @@ -284,7 +285,7 @@ function filter_configure_sync() { echo "pfctl done at $mt\n"; } /* check for a error while loading the rules file. if an error has occured - * then output the contents of the error to the caller + * then output the contents of the error to the caller */ if($rules_loading <> 0) { $rules_error = exec_command("/sbin/pfctl -f {$g['tmp_path']}/rules.debug"); @@ -320,7 +321,7 @@ function filter_configure_sync() { fclose($filterdnsfd); } killbypid("{$g['tmp_path']}/filterdns.pid"); - /* + /* * FilterDNS has three debugging levels. The default choosen is 1. * Availabe are level 2 and greater then 2. */ @@ -331,17 +332,17 @@ function filter_configure_sync() { $fda = fopen("{$g['tmp_path']}/commands.txt", "w"); if($fda) { if($after_filter_configure_run) - foreach($after_filter_configure_run as $afcr) - fwrite($fda, $afcr . "\n"); + foreach($after_filter_configure_run as $afcr) + fwrite($fda, $afcr . "\n"); /* - * we need a way to let a user run a shell cmd after each - * filter_configure() call. run this xml command after - * each change. - */ - if($config['system']['afterfilterchangeshellcmd'] <> "") - fwrite($fda, $config['system']['afterfilterchangeshellcmd'] . "\n"); + * we need a way to let a user run a shell cmd after each + * filter_configure() call. run this xml command after + * each change. + */ + if($config['system']['afterfilterchangeshellcmd'] <> "") + fwrite($fda, $config['system']['afterfilterchangeshellcmd'] . "\n"); - fclose($fda); + fclose($fda); } unlock($filterlck); @@ -383,7 +384,7 @@ function filter_generate_scrubing() { $scrubrules = ""; /* disable scrub option */ foreach ($FilterIflist as $scrubif => $scrubcfg) { - if(isset($scrubcfg['virtual'])) + if(isset($scrubcfg['virtual'])) continue; /* set up MSS clamping */ if($scrubcfg['mtu'] <> "" && is_numeric($scrubcfg['mtu']) && $scrubcfg['if'] != "pppoe" && $scrubcfg['if'] != "pptp") @@ -409,7 +410,7 @@ function filter_generate_scrubing() { function filter_generate_nested_alias($name, $alias, &$aliasnesting, &$aliasaddrnesting) { global $aliastable, $filterdns; - + $addresses = split(" ", $alias); $finallist = ""; $builtlist = ""; @@ -446,10 +447,10 @@ function filter_expand_alias($alias_name) global $config; if(isset($config['aliases']['alias'])) { - foreach ($config['aliases']['alias'] as $aliased) { + foreach ($config['aliases']['alias'] as $aliased) { if($aliased['name'] == $alias_name) { $aliasnesting = array(); - $aliasaddrnesting = array(); + $aliasaddrnesting = array(); return filter_generate_nested_alias($aliased['name'], $aliased['address'], $aliasnesting, $aliasaddrnesting); } } @@ -494,7 +495,7 @@ function filter_generate_aliases() { $aliases .= "table <{$aliased['name']}> persist\n"; else $aliases .= "table <{$aliased['name']}> { {$addrlist}{$extralias} } \n"; - + $aliases .= "{$aliased['name']} = \"<{$aliased['name']}>\"\n"; } else if($aliased['type'] == "openvpn") { $openvpncfg = array(); @@ -515,7 +516,7 @@ function filter_generate_aliases() { } } $aliases .= "table <{$aliased['name']}> { {$newaddress}{$extralias} } \n"; - $aliases .= "{$aliased['name']} = \"<{$aliased['name']}>\"\n"; + $aliases .= "{$aliased['name']} = \"<{$aliased['name']}>\"\n"; } elseif($aliased['type'] == "urltable") { $urlfn = alias_expand_urltable($aliased['name']); if ($urlfn) { @@ -624,7 +625,7 @@ function filter_generate_optcfg_array() { $oic['bridge'] = link_interface_to_bridge($if); $FilterIflist[$if] = $oic; } - + if($config['pptpd']['mode'] == "server" || $config['pptpd']['mode'] == "redir") { $oic = array(); $oic['if'] = 'pptp'; @@ -652,7 +653,7 @@ function filter_generate_optcfg_array() { $oic['mode'] = $config['l2tp']['mode']; $oic['virtual'] = true; $FilterIflist['l2tp'] = $oic; - } + } if($config['pppoe']['mode'] == "server") { $oic = array(); $oic['if'] = 'pppoe'; @@ -710,7 +711,7 @@ function filter_flush_state_table() { return mwexec("/sbin/pfctl -F state"); } -function filter_generate_reflection($rule, $extport, &$starting_localhost_port, &$reflection_txt) { +function filter_generate_reflection($rule, $nordr, $srcaddr, $dstport, &$starting_localhost_port, &$reflection_txt) { global $FilterIflist, $config; // Initialize natrules holder string @@ -739,18 +740,19 @@ function filter_generate_reflection($rule, $extport, &$starting_localhost_port, update_filter_reload_status("Creating reflection rule for {$rule['descr']}..."); - if($extport[1]) - $range_end = ($extport[1]); + if($dstport[1]) + $range_end = ($dstport[1]); else - $range_end = ($extport[0]); + $range_end = ($dstport[0]); $range_end++; + /* TODO: support multiple ip's in an alias. */ - if (is_alias($rule['external-address'])) - $extaddr = filter_expand_alias($rule['external-address']); - else if(is_ipaddr($rule['external-address'])) - $extaddr = $rule['external-address']; + if (is_alias($rule['destination']['address'])) + $dstaddr = filter_expand_alias($rule['destination']['address']); + else if(is_ipaddr($rule['destination']['address'])) + $dstaddr = $rule['destination']['address']; else if (is_ipaddr($FilterIflist[$rule['interface']]['ip'])) - $extaddr = $FilterIflist[$rule['interface']]['ip']; + $dstaddr = $FilterIflist[$rule['interface']]['ip']; else return "\n"; @@ -765,8 +767,8 @@ function filter_generate_reflection($rule, $extport, &$starting_localhost_port, if($rule['local-port']) $lrange_start = $rule['local-port']; - if($range_end - $extport[0] > 500) { - $range_end = $extport[0]+1; + if($range_end - $dstport[0] > 500) { + $range_end = $dstport[0]+1; log_error("Not installing nat reflection rules for a port range > 500"); /* only install reflection rules for < 19991 items */ } else if($starting_localhost_port < 19991) { @@ -783,21 +785,21 @@ function filter_generate_reflection($rule, $extport, &$starting_localhost_port, } $inetdport = $starting_localhost_port; - if(($range_end - 1) > $extport[0]) { + if(($range_end - 1) > $dstport[0]) { $rflctrange = "{$starting_localhost_port}"; - $delta = $range_end - $extport[0] - 1; + $delta = $range_end - $dstport[0] - 1; if(($starting_localhost_port + $delta) > 19990) { - log_error("Installing partial nat reflection rules. Maximum 1,000 reached."); - $delta = 19990 - $starting_localhost_port; - } + log_error("Installing partial nat reflection rules. Maximum 1,000 reached."); + $delta = 19990 - $starting_localhost_port; + } $starting_localhost_port = $starting_localhost_port + $delta; $rflctrange .= ":{$starting_localhost_port}"; - $rflctintrange = "{$extport[0]}:{$range_end}"; + $rflctintrange = "{$dstport[0]}:{$range_end}"; if($rflctnorange) $toadd_array = range($loc_pt, $loc_pt + $delta); } else { $rflctrange = $starting_localhost_port; - $rflctintrange = $extport[0]; + $rflctintrange = $dstport[0]; if($rflctnorange) $toadd_array = array($loc_pt); $starting_localhost_port++; @@ -811,7 +813,8 @@ function filter_generate_reflection($rule, $extport, &$starting_localhost_port, $reflection_txt[] = "{$inetdport}\tdgram\tudp\tnowait/0\tnobody\t/usr/bin/nc\tnc -u -w {$reflectiontimeout} {$target} {$tda}\n"; $inetdport++; } - $natrules .= "rdr on {$rdr_if_list} proto {$protocol} from any to {$extaddr} port {$rflctintrange} tag PFREFLECT -> 127.0.0.1 port {$rflctrange}\n"; + $natrules .= "{$nordr}rdr on {$rdr_if_list} proto {$protocol} from {$srcaddr} to {$dstaddr} port {$rflctintrange} tag PFREFLECT" . + ($nordr == "" ? " -> 127.0.0.1 port {$rflctrange}" : "") . "\n"; break; case "tcp": case "udp": @@ -827,7 +830,8 @@ function filter_generate_reflection($rule, $extport, &$starting_localhost_port, $reflection_txt[] = "{$inetdport}\t{$socktype}\t{$protocol}\tnowait/0\tnobody\t/usr/bin/nc\tnc {$dash_u}-w {$reflectiontimeout} {$target} {$tda}\n"; $inetdport++; } - $natrules .= "rdr on {$rdr_if_list} proto {$protocol} from any to {$extaddr} port {$rflctintrange} tag PFREFLECT -> 127.0.0.1 port {$rflctrange}\n"; + $natrules .= "{$nordr}rdr on {$rdr_if_list} proto {$protocol} from {$srcaddr} to {$dstaddr} port {$rflctintrange} tag PFREFLECT" . + ($nordr == "" ? " -> 127.0.0.1 port {$rflctrange}" : "") . "\n"; break; } } @@ -852,7 +856,7 @@ function filter_nat_rules_generate_if($if, $src = "any", $srcport = "", $dst = " else $tgt = "($if)"; } - /* Add the protocol, if defined */ + /* Add the protocol, if defined */ if (!empty($proto) && $proto != "any") $protocol = " proto {$proto}"; else @@ -879,7 +883,7 @@ function filter_nat_rules_generate_if($if, $src = "any", $srcport = "", $dst = " if(!$natport) $staticnatport_txt = " port 1024:65535"; // set source port range else - $staticnatport_txt = ""; + $staticnatport_txt = ""; /* Allow for negating NAT entries */ if($nonat) { $nat = "no nat"; @@ -902,7 +906,7 @@ function filter_nat_rules_generate() { global $config, $g, $after_filter_configure_run, $FilterIflist; $natrules = "nat-anchor \"natearly/*\"\n"; - + $natrules .= "nat-anchor \"natrules/*\"\n\n"; update_filter_reload_status("Creating 1:1 rules..."); @@ -915,7 +919,7 @@ function filter_nat_rules_generate() { $sn = $natent['subnet']; if(!$natent['interface']) $natif = "wan"; - else + else $natif = $natent['interface']; $natif = $FilterIflist[$natif]['if']; if($natif) @@ -936,7 +940,7 @@ function filter_nat_rules_generate() { $dst = $obent['destination']['address']; if(!$obent['interface']) $natif = "wan"; - else + else $natif = $obent['interface']; if (!isset($FilterIflist[$natif])) @@ -965,7 +969,7 @@ function filter_nat_rules_generate() { foreach ($config['staticroutes']['route'] as $route) { $netip = explode("/", $route['network']); if(is_array($config['gateways']['gateway_item'])) { - foreach($config['gateways']['gateway_item'] as $gateway) { + foreach($config['gateways']['gateway_item'] as $gateway) { if($route['gateway'] == $gateway['name']) { $gatewayip = $gateway['gateway']; $interfacegw = $gateway['interface']; @@ -1018,7 +1022,7 @@ function filter_nat_rules_generate() { } } /* add openvpn interfaces */ - if(is_array($config['openvpn']['openvpn-server'])) { + if(is_array($config['openvpn']['openvpn-server'])) { foreach ($config['openvpn']['openvpn-server'] as $ovpnsrv) { if (!empty($ovpnsrv['tunnel_network'])) { $numberofnathosts++; @@ -1026,7 +1030,7 @@ function filter_nat_rules_generate() { } } } - if(is_array($config['openvpn']['openvpn-client'])) { + if(is_array($config['openvpn']['openvpn-client'])) { foreach ($config['openvpn']['openvpn-client'] as $ovpnsrv) { if (!empty($ovpnsrv['tunnel_network'])) { $numberofnathosts++; @@ -1038,7 +1042,7 @@ function filter_nat_rules_generate() { if($numberofnathosts > 4) { $natrules .= "table { {$tonathosts} }\n"; $macroortable = ""; - } else if($numberofnathosts > 0) { + } else if($numberofnathosts > 0) { $natrules .= "tonatsubnets = \"{ {$tonathosts} }\"\n"; $macroortable = "\$tonatsubnets"; } @@ -1056,7 +1060,7 @@ function filter_nat_rules_generate() { "{$macroortable}", null, "", null, $target, null, isset($ifcfg['nonat'])); $natrules .= "\n"; } - } + } endif; } @@ -1081,7 +1085,7 @@ function filter_nat_rules_generate() { $direct_networks_list = filter_get_direct_networks_list(); if($vpns_list) $natrules .= "table { $vpns_list }\n"; - if($direct_networks_list) + if($direct_networks_list) $natrules .= "table { $direct_networks_list }\n"; /* DIAG: add ipv6 NAT, if requested */ @@ -1107,101 +1111,91 @@ function filter_nat_rules_generate() { $natrules .= "# NAT Inbound Redirects\n"; foreach ($config['nat']['rule'] as $rule) { update_filter_reload_status("Creating NAT rule {$rule['descr']}"); + + if(isset($rule['disabled'])) + continue; + + if (strtolower($rule['protocol']) == "tcp/udp") + $protocol = "{ tcp udp }"; + else + $protocol = strtolower($rule['protocol']); + /* if item is an alias, expand */ - $extport = ""; - $extport[0] = alias_expand($rule['external-port']); - if(!$extport[0]) - $extport = explode("-", $rule['external-port']); + $srcport = ""; + $srcport[0] = alias_expand($rule['source']['port']); + if(!$srcport[0]) + $srcport = explode("-", $rule['source']['port']); + + /* if item is an alias, expand */ + $dstport = ""; + $dstport[0] = alias_expand($rule['destination']['port']); + if(!$dstport[0]) + $dstport = explode("-", $rule['destination']['port']); + /* if item is an alias, expand */ $localport = alias_expand($rule['local-port']); - if(!$localport) + if(!$localport || $rule['destination']['port'] == $rule['local-port']) { $localport = ""; - else + } else { + if(($dstport[1]) && ($dstport[0] != $dstport[1])) { + $localendport = $localport + ($dstport[1] - $dstport[0]); + + $localport .= ":$localendport"; + } + $localport = " port {$localport}"; + } + $target = alias_expand($rule['target']); if(!$target) { $natrules .= "# Unresolvable alias {$rule['target']}\n"; continue; /* unresolvable alias */ } + if($rule['associated-rule-id'] == "pass") - $rdrpass = "pass"; + $rdrpass = "pass "; else - $rdrpass = ""; + $rdrpass = ""; if(!$rule['interface']) - $natif = "wan"; - else - $natif = $rule['interface']; + $natif = "wan"; + else + $natif = $rule['interface']; if (!isset($FilterIflist[$natif])) continue; - $extaddr = alias_expand($rule['external-address']); - if($rule['external-address'] == "any") - $extaddr = "any"; - if(!$extaddr) - $extaddr = $FilterIflist[$natif]['ip']; + $srcaddr = filter_generate_address($rule, 'source', true); + $dstaddr = filter_generate_address($rule, 'destination', true); + + if(!$dstaddr) + $dstaddr = $FilterIflist[$natif]['ip']; + $natif = $FilterIflist[$natif]['if']; - if($extaddr <> "") { + if (isset($rule['nordr'])) + $nordr = "no "; + else + $nordr = ""; + + if($srcaddr <> "" && $dstaddr <> "") { /* is rule a port range? */ - if((!$extport[1]) || ($extport[0] == $extport[1])) { - - switch ($rule['protocol']) { - case "tcp/udp": - if($natif) { - if($rule['external-port'] <> $rule['local-port']) - $natrules .= "{$nordr} rdr {$rdrpass} on $natif proto { tcp udp } from any to {$extaddr} port {$extport[0]} -> {$target}{$localport}"; - else - $natrules .= "{$nordr} rdr {$rdrpass} on $natif proto { tcp udp } from any to {$extaddr} port {$extport[0]} -> {$target}"; - } - break; - case "udp": - case "tcp": - if($extport[0]) - if($natif) { - if($rule['external-port'] <> $rule['local-port']) - $natrules .= "rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} port {$extport[0]} -> {$target}{$localport}"; - else - $natrules .= "rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} port {$extport[0]} -> {$target}"; - } - else - if($natif) - $natrules .= "rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}{$localport}"; - break; - default: - $natrules .= "rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}"; - break; - } - } else { - switch ($rule['protocol']) { - case "tcp/udp": - if($natif) - $natrules .= "{$nordr} rdr {$rdrpass} on $natif proto { tcp udp } from any to {$extaddr} port {$extport[0]}:{$extport[1]} -> {$target}{$localport}:*"; - break; - case "udp": - case "tcp": - if($natif) - $natrules .= "{$nordr} rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} port {$extport[0]}:{$extport[1]} -> {$target}{$localport}:*"; - break; - default: - if($natif) - $natrules .= "{$nordr} rdr {$rdrpass} on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}"; - } - } + if($natif) + $natrules .= "{$nordr}rdr {$rdrpass}on {$natif} proto {$protocol} from {$srcaddr} to {$dstaddr}" . ($nordr == "" ? " -> {$target}{$localport}" : ""); + /* Does this rule redirect back to a internal host? */ - if($extaddr == "any" && !interface_has_gateway($rule['interface'])) { + if($dstaddr == "any" && !interface_has_gateway($rule['interface'])) { $rule_interface_ip = find_interface_ip($natif); $rule_interface_subnet = find_interface_subnet($natif); $rule_subnet = gen_subnet($rule_interface_ip, $rule_interface_subnet); $natrules .= "\n"; $natrules .= "no nat on {$natif} proto tcp from ({$natif}) to {$rule_subnet}/{$rule_interface_subnet}\n"; - $natrules .= "nat on {$natif} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$extport[0]} -> ({$natif})\n"; + $natrules .= "nat on {$natif} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$dstport[0]} -> ({$natif})\n"; } - $natrules .= filter_generate_reflection($rule, $extport, $starting_localhost_port, $reflection_rules); + $natrules .= filter_generate_reflection($rule, $nordr, $srcaddr, $dstport, $starting_localhost_port, $reflection_rules); $natrules .= "\n"; foreach ($reflection_rules as $txtline) - fwrite($inetd_fd, $txtline); + fwrite($inetd_fd, $txtline); } } } @@ -1219,12 +1213,12 @@ function filter_nat_rules_generate() { else if($pptpdcfg['mode'] == "redir") $pptpdtarget = $pptpdcfg['redir']; if($pptpdcfg['mode'] == "redir" && is_array($FilterIflist['wan'])) { - /* + /* * NB: ermal -- the rdr rule below is commented out now that we have a solution - * for PPTP passthrough. This unbreaks other GRE traffic passing - * through pfSense. + * for PPTP passthrough. This unbreaks other GRE traffic passing + * through pfSense. * After some more testing this will be removed compeletely. - */ + */ $natrules .= << "") @@ -1388,7 +1386,7 @@ function filter_generate_user_rule($rule) { $ifcfg = $FilterIflist[$rule['interface']]; if($pptpdcfg['mode'] != "server") { if(($rule['source']['network'] == "pptp") || - ($rule['destination']['network'] == "pptp")) + ($rule['destination']['network'] == "pptp")) return "# source network or destination network == pptp on " . $rule['descr']; } @@ -1409,7 +1407,7 @@ function filter_generate_user_rule($rule) { } if($type == "reject") { $aline['type'] = "block return "; - } else + } else $aline['type'] = $type . " "; if(isset($rule['floating']) && $rule['floating'] == "yes") { if($rule['direction'] != "any") @@ -1465,8 +1463,8 @@ function filter_generate_user_rule($rule) { $routeto .= "} "; } else { $routeto .= "} round-robin "; - if(isset($config['system']['lb_use_sticky'])) - $routeto .= " sticky-address "; + if(isset($config['system']['lb_use_sticky'])) + $routeto .= " sticky-address "; } } /* Add the load balanced gateways */ @@ -1506,7 +1504,7 @@ function filter_generate_user_rule($rule) { $aline['prot'] = " proto tcp "; } update_filter_reload_status("Creating rule {$rule['descr']}"); - + /* source address */ $src = filter_generate_address($rule, "source"); if(empty($src) || ($src == "/")) { @@ -1581,7 +1579,7 @@ function filter_generate_user_rule($rule) { if($noadvoptions == false || $l7_present) if( isset($rule['source-track']) and $rule['source-track'] <> "" or - isset($rule['max']) and $rule['max'] <> "" or + isset($rule['max']) and $rule['max'] <> "" or isset($rule['max-src-nodes']) and $rule['max-src-nodes'] <> "" or isset($rule['max-src-conn']) and $rule['max-src-conn'] <> "" or isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "" or @@ -1602,14 +1600,16 @@ function filter_generate_user_rule($rule) { $aline['flags'] .= "max-src-states " . $rule['max-src-states'] . " "; if(isset($rule['statetimeout']) and $rule['statetimeout'] <> "") $aline['flags'] .= "tcp.established " . $rule['statetimeout'] . " "; - if(isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "" - and isset($rule['max-src-conn-rates']) and $rule['max-src-conn-rates'] <> "") { + if(isset($rule['max-src-conn-rate']) + and $rule['max-src-conn-rate'] <> "" + and isset($rule['max-src-conn-rates']) + and $rule['max-src-conn-rates'] <> "") { $aline['flags'] .= "max-src-conn-rate " . $rule['max-src-conn-rate'] . " "; $aline['flags'] .= "/" . $rule['max-src-conn-rates'] . ", overload flush global "; } - if(!empty($aline['divert'])) + if(!empty($aline['divert'])) $aline['flags'] .= "max-packets 5 "; - + $aline['flags'] .= " ) "; } } @@ -1638,22 +1638,22 @@ function filter_generate_user_rule($rule) { } /* is a time based rule schedule attached? */ - if(!empty($rule['sched']) && !empty($config['schedules'])) { + if(!empty($rule['sched']) && !empty($config['schedules'])) { $aline['schedlabel'] = ""; - foreach ($config['schedules']['schedule'] as $sched) { - if($sched['name'] == $rule['sched']) { - if(!filter_get_time_based_rule_status($sched)) { + foreach ($config['schedules']['schedule'] as $sched) { + if($sched['name'] == $rule['sched']) { + if(!filter_get_time_based_rule_status($sched)) { if(!isset($config['system']['schedule_states'])) - mwexec("/sbin/pfctl -y {$sched['schedlabel']}"); - return "# schedule finished - {$rule['descr']}"; - } else if($g['debug']) - log_error("[TDR DEBUG] status true -- rule type '$type'"); + mwexec("/sbin/pfctl -y {$sched['schedlabel']}"); + return "# schedule finished - {$rule['descr']}"; + } else if($g['debug']) + log_error("[TDR DEBUG] status true -- rule type '$type'"); $aline['schedlabel'] = " schedule \"{$sched['schedlabel']}\" "; - break; - } - } - } + break; + } + } + } $line = ""; /* exception(s) to a user rules can go here. */ @@ -1674,14 +1674,14 @@ function filter_generate_user_rule($rule) { $aline['reply'] . $aline['route'] . $aline['prot'] . $aline['src'] . $aline['os'] . $aline['dst'] . $aline['divert'] . $aline['icmp-type'] . $aline['tag'] . $aline['tagged'] . $aline['dscp'] . $aline['allowopts'] . $aline['flags'] . $aline['queue'] . $aline['dnpipe'] . $aline['schedlabel']; - + return $line; } function filter_rules_generate() { global $config, $g, $FilterIflist, $time_based_rules; - + update_filter_reload_status("Creating default rules"); if(isset($config['system']['developerspew'])) { $mt = microtime(); @@ -1698,25 +1698,25 @@ function filter_rules_generate() { */ if(isset($config['captiveportal']['enable'])) { $cpinterfaces = explode(",", $config['captiveportal']['interface']); - $cpiflist = array(); + $cpiflist = array(); $cpiplist = array(); - foreach ($cpinterfaces as $cpifgrp) { - if(!isset($FilterIflist[$cpifgrp])) - continue; - $tmpif = get_real_interface($cpifgrp); - if(!empty($tmpif)) { - $cpiflist[] = "{$tmpif}"; - $cpipm = get_interface_ip($cpifgrp); - if(is_ipaddr($cpipm)) - $cpiplist[] = $cpipm; - } - } - if (count($cpiplist) > 0 && count($cpiflist) > 0) { - $cpinterface = implode(" ", $cpiflist); - $cpaddresses = implode(" ", $cpiplist); - $ipfrules .= "pass in quick on { {$cpinterface} } proto tcp from any to { {$cpaddresses} } port { 8000 8001 } keep state(sloppy)\n"; - $ipfrules .= "pass out quick on { {$cpinterface} } proto tcp from { {$cpaddresses} } port { 8000 8001 } to any keep state(sloppy)\n"; - } + foreach ($cpinterfaces as $cpifgrp) { + if(!isset($FilterIflist[$cpifgrp])) + continue; + $tmpif = get_real_interface($cpifgrp); + if(!empty($tmpif)) { + $cpiflist[] = "{$tmpif}"; + $cpipm = get_interface_ip($cpifgrp); + if(is_ipaddr($cpipm)) + $cpiplist[] = $cpipm; + } + } + if (count($cpiplist) > 0 && count($cpiflist) > 0) { + $cpinterface = implode(" ", $cpiflist); + $cpaddresses = implode(" ", $cpiplist); + $ipfrules .= "pass in quick on { {$cpinterface} } proto tcp from any to { {$cpaddresses} } port { 8000 8001 } keep state(sloppy)\n"; + $ipfrules .= "pass out quick on { {$cpinterface} } proto tcp from { {$cpaddresses} } port { 8000 8001 } to any keep state(sloppy)\n"; + } } /* relayd */ $ipfrules .= "anchor \"relayd/*\"\n"; @@ -1741,14 +1741,14 @@ block quick proto { tcp, udp } from any to any port = 0 EOD; - if(!isset($config['system']['ipv6allow'])) { - $ipfrules .= "# Block all IPv6\n"; - $ipfrules .= "block in quick inet6 all\n"; - $ipfrules .= "block out quick inet6 all\n"; - } + if(!isset($config['system']['ipv6allow'])) { + $ipfrules .= "# Block all IPv6\n"; + $ipfrules .= "block in quick inet6 all\n"; + $ipfrules .= "block out quick inet6 all\n"; + } + + $ipfrules .= << to any label "Block snort2c hosts" block quick from any to label "Block snort2c hosts" @@ -1767,15 +1767,15 @@ EOD; $ipfrules .= filter_process_carp_rules(); - $ipfrules .= "\n# SSH lockout\n"; - if(is_array($config['system']['ssh']) && !empty($config['system']['ssh']['port'])) { - $ipfrules .= "block in log quick proto tcp from to any port "; - $ipfrules .= $config['system']['ssh']['port']; - $ipfrules .= " label \"sshlockout\"\n"; - } else { + $ipfrules .= "\n# SSH lockout\n"; + if(is_array($config['system']['ssh']) && !empty($config['system']['ssh']['port'])) { + $ipfrules .= "block in log quick proto tcp from to any port "; + $ipfrules .= $config['system']['ssh']['port']; + $ipfrules .= " label \"sshlockout\"\n"; + } else { if($config['system']['ssh']['port'] <> "") $sshport = $config['system']['ssh']['port']; - else + else $sshport = 22; $ipfrules .= "block in log quick proto tcp from to any port {$sshport} label \"sshlockout\"\n"; } @@ -1818,7 +1818,7 @@ EOD; if(isset($config['interfaces'][$on]['blockpriv'])) { if($isbridged == false) { $ipfrules .= << 1 && !empty($FilterIflist['lan']['if'])) { /* if antilockout is enabled, LAN exists and has - * an IP and subnet mask assigned + * an IP and subnet mask assigned */ $lanif = $FilterIflist["lan"]['if']; $ipfrules .= << 0) { - unset($config['cron']['item'][$x]); - write_config(); - } - configure_cron(); - } - break; - } + $x=0; + foreach($config['cron']['item'] as $item) { + if(strstr($item['command'], "filter_configure_sync")) { + $is_installed = true; + break; + } + $x++; + } + + switch($should_install) { + case true: + if(!$is_installed) { + $cron_item = array(); + $cron_item['minute'] = "0,15,30,45"; + $cron_item['hour'] = "*"; + $cron_item['mday'] = "*"; + $cron_item['month'] = "*"; + $cron_item['wday'] = "*"; + $cron_item['who'] = "root"; + $cron_item['command'] = "/etc/rc.filter_configure_sync"; + $config['cron']['item'][] = $cron_item; + write_config("Installed 15 minute filter reload for Time Based Rules"); + configure_cron(); + } + break; + case false: + if($is_installed == true) { + if($x > 0) { + unset($config['cron']['item'][$x]); + write_config(); + } + configure_cron(); + } + break; + } } /****f* filter/filter_get_time_based_rule_status @@ -2141,132 +2142,132 @@ function filter_tdr_install_cron($should_install) { */ function filter_get_time_based_rule_status($schedule) { - $should_add_rule = false; - /* no schedule? rule should be installed */ - if(empty($schedule)) - return true; - /* - * iterate through time blocks and determine - * if the rule should be installed or not. - */ - foreach($schedule['timerange'] as $timeday) { - if($timeday['month']) - $month = $timeday['month']; - else - $week = ""; - if($timeday['day']) - $day = $timeday['day']; - else - $day = ""; - if($timeday['hour']) - $hour = $timeday['hour']; - else - $hour = ""; - if($timeday['position']) - $position = $timeday['position']; - else - $position = ""; - if($timeday['desc']) - $desc = $timeday['desc']; - else - $desc = ""; - if($month) { - $monthstatus = filter_tdr_month($month); - } else { - $monthstatus = true; - } - if($day) { - $daystatus = filter_tdr_day($day); - } else { - $daystatus = true; - } - if($hour) { - $hourstatus = filter_tdr_hour($hour); - } else { - $hourstatus = true; - } - if($position) { - $positionstatus = filter_tdr_position($position); - } else { - $positionstatus = true; - } - - if($monthstatus == true && $daystatus == true && $positionstatus == true && $hourstatus == true) + $should_add_rule = false; + /* no schedule? rule should be installed */ + if(empty($schedule)) + return true; + /* + * iterate through time blocks and determine + * if the rule should be installed or not. + */ + foreach($schedule['timerange'] as $timeday) { + if($timeday['month']) + $month = $timeday['month']; + else + $week = ""; + if($timeday['day']) + $day = $timeday['day']; + else + $day = ""; + if($timeday['hour']) + $hour = $timeday['hour']; + else + $hour = ""; + if($timeday['position']) + $position = $timeday['position']; + else + $position = ""; + if($timeday['desc']) + $desc = $timeday['desc']; + else + $desc = ""; + if($month) { + $monthstatus = filter_tdr_month($month); + } else { + $monthstatus = true; + } + if($day) { + $daystatus = filter_tdr_day($day); + } else { + $daystatus = true; + } + if($hour) { + $hourstatus = filter_tdr_hour($hour); + } else { + $hourstatus = true; + } + if($position) { + $positionstatus = filter_tdr_position($position); + } else { + $positionstatus = true; + } + + if($monthstatus == true && $daystatus == true && $positionstatus == true && $hourstatus == true) $should_add_rule = true; - } + } - return $should_add_rule; + return $should_add_rule; } function filter_tdr_day($schedule) { global $g; - /* - * Calculate day of month. - * IE: 29th of may - */ - $weekday = date("w"); - if($weekday == 0) - $weekday = 7; - $date = date("d"); - $defined_days = split(",", $schedule); + /* + * Calculate day of month. + * IE: 29th of may + */ + $weekday = date("w"); + if($weekday == 0) + $weekday = 7; + $date = date("d"); + $defined_days = split(",", $schedule); if($g['debug']) - log_error("[TDR DEBUG] filter_tdr_day($schedule)"); - foreach($defined_days as $dd) { - if($date == $dd) - return true; - } - return false; + log_error("[TDR DEBUG] filter_tdr_day($schedule)"); + foreach($defined_days as $dd) { + if($date == $dd) + return true; + } + return false; } function filter_tdr_hour($schedule) { global $g; - /* $schedule should be a string such as 16:00-19:00 */ - $tmp = split("-", $schedule); - $starting_time = strtotime($tmp[0]); - $ending_time = strtotime($tmp[1]); - $now = strtotime("now"); + /* $schedule should be a string such as 16:00-19:00 */ + $tmp = split("-", $schedule); + $starting_time = strtotime($tmp[0]); + $ending_time = strtotime($tmp[1]); + $now = strtotime("now"); if($g['debug']) - log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now"); - if($now >= $starting_time and $now <= $ending_time) - return true; - return false; + log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now"); + if($now >= $starting_time and $now <= $ending_time) + return true; + return false; } function filter_tdr_position($schedule) { global $g; - /* - * Calculate possition, ie: day of week. - * Sunday = 7, Monday = 1, Tuesday = 2 - * Weds = 3, Thursday = 4, Friday = 5, - * Saturday = 6 - * ... - */ - $weekday = date("w"); + /* + * Calculate possition, ie: day of week. + * Sunday = 7, Monday = 1, Tuesday = 2 + * Weds = 3, Thursday = 4, Friday = 5, + * Saturday = 6 + * ... + */ + $weekday = date("w"); if($g['debug']) - log_error("[TDR DEBUG] filter_tdr_position($schedule) $weekday"); - if($weekday == 0) - $weekday = 7; - $schedule_days = split(",", $schedule); - foreach($schedule_days as $day) { - if($day == $weekday) - return true; - } - return false; + log_error("[TDR DEBUG] filter_tdr_position($schedule) $weekday"); + if($weekday == 0) + $weekday = 7; + $schedule_days = split(",", $schedule); + foreach($schedule_days as $day) { + if($day == $weekday) + return true; + } + return false; } function filter_tdr_month($schedule) { global $g; - /* - * Calculate month - */ - $todays_month = date("n"); - $months = split(",", $schedule); + /* + * Calculate month + */ + $todays_month = date("n"); + $months = split(",", $schedule); if($g['debug']) - log_error("[TDR DEBUG] filter_tdr_month($schedule)"); - foreach($months as $month) { - if($month == $todays_month) - return true; - } - return false; + log_error("[TDR DEBUG] filter_tdr_month($schedule)"); + foreach($months as $month) { + if($month == $todays_month) + return true; + } + return false; } function filter_setup_logging_interfaces() { @@ -2277,13 +2278,13 @@ function filter_setup_logging_interfaces() { } $rules = ""; foreach ($FilterIflist as $ifdescr => $ifcfg) { - /* + /* * XXX: This should be cleared out after a discussion - * between pf(4) devs is cleared out. This breaks + * between pf(4) devs is cleared out. This breaks * compatibility with OpenBSD. - */ + */ if(isset($ifcfg['virtual'])) - continue; + continue; $rules .= "set loginterface {$ifcfg['if']}\n"; } return $rules; @@ -2297,7 +2298,7 @@ function filter_process_carp_nat_rules() { echo "filter_process_carp_nat_rules() being called $mt\n"; } $lines = ""; - if(isset($config['installedpackages']['carp']['config']) && + if(isset($config['installedpackages']['carp']['config']) && is_array($config['installedpackages']['carp']['config'])) { foreach($config['installedpackages']['carp']['config'] as $carp) { $ip = $carp['ipaddress']; @@ -2350,8 +2351,8 @@ function filter_generate_ipsec_rules() { else exec("/sbin/sysctl net.inet.ipcomp.ipcomp_enable=0"); - if(isset($config['ipsec']['enable']) && - is_array($config['ipsec']['phase1'])) { + if(isset($config['ipsec']['enable']) && + is_array($config['ipsec']['phase1'])) { /* step through all phase1 entries */ foreach ($config['ipsec']['phase1'] as $ph1ent) { if(isset ($ph1ent['disabled'])) @@ -2403,7 +2404,7 @@ function filter_generate_ipsec_rules() { if(!is_ipaddr($gateway) || empty($interface)) { $route_to = " "; $reply_to = " "; - } else { + } else { $route_to = " route-to ( $interface $gateway ) "; $reply_to = " reply-to ( $interface $gateway ) "; } @@ -2446,11 +2447,11 @@ EOD; function discover_pkg_rules($ruletype) { global $config, $g; - if(!is_dir("/usr/local/pkg")) + if(!is_dir("/usr/local/pkg")) return ""; $files = split("\n", trim(`ls /usr/local/pkg/*.inc`)); foreach($files as $pkg_inc) { - if($pkg_inc == "ls: No match.") + if($pkg_inc == "ls: No match.") continue; update_filter_reload_status("Checking for {$ruletype} PF hooks in package {$pkg_inc}"); require_once($pkg_inc); @@ -2472,4 +2473,5 @@ function discover_pkg_rules($ruletype) { return $rules; } +// vim: ts=4 sw=4 noexpandtab ?> diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc index 76548d0..86d50f9 100644 --- a/etc/inc/globals.inc +++ b/etc/inc/globals.inc @@ -88,7 +88,7 @@ $g = array( "disablehelpmenu" => false, "disablehelpicon" => false, "debug" => false, - "latest_config" => "6.1", + "latest_config" => "6.2", "nopkg_platforms" => array("cdrom"), "minimum_ram_warning" => "105", "minimum_ram_warning_text" => "128 MB", diff --git a/etc/inc/pfsense-utils.inc b/etc/inc/pfsense-utils.inc index 193718a..0995a92 100644 --- a/etc/inc/pfsense-utils.inc +++ b/etc/inc/pfsense-utils.inc @@ -289,9 +289,11 @@ function is_alias_inuse($alias) { /* loop through nat rules looking for alias in use */ if(is_array($config['nat']['rule'])) foreach($config['nat']['rule'] as $rule) { - if($rule['target'] == $alias) + if($rule['target'] && $rule['target'] == $alias) return true; - if($rule['external-address'] == $alias) + if($rule['source']['address'] && $rule['source']['address'] == $alias) + return true; + if($rule['destination']['address'] && $rule['destination']['address'] == $alias) return true; } return false; diff --git a/etc/inc/upgrade_config.inc b/etc/inc/upgrade_config.inc index 6282fa5..f5a5493 100644 --- a/etc/inc/upgrade_config.inc +++ b/etc/inc/upgrade_config.inc @@ -1863,4 +1863,35 @@ function upgrade_060_to_061() { $config['interfaces']['lan']['enable'] = true; } +function upgrade_061_to_062() { + global $config; + + /* Convert NAT port forwarding rules */ + if (is_array($config['nat']['rule'])) { + $a_nat = &$config['nat']['rule']; + + foreach ($a_nat as &$natent) { + $natent['disabled'] = false; + $natent['nordr'] = false; + + $natent['source'] = array( + "not" => false, + "any" => true, + "port" => "" + ); + + $natent['destination'] = array( + "not" => false, + "address" => $natent['external-address'], + "port" => $natent['external-port'] + ); + + unset($natent['external-address']); + unset($natent['external-port']); + } + + unset($natent); + } +} + ?> -- cgit v1.1