* Copyright (C) 2003-2004 Manuel Kasper * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ require_once("guiconfig.inc"); require_once("filter.inc"); $a_nat = &config_read_array('nat', 'rule'); if ($_SERVER['REQUEST_METHOD'] === 'GET') { // load form data from config if (isset($_GET['id']) && is_numericint($_GET['id']) && isset($a_nat[$_GET['id']])) { $id = $_GET['id']; $configId = $id; // load form data from id } elseif (isset($_GET['dup']) && isset($a_nat[$_GET['dup']])){ $after = $_GET['dup']; $configId = $_GET['dup']; // load form data from id } if (isset($_GET['after']) && isset($a_nat[$_GET['after']])) { $after = $_GET['after']; } // initialize form and set defaults $pconfig = array(); $pconfig['protocol'] = "tcp"; $pconfig['srcbeginport'] = "any"; $pconfig['srcendport'] = "any"; $pconfig['interface'] = ["wan"]; $pconfig['dstbeginport'] = 80 ; $pconfig['dstendport'] = 80 ; $pconfig['local-port'] = 80; if (isset($configId)) { // copy 1-on-1 foreach (array('protocol','target','local-port','descr','interface','associated-rule-id','nosync','log', 'natreflection','created','updated','ipprotocol','tag','tagged','poolopts') as $fieldname) { if (isset($a_nat[$configId][$fieldname])) { $pconfig[$fieldname] = $a_nat[$configId][$fieldname]; } else { $pconfig[$fieldname] = null; } } // fields with some kind of logic. $pconfig['disabled'] = isset($a_nat[$configId]['disabled']); $pconfig['nordr'] = isset($a_nat[$configId]['nordr']); $pconfig['interface'] = explode(",", $pconfig['interface']); address_to_pconfig($a_nat[$configId]['source'], $pconfig['src'], $pconfig['srcmask'], $pconfig['srcnot'], $pconfig['srcbeginport'], $pconfig['srcendport']); address_to_pconfig($a_nat[$configId]['destination'], $pconfig['dst'], $pconfig['dstmask'], $pconfig['dstnot'], $pconfig['dstbeginport'], $pconfig['dstendport']); if (empty($pconfig['ipprotocol'])) { if (strpos($pconfig['src'].$pconfig['dst'].$pconfig['target'], ":") !== false) { $pconfig['ipprotocol'] = 'inet6'; } else { $pconfig['ipprotocol'] = 'inet'; } } } elseif (isset($_GET['template']) && $_GET['template'] == 'transparent_proxy') { // new rule for transparent proxy reflection, to use as sample $pconfig['interface'] = ["lan"]; $pconfig['src'] = "lan"; $pconfig['dst'] = "any"; $pconfig['ipprotocol'] = "inet"; if (isset($_GET['https'])){ $pconfig['dstbeginport'] = 443; $pconfig['dstendport'] = 443; if (isset($config['OPNsense']['proxy']['forward']['sslbumpport'])) { $pconfig['local-port'] = $config['OPNsense']['proxy']['forward']['sslbumpport']; } else { $pconfig['local-port'] = 3129; } } else { $pconfig['dstbeginport'] = 80; $pconfig['dstendport'] = 80; // try to read the proxy configuration to determine the current port // this has some disadvantages in case of dependencies, but there isn't // a much better solution available at the moment. if (isset($config['OPNsense']['proxy']['forward']['port'])) { $pconfig['local-port'] = $config['OPNsense']['proxy']['forward']['port']; } else { $pconfig['local-port'] = 3128; } } $pconfig['target'] = '127.0.0.1'; $pconfig['natreflection'] = 'enable'; $pconfig['descr'] = gettext("redirect traffic to proxy"); } else { $pconfig['src'] = "any"; } // init empty fields foreach (array('dst','dstmask','srcmask','dstbeginport','dstendport','target', 'local-port','natreflection','descr','disabled','nosync','ipprotocol', 'tag','tagged','poolopts') as $fieldname) { if (!isset($pconfig[$fieldname])) { $pconfig[$fieldname] = null; } } } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { $pconfig = $_POST; $input_errors = array(); // validate id and store if usable if (isset($pconfig['id']) && is_numericint($pconfig['id']) && isset($a_nat[$pconfig['id']])) { $id = $_POST['id']; } if (isset($pconfig['after']) && isset($a_nat[$pconfig['after']])) { // place record after provided sequence number $after = $pconfig['after']; } /* Validate input data */ if ($pconfig['protocol'] == 'tcp' || $pconfig['protocol'] == 'udp' || $pconfig['protocol'] == 'tcp/udp') { $reqdfields = explode(" ", "interface protocol dstbeginport dstendport"); $reqdfieldsn = array(gettext("Interface"),gettext("Protocol"),gettext("Destination port from"),gettext("Destination port to")); } else { $reqdfields = explode(" ", "interface protocol"); $reqdfieldsn = array(gettext("Interface"),gettext("Protocol")); } $reqdfields[] = "src"; $reqdfieldsn[] = gettext("Source address"); $reqdfields[] = "dst"; $reqdfieldsn[] = gettext("Destination address"); if (empty($pconfig['nordr'])) { $reqdfields[] = "target"; $reqdfieldsn[] = gettext("Redirect target IP"); } do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); if (!isset($pconfig['nordr']) && ($pconfig['target'] && !is_ipaddroralias($pconfig['target']) && !is_subnet($pconfig['target']))) { $input_errors[] = sprintf(gettext("\"%s\" is not a valid redirect target IP address, network or host alias."), $pconfig['target']); } if (!empty($pconfig['srcbeginport']) && $pconfig['srcbeginport'] != 'any' && !is_portoralias($pconfig['srcbeginport'])) $input_errors[] = sprintf(gettext("%s is not a valid start source port. It must be a port alias or integer between 1 and 65535."), $pconfig['srcbeginport']); if (!empty($pconfig['srcendport']) && $pconfig['srcendport'] != 'any' && !is_portoralias($pconfig['srcendport'])) $input_errors[] = sprintf(gettext("%s is not a valid end source port. It must be a port alias or integer between 1 and 65535."), $pconfig['srcendport']); if (!empty($pconfig['dstbeginport']) && $pconfig['dstbeginport'] != 'any' && !is_portoralias($pconfig['dstbeginport'])) $input_errors[] = sprintf(gettext("%s is not a valid start destination port. It must be a port alias or integer between 1 and 65535."), $pconfig['dstbeginport']); if (!empty($pconfig['dstendport']) && $pconfig['dstendport'] != 'any' && !is_portoralias($pconfig['dstendport'])) $input_errors[] = sprintf(gettext("%s is not a valid end destination port. It must be a port alias or integer between 1 and 65535."), $pconfig['dstendport']); if (($pconfig['protocol'] == "tcp" || $pconfig['protocol'] == "udp" || $_POST['protocol'] == "tcp/udp") && (!isset($pconfig['nordr']) && !is_portoralias($pconfig['local-port']))) { $input_errors[] = sprintf(gettext("A valid redirect target port must be specified. It must be a port alias or integer between 1 and 65535."), $pconfig['local-port']); } if (!is_specialnet($pconfig['src']) && !is_ipaddroralias($pconfig['src'])) { $input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."), $pconfig['src']); } // validate ipv4/v6, addresses should use selected address family foreach (array('src', 'dst', 'target') as $fieldname) { if (is_ipaddrv6($pconfig[$fieldname]) && $pconfig['ipprotocol'] != 'inet6') { $input_errors[] = sprintf(gettext("%s is not a valid IPv4 address."), $pconfig[$fieldname]); } if (is_ipaddrv4($pconfig[$fieldname]) && $pconfig['ipprotocol'] != 'inet') { $input_errors[] = sprintf(gettext("%s is not a valid IPv6 address."), $pconfig[$fieldname]); } } if (!empty($pconfig['srcmask']) && !is_numericint($pconfig['srcmask'])) { $input_errors[] = gettext("A valid source bit count must be specified."); } if (!is_specialnet($pconfig['dst']) && !is_ipaddroralias($pconfig['dst'])) { $input_errors[] = sprintf(gettext("%s is not a valid destination IP address or alias."), $pconfig['dst']); } if (!empty($pconfig['dstmask']) && !is_numericint($pconfig['dstmask'])) { $input_errors[] = gettext("A valid destination bit count must be specified."); } if (!isset($_POST['nordr']) && is_numericint($pconfig['dstbeginport']) && is_numericint($pconfig['dstendport']) && is_numericint($pconfig['local-port']) && (max($pconfig['dstendport'],$pconfig['dstbeginport']) - min($pconfig['dstendport'],$pconfig['dstbeginport']) + $pconfig['local-port']) > 65535) { $input_errors[] = gettext("The target port range must be an integer between 1 and 65535."); } if (count($input_errors) == 0) { $natent = array(); if ($pconfig['protocol'] != 'any') { $natent['protocol'] = $pconfig['protocol']; } $natent['interface'] = implode(",", $pconfig['interface']); $natent['ipprotocol'] = $pconfig['ipprotocol']; $natent['descr'] = $pconfig['descr']; $natent['tag'] = $pconfig['tag']; $natent['tagged'] = $pconfig['tagged']; $natent['poolopts'] = $pconfig['poolopts']; if (!empty($natent['nordr'])) { $natent['associated-rule-id'] = ''; } elseif (!empty($pconfig['filter-rule-association']) && $pconfig['filter-rule-association'] == "pass") { $natent['associated-rule-id'] = "pass"; } elseif (!empty($pconfig['associated-rule-id'])) { $natent['associated-rule-id'] = $pconfig['associated-rule-id']; } else { $natent['associated-rule-id'] = null; } $natent['disabled'] = !empty($pconfig['disabled']); $natent['nordr'] = !empty($pconfig['nordr']); $natent['nosync'] = !empty($pconfig['nosync']); $natent['log'] = !empty($pconfig['log']); if (empty($natent['nordr'])) { $natent['target'] = $pconfig['target']; $natent['local-port'] = $pconfig['local-port']; } pconfig_to_address($natent['source'], $pconfig['src'], $pconfig['srcmask'], !empty($pconfig['srcnot']), $pconfig['srcbeginport'], $pconfig['srcendport']); pconfig_to_address($natent['destination'], $pconfig['dst'], $pconfig['dstmask'], !empty($pconfig['dstnot']), $pconfig['dstbeginport'], $pconfig['dstendport']); if ($pconfig['natreflection'] == "purenat" || $pconfig['natreflection'] == "disable") { $natent['natreflection'] = $pconfig['natreflection']; } // If we used to have an associated filter rule, but no-longer should have one if (isset($id) && !empty($a_nat[$id]['associated-rule-id']) && ( empty($natent['associated-rule-id']) || $natent['associated-rule-id'] != $a_nat[$id]['associated-rule-id'] ) ) { // Delete the previous rule foreach ($config['filter']['rule'] as $key => $item){ if (isset($item['associated-rule-id']) && $item['associated-rule-id']==$a_nat[$id]['associated-rule-id'] ){ unset($config['filter']['rule'][$key]); break; } } mark_subsystem_dirty('filter'); } // Updating a rule with a filter rule associated if (!empty($natent['associated-rule-id']) || !empty($pconfig['filter-rule-association'])) { /* auto-generate a matching firewall rule */ $filterent = array(); // If a rule already exists, load it if (!empty($natent['associated-rule-id'])) { // search rule by associated-rule-id $filterentid = false; foreach ($config['filter']['rule'] as $key => $item){ if (isset($item['associated-rule-id']) && $item['associated-rule-id']==$natent['associated-rule-id']) { $filterentid = $key; break; } } if ($filterentid === false) { $filterent['associated-rule-id'] = $natent['associated-rule-id']; } else { $filterent = &config_read_array('filter', 'rule', $filterentid); } } pconfig_to_address($filterent['source'], $pconfig['src'], $pconfig['srcmask'], !empty($pconfig['srcnot']), $pconfig['srcbeginport'], $pconfig['srcendport']); // Update interface, protocol and destination $filterent['interface'] = $natent['interface']; if (!empty($natent['protocol'])) { $filterent['protocol'] = $natent['protocol']; } elseif (isset($filterent['protocol'])) { unset($filterent['protocol']); } $filterent['ipprotocol'] = $natent['ipprotocol']; if (!isset($filterent['destination'])) { $filterent['destination'] = array(); } $filterent['destination']['address'] = $pconfig['target']; if (count($pconfig['interface']) > 1) { $filterent['floating'] = true; $filterent['quick'] = "yes"; } else { unset($filterent['floating']); unset($filterent['quick']); } if (!empty($pconfig['log'])) { $filterent['log'] = true; } elseif (isset($filterent['log'])) { unset($filterent['log']); } if (is_numericint($pconfig['local-port']) && is_numericint($pconfig['dstendport']) && is_numericint($pconfig['dstbeginport'])) { $dstpfrom = $pconfig['local-port']; $dstpto = $dstpfrom + max($pconfig['dstendport'], $pconfig['dstbeginport']) - min($pconfig['dstbeginport'],$pconfig['dstendport']) ; if ($dstpfrom == $dstpto) { $filterent['destination']['port'] = $dstpfrom; } else { $filterent['destination']['port'] = $dstpfrom . "-" . $dstpto; } } else { // if any of the ports is an alias, copy contents of local-port $filterent['destination']['port'] = $pconfig['local-port']; } $filterent['descr'] = $pconfig['descr']; // If this is a new rule, create an ID and add the rule if (!empty($pconfig['filter-rule-association']) && $pconfig['filter-rule-association'] != 'pass') { if ($pconfig['filter-rule-association'] == 'add-associated') { $filterent['associated-rule-id'] = $natent['associated-rule-id'] = uniqid("nat_", true); } $filterent['created'] = make_config_revision_entry(); $config['filter']['rule'][] = $filterent; } mark_subsystem_dirty('filter'); } // Update the NAT entry now $natent['updated'] = make_config_revision_entry(); if (isset($id)) { if (isset($a_nat[$id]['created'])) { $natent['created'] = $a_nat[$id]['created']; } $a_nat[$id] = $natent; } else { $natent['created'] = make_config_revision_entry(); if (isset($after)) { array_splice($a_nat, $after+1, 0, array($natent)); } else { $a_nat[] = $natent; } } write_config(); mark_subsystem_dirty('natconf'); header(url_safe('Location: /firewall_nat.php')); exit; } } legacy_html_escape_form_data($pconfig); include("head.inc"); ?>
0) print_input_errors($input_errors); ?>
/>
/>
/>
" aria-label=""/>
"/>
/>
/>
 
()
()