Project

General

Profile

Download (31.9 KB) Statistics
| Branch: | Tag: | Revision:
1 f20afeb6 Warren Baker
<?php
2
/*
3 ac24dc24 Renato Botelho
 * unbound.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6 c5d81585 Renato Botelho
 * Copyright (c) 2015 Warren Baker <warren@percol8.co.za>
7 38809d47 Renato Botelho do Couto
 * Copyright (c) 2015-2016 Electric Sheep Fencing
8 0284d79e jim-p
 * Copyright (c) 2015-2020 Rubicon Communications, LLC (Netgate)
9 ac24dc24 Renato Botelho
 * All rights reserved.
10
 *
11
 * originally part of m0n0wall (http://m0n0.ch/wall)
12 c5d81585 Renato Botelho
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
13 ac24dc24 Renato Botelho
 * All rights reserved.
14
 *
15 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
16
 * you may not use this file except in compliance with the License.
17
 * You may obtain a copy of the License at
18 ac24dc24 Renato Botelho
 *
19 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
20 ac24dc24 Renato Botelho
 *
21 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
22
 * distributed under the License is distributed on an "AS IS" BASIS,
23
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
 * See the License for the specific language governing permissions and
25
 * limitations under the License.
26 ac24dc24 Renato Botelho
 */
27 f20afeb6 Warren Baker
28
/* include all configuration functions */
29
require_once("config.inc");
30
require_once("functions.inc");
31 3bdf2a70 Chris Buechler
require_once("filter.inc");
32
require_once("shaper.inc");
33 09d529a6 Viktor G
require_once("interfaces.inc");
34
require_once("util.inc");
35 f20afeb6 Warren Baker
36 1548bd35 Phil Davis
function create_unbound_chroot_path($cfgsubdir = "") {
37 e318d592 Phil Davis
	global $config, $g;
38
39
	// Configure chroot
40
	if (!is_dir($g['unbound_chroot_path'])) {
41
		mkdir($g['unbound_chroot_path']);
42
		chown($g['unbound_chroot_path'], "unbound");
43
		chgrp($g['unbound_chroot_path'], "unbound");
44
	}
45
46 1548bd35 Phil Davis
	if ($cfgsubdir != "") {
47
		$cfgdir = $g['unbound_chroot_path'] . $cfgsubdir;
48
		if (!is_dir($cfgdir)) {
49
			mkdir($cfgdir);
50
			chown($cfgdir, "unbound");
51
			chgrp($cfgdir, "unbound");
52
		}
53
	}
54 e318d592 Phil Davis
}
55
56 f20afeb6 Warren Baker
/* Optimize Unbound for environment */
57
function unbound_optimization() {
58 fe9d4894 Renato Botelho
	global $config;
59
60
	$optimization_settings = array();
61
62 751533a2 Phil Davis
	/*
63 fe9d4894 Renato Botelho
	 * Set the number of threads equal to number of CPUs.
64
	 * Use 1 to disable threading, if for some reason this sysctl fails.
65
	 */
66
	$numprocs = intval(get_single_sysctl('kern.smp.cpus'));
67 46762efe Warren Baker
	if ($numprocs > 1) {
68 fe9d4894 Renato Botelho
		$optimization['number_threads'] = "num-threads: {$numprocs}";
69 086cf944 Phil Davis
		$optimize_num = pow(2, floor(log($numprocs, 2)));
70 46762efe Warren Baker
	} else {
71 fe9d4894 Renato Botelho
		$optimization['number_threads'] = "num-threads: 1";
72 46762efe Warren Baker
		$optimize_num = 4;
73
	}
74 fe9d4894 Renato Botelho
75
	// Slabs to help reduce lock contention.
76 46762efe Warren Baker
	$optimization['msg_cache_slabs'] = "msg-cache-slabs: {$optimize_num}";
77
	$optimization['rrset_cache_slabs'] = "rrset-cache-slabs: {$optimize_num}";
78
	$optimization['infra_cache_slabs'] = "infra-cache-slabs: {$optimize_num}";
79
	$optimization['key_cache_slabs'] = "key-cache-slabs: {$optimize_num}";
80 fe9d4894 Renato Botelho
81
	/*
82
	 * Larger socket buffer for busy servers
83
	 * Check that it is set to 4MB (by default the OS has it configured to 4MB)
84
	 */
85 d87fcac9 Ermal
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
86
		foreach ($config['sysctl']['item'] as $tunable) {
87
			if ($tunable['tunable'] == 'kern.ipc.maxsockbuf') {
88 3e2e1b2c Steve Beaver
				$so = floor((intval($tunable['value'])/1024/1024)-4);
89 d87fcac9 Ermal
				// Check to ensure that the number is not a negative
90 ad04bbbf Warren Baker
				if ($so >= 4) {
91
					// Limit to 32MB, users might set maxsockbuf very high for other reasons.
92 4708c6f0 Phil Davis
					// We do not want unbound to fail because of that.
93 ad04bbbf Warren Baker
					$so = min($so, 32);
94 d87fcac9 Ermal
					$optimization['so_rcvbuf'] = "so-rcvbuf: {$so}m";
95 ad04bbbf Warren Baker
				} else {
96 d87fcac9 Ermal
					unset($optimization['so_rcvbuf']);
97 ad04bbbf Warren Baker
				}
98 d87fcac9 Ermal
			}
99 fe9d4894 Renato Botelho
		}
100
	}
101
	// Safety check in case kern.ipc.maxsockbuf is not available.
102 751533a2 Phil Davis
	if (!isset($optimization['so_rcvbuf'])) {
103 fe9d4894 Renato Botelho
		$optimization['so_rcvbuf'] = "#so-rcvbuf: 4m";
104 751533a2 Phil Davis
	}
105 fe9d4894 Renato Botelho
106
	return $optimization;
107 f20afeb6 Warren Baker
108
}
109
110 932711c7 Matt Smith
function test_unbound_config($unboundcfg, &$output) {
111
	global $g;
112
113 1548bd35 Phil Davis
	$cfgsubdir = "/test";
114 3d706897 Renato Botelho
	$cfgdir = "{$g['unbound_chroot_path']}{$cfgsubdir}";
115
	rmdir_recursive($cfgdir);
116
117 1548bd35 Phil Davis
	unbound_generate_config($unboundcfg, $cfgsubdir);
118
	unbound_remote_control_setup($cfgsubdir);
119
	do_as_unbound_user("unbound-anchor", $cfgsubdir);
120
121 241c4b58 BBcan177
	// Copy the Python files to the test folder
122
	if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script'])) {
123
		$python_files = glob("{$g['unbound_chroot_path']}/{$unboundcfg['python_script']}.*");
124
		if (is_array($python_files)) {
125
			foreach ($python_files as $file) {
126
				$file = pathinfo($file, PATHINFO_BASENAME);
127
				@copy("{$g['unbound_chroot_path']}/{$file}", "{$cfgdir}/{$file}");
128
			}
129
		}
130
	}
131
132 932711c7 Matt Smith
	$rv = 0;
133 3d706897 Renato Botelho
	exec("/usr/local/sbin/unbound-checkconf {$cfgdir}/unbound.conf 2>&1",
134
	    $output, $rv);
135
136
	if ($rv == 0) {
137
		rmdir_recursive($cfgdir);
138
	}
139 932711c7 Matt Smith
140
	return $rv;
141
}
142
143
144 1548bd35 Phil Davis
function unbound_generate_config($unboundcfg = NULL, $cfgsubdir = "") {
145 a569071d Phil Davis
	global $g;
146 932711c7 Matt Smith
147 1548bd35 Phil Davis
	$unboundcfgtxt = unbound_generate_config_text($unboundcfg, $cfgsubdir);
148 932711c7 Matt Smith
149
	// Configure static Host entries
150 1548bd35 Phil Davis
	unbound_add_host_entries($cfgsubdir);
151 932711c7 Matt Smith
152
	// Configure Domain Overrides
153 1548bd35 Phil Davis
	unbound_add_domain_overrides("", $cfgsubdir);
154 932711c7 Matt Smith
155
	// Configure Unbound access-lists
156 1548bd35 Phil Davis
	unbound_acls_config($cfgsubdir);
157 932711c7 Matt Smith
158 1548bd35 Phil Davis
	create_unbound_chroot_path($cfgsubdir);
159
	file_put_contents("{$g['unbound_chroot_path']}{$cfgsubdir}/unbound.conf", $unboundcfgtxt);
160 932711c7 Matt Smith
}
161
162
163 1548bd35 Phil Davis
function unbound_generate_config_text($unboundcfg = NULL, $cfgsubdir = "") {
164 932711c7 Matt Smith
165 fe9d4894 Renato Botelho
	global $config, $g;
166 932711c7 Matt Smith
	if (is_null($unboundcfg)) {
167
		$unboundcfg = $config['unbound'];
168
	}
169 fe9d4894 Renato Botelho
170
	// Setup optimization
171
	$optimization = unbound_optimization();
172
173 241c4b58 BBcan177
	$module_config = '';
174
175
	// Setup Python module (pre validator)
176
	if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script']) && $unboundcfg['python_order'] == 'pre_validator') {
177
		$module_config .= 'python ';
178
	}
179
180 dc104520 Viktor G
	// Setup DNS64 support
181
	if (isset($unboundcfg['dns64'])) {
182
		$module_config .= 'dns64 ';
183
		$dns64_conf = 'dns64-prefix: ';
184
		if (is_subnetv6($unboundcfg['dns64prefix'] . '/' . $unboundcfg['dns64netbits'])) {
185
			$dns64_conf .= $unboundcfg['dns64prefix'] . '/' . $unboundcfg['dns64netbits'];
186
		} else {
187
			$dns64_conf .= '64:ff9b::/96';
188
		}
189
	}
190
191 fe9d4894 Renato Botelho
	// Setup DNSSEC support
192 932711c7 Matt Smith
	if (isset($unboundcfg['dnssec'])) {
193 241c4b58 BBcan177
		$module_config .= 'validator ';
194 1548bd35 Phil Davis
		$anchor_file = "auto-trust-anchor-file: {$g['unbound_chroot_path']}{$cfgsubdir}/root.key";
195 751533a2 Phil Davis
	}
196 fe9d4894 Renato Botelho
197 241c4b58 BBcan177
	// Setup Python module (post validator)
198
	if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script']) && $unboundcfg['python_order'] == 'post_validator') {
199
		$module_config .= 'python ';
200
	}
201
202
	$module_config .= 'iterator';
203
204 fe9d4894 Renato Botelho
	// Setup DNS Rebinding
205
	if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
206
		// Private-addresses for DNS Rebinding
207
		$private_addr = <<<EOF
208 f20afeb6 Warren Baker
# For DNS Rebinding prevention
209 afeb18ff jim-p
private-address: 127.0.0.0/8
210 f20afeb6 Warren Baker
private-address: 10.0.0.0/8
211 df0a71cb jim-p
private-address: ::ffff:a00:0/104
212 f20afeb6 Warren Baker
private-address: 172.16.0.0/12
213 df0a71cb jim-p
private-address: ::ffff:ac10:0/108
214 c683f627 Chris Buechler
private-address: 169.254.0.0/16
215 df0a71cb jim-p
private-address: ::ffff:a9fe:0/112
216 f20afeb6 Warren Baker
private-address: 192.168.0.0/16
217 df0a71cb jim-p
private-address: ::ffff:c0a8:0/112
218 f20afeb6 Warren Baker
private-address: fd00::/8
219
private-address: fe80::/10
220
EOF;
221 fe9d4894 Renato Botelho
	}
222
223 1fa69c27 jim-p
	// Determine interfaces where unbound will bind
224 7e8bfed2 jim-p
	$tlsport = is_numeric($unboundcfg['tlsport']) ? $unboundcfg['tlsport'] : "853";
225 1fa69c27 jim-p
	$bindintcfg = "";
226
	$bindints = array();
227
	$active_interfaces = explode(",", $unboundcfg['active_interface']);
228
	if (empty($unboundcfg['active_interface']) || in_array("all", $active_interfaces, true)) {
229
		$bindints[] = "0.0.0.0";
230
		$bindints[] = "::0";
231
		$bindintcfg .= "interface-automatic: " . (isset($unboundcfg['enablessl']) ? "no" : "yes") . "\n";
232
	} else {
233
		foreach ($active_interfaces as $ubif) {
234 e65b646f Viktor G
			/* Do not bind to disabled/nocarrier interfaces,
235
			 * see https://redmine.pfsense.org/issues/11087 */
236
			$ifinfo = get_interface_info($ubif);
237
			if ($ifinfo && (($ifinfo['status'] != 'up') || !$ifinfo['enable'])) {
238
				continue;
239
			}
240 1fa69c27 jim-p
			if (is_ipaddr($ubif)) {
241
				$bindints[] = $ubif;
242
			} else {
243
				$intip = get_interface_ip($ubif);
244
				if (is_ipaddrv4($intip)) {
245
					$bindints[] = $intip;
246
				}
247
				$intip = get_interface_ipv6($ubif);
248
				if (is_ipaddrv6($intip)) {
249
					$bindints[] = $intip;
250 a0e9e17d Chris Buechler
				}
251 751533a2 Phil Davis
			}
252 fe9d4894 Renato Botelho
		}
253 1fa69c27 jim-p
	}
254
	foreach ($bindints as $bindint) {
255
		$bindintcfg .= "interface: {$bindint}\n";
256
		if (isset($unboundcfg['enablessl'])) {
257 7e8bfed2 jim-p
			$bindintcfg .= "interface: {$bindint}@{$tlsport}\n";
258 1fa69c27 jim-p
		}
259
	}
260
261 7e8bfed2 jim-p
	// TLS Configuration
262
	$tlsconfig = "tls-cert-bundle: \"/etc/ssl/cert.pem\"\n";
263
264 1fa69c27 jim-p
	if (isset($unboundcfg['enablessl'])) {
265 7e8bfed2 jim-p
		$tlscert_path = "{$g['unbound_chroot_path']}/sslcert.crt";
266
		$tlskey_path = "{$g['unbound_chroot_path']}/sslcert.key";
267 1fa69c27 jim-p
268 f764f63a jim-p
		// Enable SSL/TLS on the chosen or default port
269 7e8bfed2 jim-p
		$tlsconfig .= "tls-port: {$tlsport}\n";
270 1fa69c27 jim-p
271
		// Lookup CA and Server Cert
272
		$cert = lookup_cert($unboundcfg['sslcertref']);
273
		$ca = ca_chain($cert);
274
		$cert_chain = base64_decode($cert['crt']);
275
		if (!empty($ca)) {
276
			$cert_chain .= "\n" . $ca;
277
		}
278
279
		// Write CA and Server Cert
280 7e8bfed2 jim-p
		file_put_contents($tlscert_path, $cert_chain);
281
		chmod($tlscert_path, 0644);
282
		file_put_contents($tlskey_path, base64_decode($cert['prv']));
283
		chmod($tlskey_path, 0600);
284 1fa69c27 jim-p
285
		// Add config for CA and Server Cert
286 7e8bfed2 jim-p
		$tlsconfig .= "tls-service-pem: \"{$tlscert_path}\"\n";
287
		$tlsconfig .= "tls-service-key: \"{$tlskey_path}\"\n";
288 fe9d4894 Renato Botelho
	}
289
290
	// Determine interfaces to run on
291
	$outgoingints = "";
292 932711c7 Matt Smith
	if (!empty($unboundcfg['outgoing_interface'])) {
293 fe9d4894 Renato Botelho
		$outgoingints = "# Outgoing interfaces to be used\n";
294 932711c7 Matt Smith
		$outgoing_interfaces = explode(",", $unboundcfg['outgoing_interface']);
295 751533a2 Phil Davis
		foreach ($outgoing_interfaces as $outif) {
296 e65b646f Viktor G
			$ifinfo = get_interface_info($outif);
297
			if ($ifinfo && (($ifinfo['status'] != 'up') || !$ifinfo['enable'])) {
298
				continue;
299
			}
300 fe9d4894 Renato Botelho
			$outip = get_interface_ip($outif);
301 c37ffea8 Chris Buechler
			if (is_ipaddr($outip)) {
302 fe9d4894 Renato Botelho
				$outgoingints .= "outgoing-interface: $outip\n";
303 751533a2 Phil Davis
			}
304 fe9d4894 Renato Botelho
			$outip = get_interface_ipv6($outif);
305 c37ffea8 Chris Buechler
			if (is_ipaddrv6($outip)) {
306 fe9d4894 Renato Botelho
				$outgoingints .= "outgoing-interface: $outip\n";
307 751533a2 Phil Davis
			}
308 fe9d4894 Renato Botelho
		}
309
	}
310
311
	// Allow DNS Rebind for forwarded domains
312 932711c7 Matt Smith
	if (isset($unboundcfg['domainoverrides']) && is_array($unboundcfg['domainoverrides'])) {
313 984abd66 Phil Davis
		if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
314
			$private_domains = "# Set private domains in case authoritative name server returns a Private IP address\n";
315
			$private_domains .= unbound_add_domain_overrides("private");
316
		}
317
		$reverse_zones .= unbound_add_domain_overrides("reverse");
318 fe9d4894 Renato Botelho
	}
319
320 ab8f10f2 Phil Davis
	// Configure Unbound statistics
321
	$statistics = unbound_statistics();
322
323 fe9d4894 Renato Botelho
	// Add custom Unbound options
324 932711c7 Matt Smith
	if ($unboundcfg['custom_options']) {
325
		$custom_options_source = explode("\n", base64_decode($unboundcfg['custom_options']));
326 b9608ab6 Phil Davis
		$custom_options = "# Unbound custom options\n";
327 751533a2 Phil Davis
		foreach ($custom_options_source as $ent) {
328 b9608ab6 Phil Davis
			$custom_options .= $ent."\n";
329 751533a2 Phil Davis
		}
330 fe9d4894 Renato Botelho
	}
331
332
	// Server configuration variables
333 932711c7 Matt Smith
	$port = (is_port($unboundcfg['port'])) ? $unboundcfg['port'] : "53";
334
	$hide_identity = isset($unboundcfg['hideidentity']) ? "yes" : "no";
335
	$hide_version = isset($unboundcfg['hideversion']) ? "yes" : "no";
336 deb575ab stilez
	$ipv6_allow = isset($config['system']['ipv6allow']) ? "yes" : "no";
337 932711c7 Matt Smith
	$harden_dnssec_stripped = isset($unboundcfg['dnssecstripped']) ? "yes" : "no";
338
	$prefetch = isset($unboundcfg['prefetch']) ? "yes" : "no";
339
	$prefetch_key = isset($unboundcfg['prefetchkey']) ? "yes" : "no";
340 84ec58b7 marjohn56
	$dns_record_cache = isset($unboundcfg['dnsrecordcache']) ? "yes" : "no";
341 7e9d72cf Viktor Gurov
	$aggressivensec = isset($unboundcfg['aggressivensec']) ? "yes" : "no";
342 f8a475f5 lukehamburg
	$outgoing_num_tcp = isset($unboundcfg['outgoing_num_tcp']) ? $unboundcfg['outgoing_num_tcp'] : "10";
343
	$incoming_num_tcp = isset($unboundcfg['incoming_num_tcp']) ? $unboundcfg['incoming_num_tcp'] : "10";
344 09d529a6 Viktor G
	if (empty($unboundcfg['edns_buffer_size']) || ($unboundcfg['edns_buffer_size'] == 'auto')) {
345
		$edns_buffer_size = unbound_auto_ednsbufsize();
346
	} else {
347
		$edns_buffer_size = $unboundcfg['edns_buffer_size'];
348
	}
349 932711c7 Matt Smith
	$num_queries_per_thread = (!empty($unboundcfg['num_queries_per_thread'])) ? $unboundcfg['num_queries_per_thread'] : "4096";
350
	$jostle_timeout = (!empty($unboundcfg['jostle_timeout'])) ? $unboundcfg['jostle_timeout'] : "200";
351
	$cache_max_ttl = (!empty($unboundcfg['cache_max_ttl'])) ? $unboundcfg['cache_max_ttl'] : "86400";
352
	$cache_min_ttl = (!empty($unboundcfg['cache_min_ttl'])) ? $unboundcfg['cache_min_ttl'] : "0";
353
	$infra_host_ttl = (!empty($unboundcfg['infra_host_ttl'])) ? $unboundcfg['infra_host_ttl'] : "900";
354
	$infra_cache_numhosts = (!empty($unboundcfg['infra_cache_numhosts'])) ? $unboundcfg['infra_cache_numhosts'] : "10000";
355
	$unwanted_reply_threshold = (!empty($unboundcfg['unwanted_reply_threshold'])) ? $unboundcfg['unwanted_reply_threshold'] : "0";
356 751533a2 Phil Davis
	if ($unwanted_reply_threshold == "disabled") {
357 b9608ab6 Phil Davis
		$unwanted_reply_threshold = "0";
358 751533a2 Phil Davis
	}
359 932711c7 Matt Smith
	$msg_cache_size = (!empty($unboundcfg['msgcachesize'])) ? $unboundcfg['msgcachesize'] : "4";
360
	$verbosity = isset($unboundcfg['log_verbosity']) ? $unboundcfg['log_verbosity'] : 1;
361
	$use_caps = isset($unboundcfg['use_caps']) ? "yes" : "no";
362 fe9d4894 Renato Botelho
363 203b1110 Lorenz Schori
	if (isset($unboundcfg['regovpnclients'])) {
364
		$openvpn_clients_conf .=<<<EOD
365
# OpenVPN client entries
366
include: {$g['unbound_chroot_path']}{$cfgsubdir}/openvpn.*.conf
367
EOD;
368
	} else {
369
		$openvpn_clients_conf = '';
370 c3b39cc4 Viktor G
		unlink_if_exists("{$g['unbound_chroot_path']}{$cfgsubdir}/openvpn.*.conf");
371 203b1110 Lorenz Schori
	}
372
373 a110a0cb Phil Davis
	// Set up forwarding if it is configured
374 932711c7 Matt Smith
	if (isset($unboundcfg['forwarding'])) {
375 f0c51530 jim-p
		$dnsservers = get_dns_nameservers(false, true);
376 fe9d4894 Renato Botelho
		if (!empty($dnsservers)) {
377
			$forward_conf .=<<<EOD
378 75e6d1b2 Warren Baker
# Forwarding
379 be5aa310 Warren Baker
forward-zone:
380 fe9d4894 Renato Botelho
	name: "."
381 be5aa310 Warren Baker
382
EOD;
383 cd738219 jim-p
			if (isset($unboundcfg['forward_tls_upstream'])) {
384
				$forward_conf .= "\tforward-tls-upstream: yes\n";
385
			}
386 7e8bfed2 jim-p
387
			/* Build DNS server hostname list. See https://redmine.pfsense.org/issues/8602 */
388
			$dns_hostnames = array();
389
			$dnshost_counter = 1;
390
			while (isset($config["system"]["dns{$dnshost_counter}host"])) {
391
				$pconfig_dnshost_counter = $dnshost_counter - 1;
392
				if (!empty($config["system"]["dns{$dnshost_counter}host"]) &&
393
				    isset($config["system"]["dnsserver"][$pconfig_dnshost_counter]))
394
				$dns_hostnames[$config["system"]["dnsserver"][$pconfig_dnshost_counter]] = $config["system"]["dns{$dnshost_counter}host"];
395
				$dnshost_counter++;
396
			}
397
398 751533a2 Phil Davis
			foreach ($dnsservers as $dnsserver) {
399 7e8bfed2 jim-p
				$fwdport = "";
400
				$fwdhost = "";
401 84588e00 Chris Buechler
				if (is_ipaddr($dnsserver) && !ip_in_subnet($dnsserver, "127.0.0.0/8")) {
402 7e8bfed2 jim-p
					if (isset($unboundcfg['forward_tls_upstream'])) {
403
						$fwdport = "@853";
404
						if (array_key_exists($dnsserver, $dns_hostnames)) {
405
							$fwdhost = "#{$dns_hostnames[$dnsserver]}";
406
						}
407
					}
408
					$forward_conf .= "\tforward-addr: {$dnsserver}{$fwdport}{$fwdhost}\n";
409 84588e00 Chris Buechler
				}
410 751533a2 Phil Davis
			}
411 fe9d4894 Renato Botelho
		}
412 751533a2 Phil Davis
	} else {
413 fe9d4894 Renato Botelho
		$forward_conf = "";
414 751533a2 Phil Davis
	}
415 be5aa310 Warren Baker
416 2597415b Chris Buechler
	// Size of the RRset cache == 2 * msg-cache-size per Unbound's recommendations
417
	$rrset_cache_size = $msg_cache_size * 2;
418
419 547e51b8 jim-p
	/* QNAME Minimization. https://redmine.pfsense.org/issues/8028
420
	 * Unbound uses the British style in the option name so the internal option
421
	 * name follows that, but the user-visible descriptions follow US English.
422
	 */
423
	$qname_min = "";
424
	if (isset($unboundcfg['qname-minimisation'])) {
425
		$qname_min = "qname-minimisation: yes\n";
426
		if (isset($unboundcfg['qname-minimisation-strict'])) {
427
			$qname_min .= "qname-minimisation-strict: yes\n";
428
		}
429
	}
430
431 241c4b58 BBcan177
	$python_module = '';
432
	if (isset($unboundcfg['python']) && !empty($unboundcfg['python_script'])) {
433
		$python_path = '';
434
		if (!empty($cfgsubdir)) {
435
			$python_path = "{$g['unbound_chroot_path']}{$cfgsubdir}/";
436
		}
437
		$python_module = "\n# Python Module\npython:\npython-script: {$python_path}{$unboundcfg['python_script']}.py";
438
	}
439
440 fe9d4894 Renato Botelho
	$unboundconf = <<<EOD
441 f20afeb6 Warren Baker
##########################
442
# Unbound Configuration
443
##########################
444
445
##
446
# Server configuration
447
##
448
server:
449 984abd66 Phil Davis
{$reverse_zones}
450 f20afeb6 Warren Baker
chroot: {$g['unbound_chroot_path']}
451
username: "unbound"
452 56a87b19 Warren Baker
directory: "{$g['unbound_chroot_path']}"
453 f20afeb6 Warren Baker
pidfile: "/var/run/unbound.pid"
454
use-syslog: yes
455 d12889b0 Warren Baker
port: {$port}
456 56a87b19 Warren Baker
verbosity: {$verbosity}
457 b9608ab6 Phil Davis
hide-identity: {$hide_identity}
458
hide-version: {$hide_version}
459 5c7c369f Chris Buechler
harden-glue: yes
460 f20afeb6 Warren Baker
do-ip4: yes
461 d2ec5844 stilez
do-ip6: {$ipv6_allow}
462 f20afeb6 Warren Baker
do-udp: yes
463
do-tcp: yes
464
do-daemonize: yes
465
module-config: "{$module_config}"
466 b9608ab6 Phil Davis
unwanted-reply-threshold: {$unwanted_reply_threshold}
467
num-queries-per-thread: {$num_queries_per_thread}
468
jostle-timeout: {$jostle_timeout}
469
infra-host-ttl: {$infra_host_ttl}
470
infra-cache-numhosts: {$infra_cache_numhosts}
471
outgoing-num-tcp: {$outgoing_num_tcp}
472
incoming-num-tcp: {$incoming_num_tcp}
473
edns-buffer-size: {$edns_buffer_size}
474 56a87b19 Warren Baker
cache-max-ttl: {$cache_max_ttl}
475
cache-min-ttl: {$cache_min_ttl}
476 b9608ab6 Phil Davis
harden-dnssec-stripped: {$harden_dnssec_stripped}
477
msg-cache-size: {$msg_cache_size}m
478 2597415b Chris Buechler
rrset-cache-size: {$rrset_cache_size}m
479 547e51b8 jim-p
{$qname_min}
480 f20afeb6 Warren Baker
{$optimization['number_threads']}
481
{$optimization['msg_cache_slabs']}
482
{$optimization['rrset_cache_slabs']}
483
{$optimization['infra_cache_slabs']}
484
{$optimization['key_cache_slabs']}
485 2cbcc256 Warren Baker
outgoing-range: 4096
486 f20afeb6 Warren Baker
{$optimization['so_rcvbuf']}
487
{$anchor_file}
488 56a87b19 Warren Baker
prefetch: {$prefetch}
489
prefetch-key: {$prefetch_key}
490 a771a6ae Warren Baker
use-caps-for-id: {$use_caps}
491 84ec58b7 marjohn56
serve-expired: {$dns_record_cache}
492 7e9d72cf Viktor Gurov
aggressive-nsec: {$aggressivensec}
493 f20afeb6 Warren Baker
# Statistics
494
{$statistics}
495 7e8bfed2 jim-p
# TLS Configuration
496
{$tlsconfig}
497 f20afeb6 Warren Baker
# Interface IP(s) to bind to
498 1fa69c27 jim-p
{$bindintcfg}
499 6374fb57 Warren Baker
{$outgoingints}
500 f20afeb6 Warren Baker
# DNS Rebinding
501
{$private_addr}
502
{$private_domains}
503 dc104520 Viktor G
{$dns64_conf}
504 f20afeb6 Warren Baker
505 4e8e8cc8 Warren Baker
# Access lists
506 1548bd35 Phil Davis
include: {$g['unbound_chroot_path']}{$cfgsubdir}/access_lists.conf
507 4e8e8cc8 Warren Baker
508 f20afeb6 Warren Baker
# Static host entries
509 1548bd35 Phil Davis
include: {$g['unbound_chroot_path']}{$cfgsubdir}/host_entries.conf
510 f20afeb6 Warren Baker
511 b3977493 Renato Botelho
# dhcp lease entries
512 1548bd35 Phil Davis
include: {$g['unbound_chroot_path']}{$cfgsubdir}/dhcpleases_entries.conf
513 b3977493 Renato Botelho
514 203b1110 Lorenz Schori
{$openvpn_clients_conf}
515 0cc17a06 Lorenz Schori
516 f20afeb6 Warren Baker
# Domain overrides
517 1548bd35 Phil Davis
include: {$g['unbound_chroot_path']}{$cfgsubdir}/domainoverrides.conf
518 be5aa310 Warren Baker
{$forward_conf}
519
520 f20afeb6 Warren Baker
{$custom_options}
521
522
###
523
# Remote Control Config
524
###
525 1548bd35 Phil Davis
include: {$g['unbound_chroot_path']}{$cfgsubdir}/remotecontrol.conf
526 241c4b58 BBcan177
{$python_module}
527 f20afeb6 Warren Baker
528
EOD;
529
530 932711c7 Matt Smith
	return $unboundconf;
531 f20afeb6 Warren Baker
}
532
533 1548bd35 Phil Davis
function unbound_remote_control_setup($cfgsubdir = "") {
534 fe9d4894 Renato Botelho
	global $g;
535 f20afeb6 Warren Baker
536 4b70a200 jim-p
	if (!file_exists("{$g['unbound_chroot_path']}{$cfgsubdir}/remotecontrol.conf") ||
537
	    (filesize("{$g['unbound_chroot_path']}{$cfgsubdir}/remotecontrol.conf") == 0) ||
538
	    !file_exists("{$g['unbound_chroot_path']}{$cfgsubdir}/unbound_control.key")) {
539 fe9d4894 Renato Botelho
		$remotcfg = <<<EOF
540 f20afeb6 Warren Baker
remote-control:
541 fe9d4894 Renato Botelho
	control-enable: yes
542
	control-interface: 127.0.0.1
543
	control-port: 953
544 1548bd35 Phil Davis
	server-key-file: "{$g['unbound_chroot_path']}{$cfgsubdir}/unbound_server.key"
545
	server-cert-file: "{$g['unbound_chroot_path']}{$cfgsubdir}/unbound_server.pem"
546
	control-key-file: "{$g['unbound_chroot_path']}{$cfgsubdir}/unbound_control.key"
547
	control-cert-file: "{$g['unbound_chroot_path']}{$cfgsubdir}/unbound_control.pem"
548 56a87b19 Warren Baker
549 f20afeb6 Warren Baker
EOF;
550
551 1548bd35 Phil Davis
		create_unbound_chroot_path($cfgsubdir);
552
		file_put_contents("{$g['unbound_chroot_path']}{$cfgsubdir}/remotecontrol.conf", $remotcfg);
553 f20afeb6 Warren Baker
554 fe9d4894 Renato Botelho
		// Generate our keys
555 1548bd35 Phil Davis
		do_as_unbound_user("unbound-control-setup", $cfgsubdir);
556 f20afeb6 Warren Baker
557 fe9d4894 Renato Botelho
	}
558 56a87b19 Warren Baker
}
559 f20afeb6 Warren Baker
560
function sync_unbound_service() {
561 fe9d4894 Renato Botelho
	global $config, $g;
562
563 e318d592 Phil Davis
	create_unbound_chroot_path();
564 fe9d4894 Renato Botelho
565
	// Configure our Unbound service
566
	do_as_unbound_user("unbound-anchor");
567
	unbound_remote_control_setup();
568
	unbound_generate_config();
569
	do_as_unbound_user("start");
570
	require_once("service-utils.inc");
571 751533a2 Phil Davis
	if (is_service_running("unbound")) {
572 fe9d4894 Renato Botelho
		do_as_unbound_user("restore_cache");
573 751533a2 Phil Davis
	}
574 f20afeb6 Warren Baker
575
}
576
577
function unbound_acl_id_used($id) {
578 fe9d4894 Renato Botelho
	global $config;
579 f20afeb6 Warren Baker
580 751533a2 Phil Davis
	if (is_array($config['unbound']['acls'])) {
581
		foreach ($config['unbound']['acls'] as & $acls) {
582
			if ($id == $acls['aclid']) {
583 fe9d4894 Renato Botelho
				return true;
584 751533a2 Phil Davis
			}
585
		}
586
	}
587 f20afeb6 Warren Baker
588 fe9d4894 Renato Botelho
	return false;
589 f20afeb6 Warren Baker
}
590
591
function unbound_get_next_id() {
592 fe9d4894 Renato Botelho
	$aclid = 0;
593 751533a2 Phil Davis
	while (unbound_acl_id_used($aclid)) {
594 fe9d4894 Renato Botelho
		$aclid++;
595 751533a2 Phil Davis
	}
596 fe9d4894 Renato Botelho
	return $aclid;
597 f20afeb6 Warren Baker
}
598
599
// Execute commands as the user unbound
600 1548bd35 Phil Davis
function do_as_unbound_user($cmd, $param1 = "") {
601 fe9d4894 Renato Botelho
	global $g;
602
603
	switch ($cmd) {
604 751533a2 Phil Davis
		case "start":
605
			mwexec("/usr/local/sbin/unbound -c {$g['unbound_chroot_path']}/unbound.conf");
606
			break;
607
		case "stop":
608 495bfb5d Viktor G
			mwexec("/usr/bin/su -m unbound -c '/usr/local/sbin/unbound-control -c {$g['unbound_chroot_path']}/unbound.conf stop'", true);
609 751533a2 Phil Davis
			break;
610
		case "reload":
611 495bfb5d Viktor G
			mwexec("/usr/bin/su -m unbound -c '/usr/local/sbin/unbound-control -c {$g['unbound_chroot_path']}/unbound.conf reload'", true);
612 751533a2 Phil Davis
			break;
613
		case "unbound-anchor":
614 1548bd35 Phil Davis
			$root_key_file = "{$g['unbound_chroot_path']}{$param1}/root.key";
615 4eeb2809 Chris Buechler
			// sanity check root.key because unbound-anchor will fail without manual removal otherwise. redmine #5334
616 1548bd35 Phil Davis
			if (file_exists($root_key_file)) {
617
				$rootkeycheck = mwexec("/usr/bin/grep 'autotrust trust anchor file' {$root_key_file}", true);
618 4eeb2809 Chris Buechler
				if ($rootkeycheck != "0") {
619 1548bd35 Phil Davis
					log_error("Unbound {$root_key_file} file is corrupt, removing and recreating.");
620
					unlink_if_exists($root_key_file);
621 4eeb2809 Chris Buechler
				}
622
			}
623 495bfb5d Viktor G
			mwexec("/usr/bin/su -m unbound -c '/usr/local/sbin/unbound-anchor -a {$root_key_file}'", true);
624 1548bd35 Phil Davis
			// Only sync the file if this is the real (default) one, not a test one.
625
			if ($param1 == "") {
626 c5663bf5 Renato Botelho
				//pfSense_fsync($root_key_file);
627 1548bd35 Phil Davis
			}
628 751533a2 Phil Davis
			break;
629
		case "unbound-control-setup":
630 495bfb5d Viktor G
			mwexec("/usr/bin/su -m unbound -c '/usr/local/sbin/unbound-control-setup -d {$g['unbound_chroot_path']}{$param1}'", true);
631 751533a2 Phil Davis
			break;
632
		default:
633
			break;
634 fe9d4894 Renato Botelho
	}
635 f20afeb6 Warren Baker
}
636
637 1548bd35 Phil Davis
function unbound_add_domain_overrides($pvt_rev="", $cfgsubdir = "") {
638 fe9d4894 Renato Botelho
	global $config, $g;
639
640
	$domains = $config['unbound']['domainoverrides'];
641
642
	$sorted_domains = msort($domains, "domain");
643
	$result = array();
644 f39ba24b jim-p
	$tls_domains = array();
645 7e8bfed2 jim-p
	$tls_hostnames = array();
646 751533a2 Phil Davis
	foreach ($sorted_domains as $domain) {
647 fe9d4894 Renato Botelho
		$domain_key = current($domain);
648 751533a2 Phil Davis
		if (!isset($result[$domain_key])) {
649 fe9d4894 Renato Botelho
			$result[$domain_key] = array();
650 751533a2 Phil Davis
		}
651 fe9d4894 Renato Botelho
		$result[$domain_key][] = $domain['ip'];
652 f39ba24b jim-p
		/* If any entry for a domain has TLS set, it will be active for all entries. */
653
		if (isset($domain['forward_tls_upstream'])) {
654
			$tls_domains[] = $domain_key;
655 7e8bfed2 jim-p
			$tls_hostnames[$domain['ip']] = $domain['tls_hostname'];
656 f39ba24b jim-p
		}
657 fe9d4894 Renato Botelho
	}
658
659
	// Domain overrides that have multiple entries need multiple stub-addr: added
660
	$domain_entries = "";
661 751533a2 Phil Davis
	foreach ($result as $domain=>$ips) {
662 984abd66 Phil Davis
		if ($pvt_rev == "private") {
663 fe9d4894 Renato Botelho
			$domain_entries .= "private-domain: \"$domain\"\n";
664
			$domain_entries .= "domain-insecure: \"$domain\"\n";
665 984abd66 Phil Davis
		} else if ($pvt_rev == "reverse") {
666 086cf944 Phil Davis
			if ((substr($domain, -14) == ".in-addr.arpa.") || (substr($domain, -13) == ".in-addr.arpa")) {
667 984abd66 Phil Davis
				$domain_entries .= "local-zone: \"$domain\" typetransparent\n";
668
			}
669 fe9d4894 Renato Botelho
		} else {
670 7e8bfed2 jim-p
			$use_tls = in_array($domain, $tls_domains);
671 0bde07b7 Chris Buechler
			$domain_entries .= "forward-zone:\n";
672 fe9d4894 Renato Botelho
			$domain_entries .= "\tname: \"$domain\"\n";
673 f39ba24b jim-p
			$fwdport = "";
674
			/* Enable TLS forwarding for this domain if needed. */
675 7e8bfed2 jim-p
			if ($use_tls) {
676 f39ba24b jim-p
				$domain_entries .= "\tforward-tls-upstream: yes\n";
677
				$fwdport = "@853";
678
			}
679 751533a2 Phil Davis
			foreach ($ips as $ip) {
680 7e8bfed2 jim-p
				$fwdhost = "";
681 f39ba24b jim-p
				/* If an IP address already contains a port specification, do not add another. */
682
				if (strstr($ip, '@') !== false) {
683
					$fwdport = "";
684
				}
685 7e8bfed2 jim-p
				if ($use_tls && array_key_exists($ip, $tls_hostnames)) {
686
					$fwdhost = "#{$tls_hostnames[$ip]}";
687
				}
688
				$domain_entries .= "\tforward-addr: {$ip}{$fwdport}{$fwdhost}\n";
689 751533a2 Phil Davis
			}
690 fe9d4894 Renato Botelho
		}
691
	}
692
693 751533a2 Phil Davis
	if ($pvt_rev != "") {
694 fe9d4894 Renato Botelho
		return $domain_entries;
695 751533a2 Phil Davis
	} else {
696 1548bd35 Phil Davis
		create_unbound_chroot_path($cfgsubdir);
697
		file_put_contents("{$g['unbound_chroot_path']}{$cfgsubdir}/domainoverrides.conf", $domain_entries);
698 e318d592 Phil Davis
	}
699 f20afeb6 Warren Baker
}
700
701 2c3b9ac5 jim-p
function unbound_generate_zone_data($domain, $hosts, &$added_ptr, $zone_type = "transparent", $write_domain_zone_declaration = false, $always_add_short_names = false) {
702 4541f84d jim-p
	global $config;
703 2c3b9ac5 jim-p
	if ($write_domain_zone_declaration) {
704 4541f84d jim-p
		$zone_data = "local-zone: \"{$domain}.\" {$zone_type}\n";
705
	} else {
706
		$zone_data = "";
707 49d9b45f Robbert Rijkse
	}
708
	foreach ($hosts as $host) {
709
		if (is_ipaddrv4($host['ipaddr'])) {
710
			$type = 'A';
711
		} else if (is_ipaddrv6($host['ipaddr'])) {
712
			$type = 'AAAA';
713
		} else {
714
			continue;
715
		}
716
		if (!$added_ptr[$host['ipaddr']]) {
717 4541f84d jim-p
			$zone_data .= "local-data-ptr: \"{$host['ipaddr']} {$host['fqdn']}\"\n";
718 49d9b45f Robbert Rijkse
			$added_ptr[$host['ipaddr']] = true;
719 06266c34 Lorenz Schori
		}
720 4541f84d jim-p
		/* For the system localhost entry, write an entry for just the hostname. */
721
		if ((($host['name'] == "localhost") && ($domain == $config['system']['domain'])) || $always_add_short_names) {
722
			$zone_data .= "local-data: \"{$host['name']}. {$type} {$host['ipaddr']}\"\n";
723
		}
724
		/* Redirect zones must have a zone declaration that matches the
725
		 * local-data record exactly, it cannot have entries "under" the
726
		 * domain.
727
		 */
728
		if ($zone_type == "redirect") {
729
			$zone_data .= "local-zone: \"{$host['fqdn']}.\" {$zone_type}\n";;
730
		}
731
		$zone_data .= "local-data: \"{$host['fqdn']}. {$type} {$host['ipaddr']}\"\n";
732
	}
733
	return $zone_data;
734
}
735
736
function unbound_add_host_entries($cfgsubdir = "") {
737
	global $config, $g;
738
739
	$hosts = system_hosts_entries($config['unbound']);
740
741
	/* Pass 1: Build domain list and hosts inside domains */
742
	$hosts_by_domain = array();
743
	foreach ($hosts as $host) {
744
		if (!array_key_exists($host['domain'], $hosts_by_domain)) {
745
			$hosts_by_domain[$host['domain']] = array();
746
		}
747
		$hosts_by_domain[$host['domain']][] = $host;
748
	}
749
750
	$added_ptr = array();
751
	/* Build local zone data */
752
	// Check if auto add host entries is not set
753
	$system_domain_local_zone_type = "transparent";
754
	if (!isset($config['unbound']['disable_auto_added_host_entries'])) {
755
		// Make sure the config setting is a valid unbound local zone type.  If not use "transparent".
756
		if (array_key_exists($config['unbound']['system_domain_local_zone_type'], unbound_local_zone_types())) {
757
			$system_domain_local_zone_type = $config['unbound']['system_domain_local_zone_type'];
758
		}
759
	}
760
	/* Add entries for the system domain before all others */
761
	if (array_key_exists($config['system']['domain'], $hosts_by_domain)) {
762
		$unbound_entries .= unbound_generate_zone_data($config['system']['domain'],
763
					$hosts_by_domain[$config['system']['domain']],
764
					$added_ptr,
765
					$system_domain_local_zone_type,
766
					true);
767
		/* Unset this so it isn't processed again by the loop below. */
768
		unset($hosts_by_domain[$config['system']['domain']]);
769
	}
770
771
	/* Build zone data for other domain */
772
	foreach ($hosts_by_domain as $domain => $hosts) {
773
		$unbound_entries .= unbound_generate_zone_data($domain,
774
					$hosts,
775
					$added_ptr,
776
					"transparent",
777
					false,
778
					isset($config['unbound']['always_add_short_names']));
779 fe9d4894 Renato Botelho
	}
780
781
	// Write out entries
782 1548bd35 Phil Davis
	create_unbound_chroot_path($cfgsubdir);
783
	file_put_contents("{$g['unbound_chroot_path']}{$cfgsubdir}/host_entries.conf", $unbound_entries);
784 b3977493 Renato Botelho
785
	/* dhcpleases will write to this config file, make sure it exists */
786 1548bd35 Phil Davis
	@touch("{$g['unbound_chroot_path']}{$cfgsubdir}/dhcpleases_entries.conf");
787 f20afeb6 Warren Baker
}
788
789 56a87b19 Warren Baker
function unbound_control($action) {
790 fe9d4894 Renato Botelho
	global $config, $g;
791
792
	$cache_dumpfile = "/var/tmp/unbound_cache";
793
794
	switch ($action) {
795
	case "start":
796
		// Start Unbound
797
		if ($config['unbound']['enable'] == "on") {
798 751533a2 Phil Davis
			if (!is_service_running("unbound")) {
799 fe9d4894 Renato Botelho
				do_as_unbound_user("start");
800 751533a2 Phil Davis
			}
801 fe9d4894 Renato Botelho
		}
802
		break;
803
	case "stop":
804 751533a2 Phil Davis
		if ($config['unbound']['enable'] == "on") {
805 fe9d4894 Renato Botelho
			do_as_unbound_user("stop");
806 751533a2 Phil Davis
		}
807 fe9d4894 Renato Botelho
		break;
808
	case "reload":
809 751533a2 Phil Davis
		if ($config['unbound']['enable'] == "on") {
810 fe9d4894 Renato Botelho
			do_as_unbound_user("reload");
811 751533a2 Phil Davis
		}
812 fe9d4894 Renato Botelho
		break;
813
	case "dump_cache":
814
		// Dump Unbound's Cache
815 751533a2 Phil Davis
		if ($config['unbound']['dumpcache'] == "on") {
816 fe9d4894 Renato Botelho
			do_as_unbound_user("dump_cache");
817 751533a2 Phil Davis
		}
818 fe9d4894 Renato Botelho
		break;
819
	case "restore_cache":
820
		// Restore Unbound's Cache
821
		if ((is_service_running("unbound")) && ($config['unbound']['dumpcache'] == "on")) {
822 751533a2 Phil Davis
			if (file_exists($cache_dumpfile) && filesize($cache_dumpfile) > 0) {
823 fe9d4894 Renato Botelho
				do_as_unbound_user("load_cache < /var/tmp/unbound_cache");
824 751533a2 Phil Davis
			}
825 fe9d4894 Renato Botelho
		}
826
		break;
827
	default:
828
		break;
829
830
	}
831 56a87b19 Warren Baker
}
832
833
// Generation of Unbound statistics
834
function unbound_statistics() {
835 fe9d4894 Renato Botelho
	global $config;
836
837
	if ($config['stats'] == "on") {
838
		$stats_interval = $config['unbound']['stats_interval'];
839
		$cumulative_stats = $config['cumulative_stats'];
840 751533a2 Phil Davis
		if ($config['extended_stats'] == "on") {
841 fe9d4894 Renato Botelho
			$extended_stats = "yes";
842 751533a2 Phil Davis
		} else {
843 fe9d4894 Renato Botelho
			$extended_stats = "no";
844 751533a2 Phil Davis
		}
845 fe9d4894 Renato Botelho
	} else {
846
		$stats_interval = "0";
847
		$cumulative_stats = "no";
848
		$extended_stats = "no";
849
	}
850
	/* XXX To do - add RRD graphs */
851
	$stats = <<<EOF
852 56a87b19 Warren Baker
# Unbound Statistics
853
statistics-interval: {$stats_interval}
854
extended-statistics: yes
855
statistics-cumulative: yes
856
857
EOF;
858
859 fe9d4894 Renato Botelho
	return $stats;
860 56a87b19 Warren Baker
}
861
862 8fccab67 Warren Baker
// Unbound Access lists
863 1548bd35 Phil Davis
function unbound_acls_config($cfgsubdir = "") {
864 fe9d4894 Renato Botelho
	global $g, $config;
865
866 f8f5ba1a Chris Buechler
	if (!isset($config['unbound']['disable_auto_added_access_control'])) {
867 0266efa6 doktornotor
		$aclcfg = "access-control: 127.0.0.1/32 allow_snoop\n";
868
		$aclcfg .= "access-control: ::1 allow_snoop\n";
869 f8f5ba1a Chris Buechler
		// Add our networks for active interfaces including localhost
870 8c2a5a73 Phil Davis
		if (!empty($config['unbound']['active_interface'])) {
871 f8f5ba1a Chris Buechler
			$active_interfaces = array_flip(explode(",", $config['unbound']['active_interface']));
872 751533a2 Phil Davis
			if (in_array("all", $active_interfaces)) {
873 80075b9e Chris Buechler
				$active_interfaces = get_configured_interface_with_descr();
874 751533a2 Phil Davis
			}
875
		} else {
876 f8f5ba1a Chris Buechler
			$active_interfaces = get_configured_interface_with_descr();
877 751533a2 Phil Davis
		}
878
879
		foreach ($active_interfaces as $ubif => $ifdesc) {
880 f8f5ba1a Chris Buechler
			$ifip = get_interface_ip($ubif);
881
			if (is_ipaddrv4($ifip)) {
882
				// IPv4 is handled via NAT networks below
883
			}
884
			$ifip = get_interface_ipv6($ubif);
885
			if (is_ipaddrv6($ifip)) {
886 f302a333 Jean Cyr
				if (!is_linklocal($ifip)) {
887
					$subnet_bits = get_interface_subnetv6($ubif);
888
					$subnet_ip = gen_subnetv6($ifip, $subnet_bits);
889 751533a2 Phil Davis
					// only add LAN-type interfaces
890
					if (!interface_has_gateway($ubif)) {
891 f302a333 Jean Cyr
						$aclcfg .= "access-control: {$subnet_ip}/{$subnet_bits} allow\n";
892 751533a2 Phil Davis
					}
893 f302a333 Jean Cyr
				}
894 f8f5ba1a Chris Buechler
				// add for IPv6 static routes to local networks
895
				// for safety, we include only routes reachable on an interface with no
896 751533a2 Phil Davis
				// gateway specified - read: not an Internet connection.
897 cf08b49e Phil Davis
				$static_routes = get_staticroutes(false, false, true); // Parameter 3 returnenabledroutesonly
898 f8f5ba1a Chris Buechler
				foreach ($static_routes as $route) {
899
					if ((lookup_gateway_interface_by_name($route['gateway']) == $ubif) && !interface_has_gateway($ubif)) {
900
						// route is on this interface, interface doesn't have gateway, add it
901
						$aclcfg .= "access-control: {$route['network']} allow\n";
902
					}
903 e3045c51 Chris Buechler
				}
904
			}
905 fe9d4894 Renato Botelho
		}
906 751533a2 Phil Davis
907 79eef195 Viktor Gurov
		// OpenVPN IPv6 Tunnel Networks
908
		foreach (array('openvpn-client', 'openvpn-server') as $ovpnentry) {
909
			if (is_array($config['openvpn'][$ovpnentry])) {
910
				foreach ($config['openvpn'][$ovpnentry] as $ovpnent) {
911
					if (!isset($ovpnent['disable']) && !empty($ovpnent['tunnel_networkv6'])) {
912
						$aclcfg .= "access-control: {$ovpnent['tunnel_networkv6']} allow\n";
913
					}
914
				}
915
			}
916
		}
917
		// IPsec Mobile Virtual IPv6 Address Pool
918
		if ((isset($config['ipsec']['client']['enable'])) &&
919
		    (!empty($config['ipsec']['client']['pool_address_v6'])) &&
920
		    (!empty($config['ipsec']['client']['pool_netbits_v6']))) {
921
			$aclcfg .= "access-control: {$config['ipsec']['client']['pool_address_v6']}/{$config['ipsec']['client']['pool_netbits_v6']} allow\n";
922
		}
923
924 f8f5ba1a Chris Buechler
		// Generate IPv4 access-control entries using the same logic as automatic outbound NAT
925
		if (empty($FilterIflist)) {
926
			filter_generate_optcfg_array();
927
		}
928
		$natnetworks_array = array();
929
		$natnetworks_array = filter_nat_rules_automatic_tonathosts();
930
		foreach ($natnetworks_array as $allowednet) {
931 751533a2 Phil Davis
			$aclcfg .= "access-control: $allowednet allow \n";
932
		}
933 3bdf2a70 Chris Buechler
	}
934 fe9d4894 Renato Botelho
935
	// Configure the custom ACLs
936
	if (is_array($config['unbound']['acls'])) {
937 751533a2 Phil Davis
		foreach ($config['unbound']['acls'] as $unbound_acl) {
938 fe9d4894 Renato Botelho
			$aclcfg .= "#{$unbound_acl['aclname']}\n";
939 751533a2 Phil Davis
			foreach ($unbound_acl['row'] as $network) {
940
				if ($unbound_acl['aclaction'] == "allow snoop") {
941 fe9d4894 Renato Botelho
					$unbound_acl['aclaction'] = "allow_snoop";
942 6a827f69 doktornotor
				} elseif ($unbound_acl['aclaction'] == "deny nonlocal") {
943
					$unbound_acl['aclaction'] = "deny_non_local";
944
				} elseif ($unbound_acl['aclaction'] == "refuse nonlocal") {
945
					$unbound_acl['aclaction'] = "refuse_non_local";
946 751533a2 Phil Davis
				}
947 fe9d4894 Renato Botelho
				$aclcfg .= "access-control: {$network['acl_network']}/{$network['mask']} {$unbound_acl['aclaction']}\n";
948
			}
949
		}
950
	}
951
	// Write out Access list
952 1548bd35 Phil Davis
	create_unbound_chroot_path($cfgsubdir);
953
	file_put_contents("{$g['unbound_chroot_path']}{$cfgsubdir}/access_lists.conf", $aclcfg);
954 58d00e65 Warren Baker
955 8fccab67 Warren Baker
}
956
957 f6248774 Warren Baker
// Generate hosts and reload services
958
function unbound_hosts_generate() {
959 fe9d4894 Renato Botelho
	// Generate our hosts file
960
	unbound_add_host_entries();
961 f6248774 Warren Baker
962 fe9d4894 Renato Botelho
	// Reload our service to read the updates
963
	unbound_control("reload");
964 f6248774 Warren Baker
}
965
966 9a83872f NOYB
// Array of valid unbound local zone types
967
function unbound_local_zone_types() {
968
	return array(
969
		"deny" => gettext("Deny"),
970
		"refuse" => gettext("Refuse"),
971
		"static" => gettext("Static"),
972
		"transparent" => gettext("Transparent"),
973
		"typetransparent" => gettext("Type Transparent"),
974
		"redirect" => gettext("Redirect"),
975
		"inform" => gettext("Inform"),
976
		"inform_deny" => gettext("Inform Deny"),
977
		"nodefault" => gettext("No Default")
978
	);
979
}
980
981 09d529a6 Viktor G
// Autoconfig EDNS buffer size
982
function unbound_auto_ednsbufsize() {
983
	global $config;
984
985
	$active_ipv6_inf = false;
986
	if ($config['unbound']['active_interface'] != 'all') {
987
		$active_interfaces = explode(",", $config['unbound']['active_interface']);
988
	} else {
989
		$active_interfaces = get_configured_interface_list();
990
	}
991
992
	$min_mtu = get_interface_mtu(get_real_interface($active_interfaces[0]));
993
	foreach ($active_interfaces as $ubif) {
994
		$ubif_mtu = get_interface_mtu(get_real_interface($ubif));
995
		if (get_interface_ipv6($ubif)) {
996
			$active_ipv6_inf = true;
997
		}
998
		if ($ubif_mtu < $min_mtu) {
999
			$min_mtu = $ubif_mtu;
1000
		}
1001
	}
1002
1003
	// maximum IPv4 + UDP header = 68 bytes
1004
	$min_mtu = $min_mtu - 68;
1005
1006
	if (($min_mtu < 1232) && $active_ipv6_inf) {
1007
		$min_mtu = 1232;
1008
	} elseif ($min_mtu < 512) {
1009
		$min_mtu = 512;
1010
	}	
1011
1012
	return $min_mtu;
1013
}
1014
1015 3f0c20c3 Renato Botelho
?>