+ {{ lang._('Entries in this section override individual results from the forwarders.') }}
+ {{ lang._('Use these for changing DNS results or for adding custom DNS records.') }}
+ {{ lang._('Keep in mind that all resource record types (i.e. A, AAAA, MX, etc. records) of a specified host below are being overwritten.') }}
+
+
+
+
+
+
+
+
{{ lang._('ID') }}
+
{{ lang._('Enabled') }}
+
{{ lang._('Domain') }}
+
{{ lang._('IP') }}
+
{{ lang._('Description') }}
+
{{ lang._('Edit') }} | {{ lang._('Delete') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ lang._('Entries in this area override an entire domain by specifying an authoritative DNS server to be queried for that domain.') }}
+
+
+
+
+
+
+
+
+
{{ lang._('ID') }}
+
{{ lang._('Enabled') }}
+
{{ lang._('Host') }}
+
{{ lang._('Domain') }}
+
{{ lang._('Commands') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ lang._('After changing settings, please remember to apply them with the button below') }}
+
+
+
+
+
+
+
+
+
+
+
+
+{{ partial("layout_partials/base_dialog",['fields':formDialogHostOverride,'id':'DialogHostOverride','label':lang._('Edit Host Override')])}}
+{{ partial("layout_partials/base_dialog",['fields':formDialogHostAlias,'id':'DialogHostAlias','label':lang._('Edit Host Override Alias')])}}
+{{ partial("layout_partials/base_dialog",['fields':formDialogDomainOverride,'id':'DialogDomainOverride','label':lang._('Edit Domain Override')])}}
diff --git a/src/opnsense/service/modules/addons/template_helpers.py b/src/opnsense/service/modules/addons/template_helpers.py
index c886563da..ec60075dd 100644
--- a/src/opnsense/service/modules/addons/template_helpers.py
+++ b/src/opnsense/service/modules/addons/template_helpers.py
@@ -33,7 +33,6 @@ import glob
import collections
import netaddr
-
class SortKeyHelper:
""" generate item key for sort function
"""
diff --git a/src/opnsense/service/modules/template.py b/src/opnsense/service/modules/template.py
index 00716a008..242872297 100644
--- a/src/opnsense/service/modules/template.py
+++ b/src/opnsense/service/modules/template.py
@@ -69,6 +69,9 @@ class Template(object):
self._j2_env.filters['shlex_split'] = shlex.split
self._j2_env.filters['regex_replace'] = lambda value, pattern, replacement: re.sub(pattern, replacement, value)
+ # register additional tests
+ self._j2_env.tests['regex_match'] = lambda value, pattern: bool(re.match(pattern, value))
+
@staticmethod
def _encode_idna(x):
""" encode string to idna, preserve leading dots
diff --git a/src/opnsense/service/templates/OPNsense/Unbound/core/+TARGETS b/src/opnsense/service/templates/OPNsense/Unbound/core/+TARGETS
index a6eff6f6f..d0234382e 100644
--- a/src/opnsense/service/templates/OPNsense/Unbound/core/+TARGETS
+++ b/src/opnsense/service/templates/OPNsense/Unbound/core/+TARGETS
@@ -1,5 +1,7 @@
blocklists.conf:/tmp/unbound-blocklists.conf
dot.conf:/usr/local/etc/unbound.opnsense.d/dot.conf
+private_domains.conf:/var/unbound/private_domains.conf
+domainoverrides.conf:/usr/local/etc/unbound.opnsense.d/domainoverrides.conf
miscellaneous.conf:/usr/local/etc/unbound.opnsense.d/miscellaneous.conf
root.min.hints:/var/unbound/root.hints
unbound_dhcpd.conf:/usr/local/etc/unbound_dhcpd.conf
diff --git a/src/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf b/src/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf
new file mode 100755
index 000000000..107c7976e
--- /dev/null
+++ b/src/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf
@@ -0,0 +1,17 @@
+{% if not helpers.empty('OPNsense.unboundplus.domains.domain') %}
+{% set forwardlocal = namespace(found=false) %}
+{% for domain in helpers.toList('OPNsense.unboundplus.domains.domain') %}
+{% if domain.enabled == '1' %}
+forward-zone:
+ name: "{{ domain.domain }}"
+{% if domain.server.startswith('127.') or domain.server == '::1' %}
+{% set forwardlocal.found = true %}
+{% endif%}
+ forward-addr: {{ domain.server }}
+{% endif %}
+{% endfor %}
+{% if forwardlocal.found %}
+server:
+ do-not-query-localhost: no
+{% endif %}
+{% endif%}
\ No newline at end of file
diff --git a/src/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf b/src/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf
new file mode 100755
index 000000000..4bd85236a
--- /dev/null
+++ b/src/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf
@@ -0,0 +1,13 @@
+{% if not helpers.empty('OPNsense.unboundplus.domains.domain') %}
+# Set private domains in case authoritative name server returns a Private IP address
+{% for domain in helpers.toList('OPNsense.unboundplus.domains.domain') %}
+{% if domain.enabled == '1' %}
+domain-insecure: "{{ domain.domain }}"
+{% if domain.domain is regex_match('.+\.(in-addr|ip6)\.arpa\.?$') %}
+local-zone: {{ domain.domain }} typetransparent
+{% elif not helpers.exists('system.webgui.nodnsrebindcheck') %}
+private-domain: "{{ domain.domain }}"
+{% endif%}
+{% endif %}
+{% endfor %}
+{% endif %}
diff --git a/src/www/services_unbound_domainoverride_edit.php b/src/www/services_unbound_domainoverride_edit.php
deleted file mode 100644
index 98b58b38a..000000000
--- a/src/www/services_unbound_domainoverride_edit.php
+++ /dev/null
@@ -1,166 +0,0 @@
-
- * Copyright (C) 2003-2005 Bob Zoller
- * Copyright (C) 2003-2005 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("interfaces.inc");
-
-$a_domainOverrides = &config_read_array('unbound', 'domainoverrides');
-
-if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- if (isset($_GET['id']) && !empty($a_domainOverrides[$_GET['id']])) {
- $id = $_GET['id'];
- }
- $pconfig = array();
- $pconfig['domain'] = isset($id) && !empty($a_domainOverrides[$id]['domain']) ? $a_domainOverrides[$id]['domain'] : null;
- $pconfig['ip'] = isset($id) && !empty($a_domainOverrides[$id]['ip']) ? $a_domainOverrides[$id]['ip'] : null;
- $pconfig['descr'] = isset($id) && !empty($a_domainOverrides[$id]['descr']) ? $a_domainOverrides[$id]['descr'] : null;
-} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
- if (isset($_GET['id']) && !empty($a_domainOverrides[$_POST['id']])) {
- $id = $_POST['id'];
- }
- $input_errors= array();
- $pconfig = $_POST;
-
- /* input validation */
- $reqdfields = explode(" ", "domain ip");
- $reqdfieldsn = array(gettext("Domain"),gettext("IP address"));
-
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
- if (!empty($pconfig['domain']) && substr($pconfig['domain'], 0, 6) == '_msdcs') {
- $subdomainstr = substr($pconfig['domain'], 7);
- if ($subdomainstr && !is_domain($subdomainstr)) {
- $input_errors[] = gettext("A valid domain must be specified after _msdcs.");
- }
- } elseif (!empty($pconfig['domain']) && !is_domain($_POST['domain'])) {
- $input_errors[] = gettext("A valid domain must be specified.");
- }
-
- if (!empty($pconfig['ip'])) {
- if (strpos($pconfig['ip'],'@') !== false) {
- $ip_details = explode("@", $pconfig['ip']);
- if (!is_ipaddr($ip_details[0]) && !is_port($ip_details[1])) {
- $input_errors[] = gettext("A valid IP address and port must be specified, for example 192.168.100.10@5353.");
- }
- } elseif (!is_ipaddr($pconfig['ip'])) {
- $input_errors[] = gettext("A valid IP address must be specified, for example 192.168.100.10.");
- }
- }
-
- if (count($input_errors) == 0) {
- $doment = array();
- $doment['domain'] = $pconfig['domain'];
- $doment['ip'] = $pconfig['ip'];
- $doment['descr'] = $pconfig['descr'];
-
- if (isset($id)) {
- $a_domainOverrides[$id] = $doment;
- } else {
- $a_domainOverrides[] = $doment;
- }
-
- mark_subsystem_dirty('unbound');
- write_config();
- header(url_safe('Location: /services_unbound_overrides.php'));
- exit;
- }
-}
-
-$service_hook = 'unbound';
-legacy_html_escape_form_data($pconfig);
-include("head.inc");
-?>
-
-
-
-
-
- 0) print_input_errors($input_errors); ?>
-
-
-
-
-
-
-
-
-
diff --git a/src/www/services_unbound_host_edit.php b/src/www/services_unbound_host_edit.php
deleted file mode 100644
index 9102232d7..000000000
--- a/src/www/services_unbound_host_edit.php
+++ /dev/null
@@ -1,377 +0,0 @@
-
- * Copyright (C) 2014-2016 Deciso B.V.
- * Copyright (C) 2014 Warren Baker
- * Copyright (C) 2003-2004 Bob Zoller
- * 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("interfaces.inc");
-
-$a_hosts = &config_read_array('unbound', 'hosts');
-
-if ($_SERVER['REQUEST_METHOD'] === 'GET') {
- if (isset($_GET['id']) && !empty($a_hosts[$_GET['id']])) {
- $id = $_GET['id'];
- }
- $pconfig = array();
- foreach (array('rr', 'host', 'domain', 'ip', 'mxprio', 'mx', 'descr', 'aliases') as $fieldname) {
- if (isset($id) && !empty($a_hosts[$id][$fieldname])) {
- $pconfig[$fieldname] = $a_hosts[$id][$fieldname];
- } else {
- $pconfig[$fieldname] = null;
- }
- }
-} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
- if (isset($_POST['id']) && !empty($a_hosts[$_POST['id']])) {
- $id = $_POST['id'];
- }
-
- $input_errors = array();
- $pconfig = $_POST;
-
- $pconfig['aliases'] = array();
- if (isset($pconfig['aliases_host'])) {
- $pconfig['aliases']['item'] = array();
- foreach ($pconfig['aliases_host'] as $opt_seq => $opt_host) {
- if (empty($opt_host) && empty($pconfig['aliases_domain'][$opt_seq]) && empty($pconfig['aliases_descr'][$opt_seq])) {
- continue;
- }
- $pconfig['aliases']['item'][] = array(
- 'domain' => $pconfig['aliases_domain'][$opt_seq],
- 'descr' => $pconfig['aliases_descr'][$opt_seq],
- 'host' => $opt_host,
- );
- }
- }
-
- $reqdfields = explode(" ", "domain rr");
- $reqdfieldsn = array(gettext("Domain"),gettext("Type"));
-
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
-
- if (!empty($pconfig['host']) && !is_hostname($pconfig['host']) && $pconfig['host'] != '*') {
- $input_errors[] = gettext("The hostname can only contain the characters A-Z, 0-9 and '-'.");
- }
-
- if (!empty($pconfig['domain']) && !is_domain($pconfig['domain'])) {
- $input_errors[] = gettext("A valid domain must be specified.");
- }
-
- if (!empty($pconfig['domain']) && $pconfig['domain'] == $config['system']['domain'] && $pconfig['host'] == '*') {
- $input_errors[] = sprintf(
- gettext("A wildcard domain override is not supported for the local domain '%s'."),
- $config['system']['domain']
- );
- }
-
- switch ($pconfig['rr']) {
- case 'A': /* also: AAAA */
- $reqdfields = explode(" ", "ip");
- $reqdfieldsn = array(gettext("IP address"));
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
-
- if (!empty($pconfig['ip']) && !is_ipaddr($pconfig['ip'])) {
- $input_errors[] = gettext("A valid IP address must be specified.");
- }
- break;
- case 'MX':
- $reqdfields = explode(" ", "mxprio mx");
- $reqdfieldsn = array(gettext("MX Priority"), gettext("MX Host"));
- do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
-
- if (!empty($pconfig['mxprio']) && !is_numericint($pconfig['mxprio'])) {
- $input_errors[] = gettext("A valid MX priority must be specified.");
- }
-
- if (!empty($pconfig['mx']) && !is_domain($pconfig['mx'])) {
- $input_errors[] = gettext("A valid MX host must be specified.");
- }
- break;
- default:
- $input_errors[] = gettext("A valid resource record type must be specified.");
- break;
- }
-
- foreach ($pconfig['aliases']['item'] as $idx => $alias) {
- if (!empty($alias['host']) && !is_hostname($alias['host'])) {
- $input_errors[] = gettext('Hostnames in alias list can only contain the characters A-Z, 0-9 and \'-\'.');
- }
- if (!empty($alias['domain']) && !is_domain($alias['domain'])) {
- $input_errors[] = gettext('A valid domain must be specified in alias list.');
- }
- if (empty($alias['host']) && empty($alias['domain'])) {
- $input_errors[] = gettext('A valid hostname or domain must be specified in alias list.');
- }
- }
-
- if (count($input_errors) == 0) {
- $hostent = array();
- $hostent['host'] = $pconfig['host'];
- $hostent['domain'] = $pconfig['domain'];
- /* distinguish between A and AAAA by parsing the passed IP address */
- $hostent['rr'] = ($pconfig['rr'] == 'A' && is_ipaddrv6($pconfig['ip'])) ? 'AAAA' : $pconfig['rr'];
- $hostent['ip'] = $pconfig['ip'];
- $hostent['mxprio'] = $pconfig['mxprio'];
- $hostent['mx'] = $pconfig['mx'];
- $hostent['descr'] = $pconfig['descr'];
- $hostent['aliases'] = $pconfig['aliases'];
-
- if (isset($id)) {
- $a_hosts[$id] = $hostent;
- } else {
- $a_hosts[] = $hostent;
- }
-
- usort($a_hosts, function ($a, $b) {
- return strcasecmp($a['host'], $b['host']);
- });
-
- mark_subsystem_dirty('unbound');
- write_config();
- header(url_safe('Location: /services_unbound_overrides.php'));
- exit;
- }
-}
-
-$service_hook = 'unbound';
-legacy_html_escape_form_data($pconfig);
-include("head.inc");
-?>
-
-
-
-
-
-
-
- 0) print_input_errors($input_errors); ?>
-
-
-
-
-
-
-
-
-
diff --git a/src/www/services_unbound_overrides.php b/src/www/services_unbound_overrides.php
deleted file mode 100644
index 93c98ec74..000000000
--- a/src/www/services_unbound_overrides.php
+++ /dev/null
@@ -1,252 +0,0 @@
-
- * Copyright (C) 2014-2016 Deciso B.V.
- * Copyright (C) 2014 Warren Baker
- * 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("system.inc");
-require_once("interfaces.inc");
-require_once("plugins.inc.d/unbound.inc");
-
-$a_hosts = &config_read_array('unbound', 'hosts');
-$a_domains = &config_read_array('unbound', 'domainoverrides');
-
-/* Backwards compatibility for records created before introducing RR types. */
-foreach ($a_hosts as $i => $hostent) {
- if (!isset($hostent['rr'])) {
- $a_hosts[$i]['rr'] = is_ipaddrv6($hostent['ip']) ? 'AAAA' : 'A';
- }
-}
-
-if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $pconfig = $_POST;
- if (!empty($pconfig['apply'])) {
- unbound_configure_do();
- clear_subsystem_dirty('unbound');
- header(url_safe('Location: /services_unbound_overrides.php'));
- exit;
- } elseif (!empty($pconfig['act']) && $pconfig['act'] == 'del') {
- if (isset($pconfig['id']) && !empty($a_hosts[$pconfig['id']])) {
- unset($a_hosts[$pconfig['id']]);
- write_config();
- mark_subsystem_dirty('unbound');
- exit;
- }
- } elseif (!empty($pconfig['act']) && $pconfig['act'] == 'doverride') {
- if (isset($pconfig['id']) && !empty($a_domains[$pconfig['id']])) {
- unset($a_domains[$pconfig['id']]);
- write_config();
- mark_subsystem_dirty('unbound');
- exit;
- }
- }
-}
-
-$service_hook = 'unbound';
-
-legacy_html_escape_form_data($a_hosts);
-legacy_html_escape_form_data($a_domains);
-
-include_once("head.inc");
-
-?>
-
-
-
-
-
-
-