diff options
author | jim-p <jimp@netgate.com> | 2019-02-06 14:13:26 -0500 |
---|---|---|
committer | jim-p <jimp@netgate.com> | 2019-05-10 16:20:21 -0400 |
commit | 44fb8aca0db0e8c7fe03cb2e37a3cfe71872b1b3 (patch) | |
tree | 432551f3a295c410788239a4c36ad2fc4e8a031c | |
parent | fdb7f0a54726542d848f87e9158f7f0f9aeb648d (diff) | |
download | pfsense-44fb8aca0db0e8c7fe03cb2e37a3cfe71872b1b3.zip pfsense-44fb8aca0db0e8c7fe03cb2e37a3cfe71872b1b3.tar.gz |
Add back DNS over TLS host verification code. Fixes #8602
Requires Unbound 1.9.0_1 from pfsense/freebsd-ports, which fixes a bug
in Unbound 1.9.0 which did not fully implement OpenSSL 1.0.2 host
validation support. See https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=4206#c5
(cherry picked from commit 7e8bfed216304b37342a0800eb35ef7c29546f5d)
-rw-r--r-- | src/etc/inc/unbound.inc | 65 | ||||
-rw-r--r-- | src/usr/local/www/services_unbound_domainoverride_edit.php | 13 | ||||
-rw-r--r-- | src/usr/local/www/system.php | 40 |
3 files changed, 97 insertions, 21 deletions
diff --git a/src/etc/inc/unbound.inc b/src/etc/inc/unbound.inc index 350cf56..66a7c89 100644 --- a/src/etc/inc/unbound.inc +++ b/src/etc/inc/unbound.inc @@ -183,7 +183,7 @@ EOF; } // Determine interfaces where unbound will bind - $sslport = is_numeric($unboundcfg['sslport']) ? $unboundcfg['sslport'] : "853"; + $tlsport = is_numeric($unboundcfg['tlsport']) ? $unboundcfg['tlsport'] : "853"; $bindintcfg = ""; $bindints = array(); $active_interfaces = explode(",", $unboundcfg['active_interface']); @@ -210,18 +210,19 @@ EOF; foreach ($bindints as $bindint) { $bindintcfg .= "interface: {$bindint}\n"; if (isset($unboundcfg['enablessl'])) { - $bindintcfg .= "interface: {$bindint}@{$sslport}\n"; + $bindintcfg .= "interface: {$bindint}@{$tlsport}\n"; } } - // SSL Configuration - $sslconfig = ""; + // TLS Configuration + $tlsconfig = "tls-cert-bundle: \"/etc/ssl/cert.pem\"\n"; + if (isset($unboundcfg['enablessl'])) { - $sslcert_path = "{$g['unbound_chroot_path']}/sslcert.crt"; - $sslkey_path = "{$g['unbound_chroot_path']}/sslcert.key"; + $tlscert_path = "{$g['unbound_chroot_path']}/sslcert.crt"; + $tlskey_path = "{$g['unbound_chroot_path']}/sslcert.key"; // Enable SSL on the chosen or default port - $sslconfig .= "ssl-port: {$sslport}\n"; + $tlsconfig .= "tls-port: {$tlsport}\n"; // Lookup CA and Server Cert $cert = lookup_cert($unboundcfg['sslcertref']); @@ -232,14 +233,14 @@ EOF; } // Write CA and Server Cert - file_put_contents($sslcert_path, $cert_chain); - chmod($sslcert_path, 0644); - file_put_contents($sslkey_path, base64_decode($cert['prv'])); - chmod($sslkey_path, 0600); + file_put_contents($tlscert_path, $cert_chain); + chmod($tlscert_path, 0644); + file_put_contents($tlskey_path, base64_decode($cert['prv'])); + chmod($tlskey_path, 0600); // Add config for CA and Server Cert - $sslconfig .= "ssl-service-pem: \"{$sslcert_path}\"\n"; - $sslconfig .= "ssl-service-key: \"{$sslkey_path}\"\n"; + $tlsconfig .= "tls-service-pem: \"{$tlscert_path}\"\n"; + $tlsconfig .= "tls-service-key: \"{$tlskey_path}\"\n"; } // Determine interfaces to run on @@ -345,10 +346,29 @@ EOD; if (isset($unboundcfg['forward_tls_upstream'])) { $forward_conf .= "\tforward-tls-upstream: yes\n"; } + + /* Build DNS server hostname list. See https://redmine.pfsense.org/issues/8602 */ + $dns_hostnames = array(); + $dnshost_counter = 1; + while (isset($config["system"]["dns{$dnshost_counter}host"])) { + $pconfig_dnshost_counter = $dnshost_counter - 1; + if (!empty($config["system"]["dns{$dnshost_counter}host"]) && + isset($config["system"]["dnsserver"][$pconfig_dnshost_counter])) + $dns_hostnames[$config["system"]["dnsserver"][$pconfig_dnshost_counter]] = $config["system"]["dns{$dnshost_counter}host"]; + $dnshost_counter++; + } + foreach ($dnsservers as $dnsserver) { + $fwdport = ""; + $fwdhost = ""; if (is_ipaddr($dnsserver) && !ip_in_subnet($dnsserver, "127.0.0.0/8")) { - $fwdport = isset($unboundcfg['forward_tls_upstream']) ? "@853" : ""; - $forward_conf .= "\tforward-addr: {$dnsserver}{$fwdport}\n"; + if (isset($unboundcfg['forward_tls_upstream'])) { + $fwdport = "@853"; + if (array_key_exists($dnsserver, $dns_hostnames)) { + $fwdhost = "#{$dns_hostnames[$dnsserver]}"; + } + } + $forward_conf .= "\tforward-addr: {$dnsserver}{$fwdport}{$fwdhost}\n"; } } } @@ -425,8 +445,8 @@ use-caps-for-id: {$use_caps} serve-expired: {$dns_record_cache} # Statistics {$statistics} -# SSL Configuration -{$sslconfig} +# TLS Configuration +{$tlsconfig} # Interface IP(s) to bind to {$bindintcfg} {$outgoingints} @@ -571,6 +591,7 @@ function unbound_add_domain_overrides($pvt_rev="", $cfgsubdir = "") { $sorted_domains = msort($domains, "domain"); $result = array(); $tls_domains = array(); + $tls_hostnames = array(); foreach ($sorted_domains as $domain) { $domain_key = current($domain); if (!isset($result[$domain_key])) { @@ -580,6 +601,7 @@ function unbound_add_domain_overrides($pvt_rev="", $cfgsubdir = "") { /* If any entry for a domain has TLS set, it will be active for all entries. */ if (isset($domain['forward_tls_upstream'])) { $tls_domains[] = $domain_key; + $tls_hostnames[$domain['ip']] = $domain['tls_hostname']; } } @@ -594,20 +616,25 @@ function unbound_add_domain_overrides($pvt_rev="", $cfgsubdir = "") { $domain_entries .= "local-zone: \"$domain\" typetransparent\n"; } } else { + $use_tls = in_array($domain, $tls_domains); $domain_entries .= "forward-zone:\n"; $domain_entries .= "\tname: \"$domain\"\n"; $fwdport = ""; /* Enable TLS forwarding for this domain if needed. */ - if (in_array($domain, $tls_domains)) { + if ($use_tls) { $domain_entries .= "\tforward-tls-upstream: yes\n"; $fwdport = "@853"; } foreach ($ips as $ip) { + $fwdhost = ""; /* If an IP address already contains a port specification, do not add another. */ if (strstr($ip, '@') !== false) { $fwdport = ""; } - $domain_entries .= "\tforward-addr: {$ip}{$fwdport}\n"; + if ($use_tls && array_key_exists($ip, $tls_hostnames)) { + $fwdhost = "#{$tls_hostnames[$ip]}"; + } + $domain_entries .= "\tforward-addr: {$ip}{$fwdport}{$fwdhost}\n"; } } } diff --git a/src/usr/local/www/services_unbound_domainoverride_edit.php b/src/usr/local/www/services_unbound_domainoverride_edit.php index b5429a6..b3e6957 100644 --- a/src/usr/local/www/services_unbound_domainoverride_edit.php +++ b/src/usr/local/www/services_unbound_domainoverride_edit.php @@ -42,6 +42,7 @@ if (isset($id) && $a_domainOverrides[$id]) { $pconfig['domain'] = $a_domainOverrides[$id]['domain']; $pconfig['ip'] = $a_domainOverrides[$id]['ip']; $pconfig['descr'] = $a_domainOverrides[$id]['descr']; + $pconfig['tls_hostname'] = $a_domainOverrides[$id]['tls_hostname']; $pconfig['forward_tls_upstream'] = isset($a_domainOverrides[$id]['forward_tls_upstream']); } @@ -80,11 +81,16 @@ if ($_POST['save']) { } } + if (!empty($_POST['tls_hostname']) && !is_hostname($_POST['tls_hostname'])) { + $input_errors[] = gettext("The supplied TLS hostname is not valid."); + } + if (!$input_errors) { $doment = array(); $doment['domain'] = $_POST['domain']; $doment['ip'] = $_POST['ip']; $doment['descr'] = $_POST['descr']; + $doment['tls_hostname'] = $_POST['tls_hostname']; $doment['forward_tls_upstream'] = isset($_POST['forward_tls_upstream']); if (isset($id) && $a_domainOverrides[$id]) { @@ -137,6 +143,13 @@ $section->addInput(new Form_Checkbox( ))->setHelp('When set, queries to %1$sall DNS servers for this domain%2$s will be sent using SSL/TLS on the default port of 853.', '<b>', '</b>'); $section->addInput(new Form_Input( + 'tls_hostname', + 'TLS Hostname', + 'text', + $pconfig['tls_hostname'] +))->setHelp('An optional TLS hostname used to verify the server certificate when performing TLS Queries.'); + +$section->addInput(new Form_Input( 'descr', 'Description', 'text', diff --git a/src/usr/local/www/system.php b/src/usr/local/www/system.php index d1cab7d..5337ca8 100644 --- a/src/usr/local/www/system.php +++ b/src/usr/local/www/system.php @@ -52,6 +52,14 @@ if (!isset($config['system']['language'])) { $config['system']['language'] = $g['language']; } +$dnshost_counter = 1; + +while (isset($config["system"]["dns{$dnshost_counter}host"])) { + $pconfig_dnshost_counter = $dnshost_counter - 1; + $pconfig["dnshost{$pconfig_dnshost_counter}"] = $config["system"]["dns{$dnshost_counter}host"]; + $dnshost_counter++; +} + $dnsgw_counter = 1; while (isset($config["system"]["dns{$dnsgw_counter}gw"])) { @@ -184,11 +192,15 @@ if ($_POST) { while (isset($_POST[$dnsname])) { $dnsgwname = "dnsgw{$dnscounter}"; + $dnshostname = "dnshost{$dnscounter}"; $dnslist[] = $_POST[$dnsname]; if (($_POST[$dnsname] && !is_ipaddr($_POST[$dnsname]))) { $input_errors[] = sprintf(gettext("A valid IP address must be specified for DNS server %s."), $dnscounter+1); } else { + if (!empty($_POST[$dnshostname]) && !is_hostname($_POST[$dnshostname])) { + $input_errors[] = sprintf(gettext('The hostname provided for DNS server "%1$s" is not valid.'), $_POST[$dnsname]); + } if (($_POST[$dnsgwname] <> "") && ($_POST[$dnsgwname] <> "none")) { // A real gateway has been selected. if (is_ipaddr($_POST[$dnsname])) { @@ -350,22 +362,29 @@ if ($_POST) { while (isset($_POST[$dnsname])) { // The $_POST array key of the corresponding gateway (starts from 0) $dnsgwname = "dnsgw{$dnscounter}"; - // The numbering of DNS GW entries in the config starts from 1 + $dnshostname = "dnshost{$dnscounter}"; + // The numbering of DNS GW/host entries in the config starts from 1 $dnsgwconfigcounter = $dnscounter + 1; + $dnshostconfigcounter = $dnscounter + 1; // So this is the array key of the DNS GW entry in $config['system'] $dnsgwconfigname = "dns{$dnsgwconfigcounter}gw"; + $dnshostconfigname = "dns{$dnshostconfigcounter}host"; $olddnsgwname = $config['system'][$dnsgwconfigname]; + $olddnshostname = $config['system'][$dnshostconfigname]; if ($ignore_posted_dnsgw[$dnsgwname]) { $thisdnsgwname = "none"; } else { $thisdnsgwname = $pconfig[$dnsgwname]; } + $thisdnshostname = $pconfig[$dnshostname]; // "Blank" out the settings for this index, then we set them below using the "outdnscounter" index. $config['system'][$dnsgwconfigname] = "none"; $pconfig[$dnsgwname] = "none"; + $config['system'][$dnshostconfigname] = ""; + $pconfig[$dnshostname] = ""; $pconfig[$dnsname] = ""; if ($_POST[$dnsname]) { @@ -377,19 +396,28 @@ if ($_POST) { $outdnsname = "dns{$outdnscounter}"; // The $pconfig array key of the corresponding gateway (starts from 0) $outdnsgwname = "dnsgw{$outdnscounter}"; - // The numbering of DNS GW entries in the config starts from 1 + // The $pconfig array key of the corresponding hostname (starts from 0) + $outdnshostname = "dnshost{$outdnscounter}"; + + // The numbering of DNS GW/host entries in the config starts from 1 $outdnsgwconfigcounter = $outdnscounter + 1; + $outdnshostconfigcounter = $outdnscounter + 1; // So this is the array key of the output DNS GW entry in $config['system'] $outdnsgwconfigname = "dns{$outdnsgwconfigcounter}gw"; + $outdnshostconfigname = "dns{$outdnshostconfigcounter}host"; $pconfig[$outdnsname] = $_POST[$dnsname]; if ($_POST[$dnsgwname]) { $config['system'][$outdnsgwconfigname] = $thisdnsgwname; $pconfig[$outdnsgwname] = $thisdnsgwname; + $config['system'][$outdnshostconfigname] = $thisdnshostname; + $pconfig[$outdnshostname] = $thisdnshostname; } else { // Note: when no DNS GW name is chosen, the entry is set to "none", so actually this case never happens. unset($config['system'][$outdnsgwconfigname]); $pconfig[$outdnsgwname] = ""; + unset($config['system'][$outdnshostconfigname]); + $pconfig[$outdnshostname] = ""; } $outdnscounter++; } @@ -485,6 +513,7 @@ $dnsserver_count = count($pconfig['dnsserver']); $dnsserver_num = 0; $dnsserver_help = gettext("Address") . '<br/>' . gettext("Enter IP addresses to be used by the system for DNS resolution.") . " " . gettext("These are also used for the DHCP service, DNS Forwarder and DNS Resolver when it has DNS Query Forwarding enabled."); +$dnshost_help = gettext("Hostname") . '<br/>' . gettext("Enter the DNS Server Hostname for TLS Verification in the DNS Resolver (optional)."); $dnsgw_help = gettext("Gateway") . '<br/>'. gettext("Optionally select the gateway for each DNS server.") . " " . gettext("When using multiple WAN connections there should be at least one unique DNS server per gateway."); @@ -506,6 +535,13 @@ foreach ($pconfig['dnsserver'] as $dnsserver) { $dnsserver ))->setHelp(($is_last_dnsserver) ? $dnsserver_help:null); + $group->add(new Form_Input( + 'dnshost' . $dnsserver_num, + 'DNS Hostname', + 'text', + $pconfig['dnshost' . $dnsserver_num] + ))->setHelp(($is_last_dnsserver) ? $dnshost_help:null); + if ($multiwan) { $options = array('none' => 'none'); |