Add GUI controls to the DNS Resolver for providing DNS over TLS service to local clients. Implements #8030

This commit is contained in:
jim-p 2018-04-06 13:56:31 -04:00
parent 423ce46d6d
commit 1fa69c27ee
2 changed files with 118 additions and 30 deletions

View File

@ -178,35 +178,64 @@ private-address: fe80::/10
EOF;
}
// Determine interfaces to run on
$bindints = "";
if (!empty($unboundcfg['active_interface'])) {
$active_interfaces = explode(",", $unboundcfg['active_interface']);
if (in_array("all", $active_interfaces, true)) {
$bindints .= "interface: 0.0.0.0\n";
$bindints .= "interface: ::0\n";
$bindints .= "interface-automatic: yes\n";
} else {
foreach ($active_interfaces as $ubif) {
if (is_ipaddr($ubif)) {
$bindints .= "interface: $ubif\n";
} else {
$intip = get_interface_ip($ubif);
if (is_ipaddrv4($intip)) {
$bindints .= "interface: $intip\n";
}
$intip = get_interface_ipv6($ubif);
if (is_ipaddrv6($intip)) {
$bindints .= "interface: $intip\n";
}
// Determine interfaces where unbound will bind
$sslport = is_numeric($unboundcfg['sslport']) ? $unboundcfg['sslport'] : "853";
$bindintcfg = "";
$bindints = array();
$active_interfaces = explode(",", $unboundcfg['active_interface']);
if (empty($unboundcfg['active_interface']) || in_array("all", $active_interfaces, true)) {
$bindints[] = "0.0.0.0";
$bindints[] = "::0";
$bindintcfg .= "interface-automatic: " . (isset($unboundcfg['enablessl']) ? "no" : "yes") . "\n";
} else {
foreach ($active_interfaces as $ubif) {
if (is_ipaddr($ubif)) {
$bindints[] = $ubif;
} else {
$intip = get_interface_ip($ubif);
if (is_ipaddrv4($intip)) {
$bindints[] = $intip;
}
$intip = get_interface_ipv6($ubif);
if (is_ipaddrv6($intip)) {
$bindints[] = $intip;
}
}
}
} else {
$bindints .= "interface: 0.0.0.0\n";
$bindints .= "interface: ::0\n";
/* If the active interface array is empty, treat it the same as "All" as is done above. Otherwise it breaks CARP with a default config. */
$bindints .= "interface-automatic: yes\n";
}
foreach ($bindints as $bindint) {
$bindintcfg .= "interface: {$bindint}\n";
if (isset($unboundcfg['enablessl'])) {
$bindintcfg .= "interface: {$bindint}@{$sslport}\n";
}
}
// SSL Configuration
$sslconfig = "";
if (isset($unboundcfg['enablessl'])) {
$sslcert_path = "{$g['unbound_chroot_path']}/sslcert.crt";
$sslkey_path = "{$g['unbound_chroot_path']}/sslcert.key";
// Enable SSL on the chosen or default port
$sslconfig .= "ssl-port: {$sslport}\n";
// Lookup CA and Server Cert
$cert = lookup_cert($unboundcfg['sslcertref']);
$ca = ca_chain($cert);
$cert_chain = base64_decode($cert['crt']);
if (!empty($ca)) {
$cert_chain .= "\n" . $ca;
}
// 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);
// Add config for CA and Server Cert
$sslconfig .= "ssl-service-pem: \"{$sslcert_path}\"\n";
$sslconfig .= "ssl-service-key: \"{$sslkey_path}\"\n";
}
// Determine interfaces to run on
@ -392,10 +421,11 @@ use-caps-for-id: {$use_caps}
serve-expired: {$dns_record_cache}
# Statistics
{$statistics}
# SSL Configuration
{$sslconfig}
# Interface IP(s) to bind to
{$bindints}
{$bindintcfg}
{$outgoingints}
# DNS Rebinding
{$private_addr}
{$private_domains}
@ -764,7 +794,6 @@ function unbound_acls_config($cfgsubdir = "") {
$active_interfaces = get_configured_interface_with_descr();
}
$bindints = "";
foreach ($active_interfaces as $ubif => $ifdesc) {
$ifip = get_interface_ip($ubif);
if (is_ipaddrv4($ifip)) {

View File

@ -53,6 +53,9 @@ $a_domainOverrides = &$a_unboundcfg['domainoverrides'];
if (isset($a_unboundcfg['enable'])) {
$pconfig['enable'] = true;
}
if (isset($a_unboundcfg['enablessl'])) {
$pconfig['enablessl'] = true;
}
if (isset($a_unboundcfg['dnssec'])) {
$pconfig['dnssec'] = true;
}
@ -73,6 +76,8 @@ if (isset($a_unboundcfg['regovpnclients'])) {
}
$pconfig['port'] = $a_unboundcfg['port'];
$pconfig['sslport'] = $a_unboundcfg['sslport'];
$pconfig['sslcertref'] = $a_unboundcfg['sslcertref'];
$pconfig['custom_options'] = base64_decode($a_unboundcfg['custom_options']);
if (empty($a_unboundcfg['active_interface'])) {
@ -93,6 +98,14 @@ if (empty($a_unboundcfg['system_domain_local_zone_type'])) {
$pconfig['system_domain_local_zone_type'] = $a_unboundcfg['system_domain_local_zone_type'];
}
$a_cert =& $config['cert'];
$certs_available = false;
if (is_array($a_cert) && count($a_cert)) {
$certs_available = true;
} else {
$a_cert = array();
}
if ($_POST['apply']) {
$retval = 0;
@ -116,6 +129,10 @@ if ($_POST['save']) {
}
}
if (isset($pconfig['enablessl']) && (!$certs_available || empty($pconfig['sslcertref']))) {
$input_errors[] = gettext("Acting as an SSL/TLS server requires a valid server certificate");
}
// forwarding mode requires having valid DNS servers
if (isset($pconfig['forwarding'])) {
$founddns = false;
@ -154,6 +171,9 @@ if ($_POST['save']) {
if ($pconfig['port'] && !is_port($pconfig['port'])) {
$input_errors[] = gettext("A valid port number must be specified.");
}
if ($pconfig['sslport'] && !is_port($pconfig['sslport'])) {
$input_errors[] = gettext("A valid SSL/TLS port number must be specified.");
}
if (is_array($pconfig['active_interface']) && !empty($pconfig['active_interface'])) {
$display_active_interface = $pconfig['active_interface'];
@ -184,7 +204,10 @@ if ($_POST['save']) {
if (!$input_errors) {
$a_unboundcfg['enable'] = isset($pconfig['enable']);
$a_unboundcfg['enablessl'] = isset($pconfig['enablessl']);
$a_unboundcfg['port'] = $pconfig['port'];
$a_unboundcfg['sslport'] = $pconfig['sslport'];
$a_unboundcfg['sslcertref'] = $pconfig['sslcertref'];
$a_unboundcfg['dnssec'] = isset($pconfig['dnssec']);
$a_unboundcfg['forwarding'] = isset($pconfig['forwarding']);
$a_unboundcfg['forward_tls_upstream'] = isset($pconfig['forward_tls_upstream']);
@ -297,6 +320,42 @@ $section->addInput(new Form_Input(
['placeholder' => '53']
))->setHelp('The port used for responding to DNS queries. It should normally be left blank unless another service needs to bind to TCP/UDP port 53.');
$section->addInput(new Form_Checkbox(
'enablessl',
'Enable SSL/TLS Service',
'Respond to incoming SSL/TLS queries from local clients',
$pconfig['enablessl']
))->setHelp('Configures the DNS Resolver to act as a DNS over SSL/TLS server which can answer queries from clients which also support DNS over TLS. ' .
'Activating this option disables automatic interface response routing behavior, thus it works best with specific interface bindings.' );
if ($certs_available) {
$values = array();
foreach ($a_cert as $cert) {
$values[ $cert['refid'] ] = $cert['descr'];
}
$section->addInput($input = new Form_Select(
'sslcertref',
'SSL/TLS Certificate',
$pconfig['sslcertref'],
$values
))->setHelp('The server certificate to use for SSL/TLS service. The CA chain will be determined automatically.');
} else {
$section->addInput(new Form_StaticText(
'SSL/TLS Certificate',
sprintf('No Certificates have been defined. A certificate is required before SSL/TLS can be enabled. %1$s Create or Import %2$s a Certificate.',
'<a href="system_certmanager.php">', '</a>')
));
}
$section->addInput(new Form_Input(
'sslport',
'SSL/TLS Listen Port',
'number',
$pconfig['sslport'],
['placeholder' => '853']
))->setHelp('The port used for responding to SSL/TLS DNS queries. It should normally be left blank unless another service needs to bind to TCP/UDP port 853.');
$activeiflist = build_if_list($pconfig['active_interface']);
$section->addInput(new Form_Select(
@ -344,7 +403,7 @@ $section->addInput(new Form_Checkbox(
$section->addInput(new Form_Checkbox(
'forward_tls_upstream',
null,
'Use SSL/TLS for DNS Queries to Forwarding Servers',
'Use SSL/TLS for outgoing DNS Queries to Forwarding Servers',
$pconfig['forward_tls_upstream']
))->setHelp('When set in conjunction with DNS Query Forwarding, queries to all upstream forwarding DNS servers will be sent using SSL/TLS on the default port of 853. Note that ALL configured forwarding servers MUST support SSL/TLS queries on port 853.');