Project

General

Profile

Download (21.4 KB) Statistics
| Branch: | Tag: | Revision:
1 f20afeb6 Warren Baker
<?php
2
/*
3 fe9d4894 Renato Botelho
	unbound.inc
4
	part of the pfSense project (https://www.pfsense.org)
5 a771a6ae Warren Baker
	Copyright (C) 2015 Warren Baker <warren@percol8.co.za>
6 fe9d4894 Renato Botelho
	All rights reserved.
7
8
	Redistribution and use in source and binary forms, with or without
9
	modification, are permitted provided that the following conditions are met:
10
11
	1. Redistributions of source code must retain the above copyright notice,
12
	   this list of conditions and the following disclaimer.
13
14
	2. Redistributions in binary form must reproduce the above copyright
15
	   notice, this list of conditions and the following disclaimer in the
16
	   documentation and/or other materials provided with the distribution.
17
18
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
	POSSIBILITY OF SUCH DAMAGE.
28
29 3ba07784 Renato Botelho
	pfSense_BUILDER_BINARIES:   /usr/local/sbin/unbound  /usr/local/sbin/unbound-anchor    /usr/local/sbin/unbound-checkconf
30
	pfSense_BUILDER_BINARIES:   /usr/local/sbin/unbound-control    /usr/local/sbin/unbound-control-setup
31 fe9d4894 Renato Botelho
	pfSense_MODULE: unbound
32 f20afeb6 Warren Baker
*/
33
34
/* include all configuration functions */
35
require_once("config.inc");
36
require_once("functions.inc");
37 3bdf2a70 Chris Buechler
require_once("filter.inc");
38
require_once("shaper.inc");
39 f20afeb6 Warren Baker
40 e318d592 Phil Davis
function create_unbound_chroot_path() {
41
	global $config, $g;
42
43
	// Configure chroot
44
	if (!is_dir($g['unbound_chroot_path'])) {
45
		mkdir($g['unbound_chroot_path']);
46
		chown($g['unbound_chroot_path'], "unbound");
47
		chgrp($g['unbound_chroot_path'], "unbound");
48
	}
49
50
}
51
52 f20afeb6 Warren Baker
/* Optimize Unbound for environment */
53
function unbound_optimization() {
54 fe9d4894 Renato Botelho
	global $config;
55
56
	$optimization_settings = array();
57
58
	/* 
59
	 * Set the number of threads equal to number of CPUs.
60
	 * Use 1 to disable threading, if for some reason this sysctl fails.
61
	 */
62
	$numprocs = intval(get_single_sysctl('kern.smp.cpus'));
63 46762efe Warren Baker
	if ($numprocs > 1) {
64 fe9d4894 Renato Botelho
		$optimization['number_threads'] = "num-threads: {$numprocs}";
65 46762efe Warren Baker
		$optimize_num = pow(2,floor(log($numprocs,2)));
66
	} else {
67 fe9d4894 Renato Botelho
		$optimization['number_threads'] = "num-threads: 1";
68 46762efe Warren Baker
		$optimize_num = 4;
69
	}
70 fe9d4894 Renato Botelho
71
	// Slabs to help reduce lock contention.
72 46762efe Warren Baker
	$optimization['msg_cache_slabs'] = "msg-cache-slabs: {$optimize_num}";
73
	$optimization['rrset_cache_slabs'] = "rrset-cache-slabs: {$optimize_num}";
74
	$optimization['infra_cache_slabs'] = "infra-cache-slabs: {$optimize_num}";
75
	$optimization['key_cache_slabs'] = "key-cache-slabs: {$optimize_num}";
76 fe9d4894 Renato Botelho
77
	/*
78
	 * Larger socket buffer for busy servers
79
	 * Check that it is set to 4MB (by default the OS has it configured to 4MB)
80
	 */
81 d87fcac9 Ermal
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
82
		foreach ($config['sysctl']['item'] as $tunable) {
83
			if ($tunable['tunable'] == 'kern.ipc.maxsockbuf') {
84 ad04bbbf Warren Baker
				$so = floor(($tunable['value']/1024/1024)-4);
85 d87fcac9 Ermal
				// Check to ensure that the number is not a negative
86 ad04bbbf Warren Baker
				if ($so >= 4) {
87
					// Limit to 32MB, users might set maxsockbuf very high for other reasons.
88 4708c6f0 Phil Davis
					// We do not want unbound to fail because of that.
89 ad04bbbf Warren Baker
					$so = min($so, 32);
90 d87fcac9 Ermal
					$optimization['so_rcvbuf'] = "so-rcvbuf: {$so}m";
91 ad04bbbf Warren Baker
				} else {
92 d87fcac9 Ermal
					unset($optimization['so_rcvbuf']);
93 ad04bbbf Warren Baker
				}
94 d87fcac9 Ermal
			}
95 fe9d4894 Renato Botelho
		}
96
	}
97
	// Safety check in case kern.ipc.maxsockbuf is not available.
98
	if (!isset($optimization['so_rcvbuf']))
99
		$optimization['so_rcvbuf'] = "#so-rcvbuf: 4m";
100
101
	return $optimization;
102 f20afeb6 Warren Baker
103
}
104
105
function unbound_generate_config() {
106 fe9d4894 Renato Botelho
	global $config, $g;
107
108
	// Setup optimization
109
	$optimization = unbound_optimization();
110
111
	// Setup DNSSEC support
112
	if (isset($config['unbound']['dnssec'])) {
113
		$module_config = "validator iterator";
114
		$anchor_file = "auto-trust-anchor-file: {$g['unbound_chroot_path']}/root.key";
115
	} else
116
		$module_config = "iterator";
117
118
	// Setup DNS Rebinding
119
	if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
120
		// Private-addresses for DNS Rebinding
121
		$private_addr = <<<EOF
122 f20afeb6 Warren Baker
# For DNS Rebinding prevention
123
private-address: 10.0.0.0/8
124
private-address: 172.16.0.0/12
125 c683f627 Chris Buechler
private-address: 169.254.0.0/16
126 f20afeb6 Warren Baker
private-address: 192.168.0.0/16
127
private-address: fd00::/8
128
private-address: fe80::/10
129
EOF;
130 fe9d4894 Renato Botelho
	}
131
132
	// Determine interfaces to run on
133
	$bindints = "";
134
	if (!empty($config['unbound']['active_interface'])) {
135
		$active_interfaces = explode(",", $config['unbound']['active_interface']);
136 b7960673 Chris Buechler
		if (in_array("all", $active_interfaces, true)) {
137
			$bindints .= "interface: 0.0.0.0\n";
138
			$bindints .= "interface: ::0\n";
139 f358fe3f Chris Buechler
			$bindints .= "interface-automatic: yes\n";
140 b7960673 Chris Buechler
		} else {
141
			foreach($active_interfaces as $ubif) {
142 a0e9e17d Chris Buechler
				if (is_ipaddr($ubif)) {
143
					//$bindints .= "interface: $ubif\n";  -- until redmine #4062 is fixed, then uncomment this. 
144
				} else {
145
					$intip = get_interface_ip($ubif);
146
					if (is_ipaddrv4($intip))
147
						$bindints .= "interface: $intip\n";
148
					$intip = get_interface_ipv6($ubif);
149
					if (is_ipaddrv6($intip))
150 ad62d077 Jean Cyr
						if (!is_linklocal($intip))  // skipping link local for the moment to not break people's configs: https://redmine.pfsense.org/issues/4062
151 a0e9e17d Chris Buechler
							$bindints .= "interface: $intip\n";
152
				}
153 b7960673 Chris Buechler
			}	
154 fe9d4894 Renato Botelho
		}
155
	} else {
156
		$bindints .= "interface: 0.0.0.0\n";
157
		$bindints .= "interface: ::0\n";
158
	}
159
160
	// Determine interfaces to run on
161
	$outgoingints = "";
162
	if (!empty($config['unbound']['outgoing_interface'])) {
163
		$outgoingints = "# Outgoing interfaces to be used\n";
164
		$outgoing_interfaces = explode(",", $config['unbound']['outgoing_interface']);
165
		foreach($outgoing_interfaces as $outif) {
166
			$outip = get_interface_ip($outif);
167
			if (!is_null($outip))
168
				$outgoingints .= "outgoing-interface: $outip\n";
169
			$outip = get_interface_ipv6($outif);
170
			if (!is_null($outip))
171
				$outgoingints .= "outgoing-interface: $outip\n";
172
		}
173
	}
174
175
	// Allow DNS Rebind for forwarded domains
176 984abd66 Phil Davis
	if (isset($config['unbound']['domainoverrides']) && is_array($config['unbound']['domainoverrides'])) {
177
		if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
178
			$private_domains = "# Set private domains in case authoritative name server returns a Private IP address\n";
179
			$private_domains .= unbound_add_domain_overrides("private");
180
		}
181
		$reverse_zones .= unbound_add_domain_overrides("reverse");
182 fe9d4894 Renato Botelho
	}
183
184
	// Configure static Host entries
185
	unbound_add_host_entries();
186
187
	// Configure Domain Overrides
188
	unbound_add_domain_overrides();
189
190
	// Configure Unbound statistics
191
	$statistics = unbound_statistics();
192
193
	// Configure Unbound access-lists
194
	unbound_acls_config();
195
196
	// Add custom Unbound options
197
	if ($config['unbound']['custom_options']) {
198 cfb5073f Renato Botelho
		$custom_options_source = explode("\n", base64_decode($config['unbound']['custom_options']));
199 b9608ab6 Phil Davis
		$custom_options = "# Unbound custom options\n";
200 b5acc797 Chris Buechler
		foreach ($custom_options_source as $ent)
201 b9608ab6 Phil Davis
			$custom_options .= $ent."\n";
202 fe9d4894 Renato Botelho
	}
203
204
	// Server configuration variables
205
	$port = (is_port($config['unbound']['port'])) ? $config['unbound']['port'] : "53";
206 b9608ab6 Phil Davis
	$hide_identity = isset($config['unbound']['hideidentity']) ? "yes" : "no";
207
	$hide_version = isset($config['unbound']['hideversion']) ? "yes" : "no";
208
	$harden_glue = isset($config['unbound']['hardenglue']) ? "yes" : "no";
209
	$harden_dnssec_stripped = isset($config['unbound']['dnssecstripped']) ? "yes" : "no";
210
	$prefetch = isset($config['unbound']['prefetch']) ? "yes" : "no";
211
	$prefetch_key = isset($config['unbound']['prefetchkey']) ? "yes" : "no";
212 fe9d4894 Renato Botelho
	$outgoing_num_tcp = (!empty($config['unbound']['outgoing_num_tcp'])) ? $config['unbound']['outgoing_num_tcp'] : "10";
213
	$incoming_num_tcp = (!empty($config['unbound']['incoming_num_tcp'])) ? $config['unbound']['incoming_num_tcp'] : "10";
214
	$edns_buffer_size = (!empty($config['unbound']['edns_buffer_size'])) ? $config['unbound']['edns_buffer_size'] : "4096";
215
	$num_queries_per_thread = (!empty($config['unbound']['num_queries_per_thread'])) ? $config['unbound']['num_queries_per_thread'] : "4096";
216
	$jostle_timeout = (!empty($config['unbound']['jostle_timeout'])) ? $config['unbound']['jostle_timeout'] : "200";
217
	$cache_max_ttl = (!empty($config['unbound']['cache_max_ttl'])) ? $config['unbound']['cache_max_ttl'] : "86400";
218
	$cache_min_ttl = (!empty($config['unbound']['cache_min_ttl'])) ? $config['unbound']['cache_min_ttl'] : "0";
219
	$infra_host_ttl = (!empty($config['unbound']['infra_host_ttl'])) ? $config['unbound']['infra_host_ttl'] : "900";
220
	$infra_cache_numhosts = (!empty($config['unbound']['infra_cache_numhosts'])) ? $config['unbound']['infra_cache_numhosts'] : "10000";
221
	$unwanted_reply_threshold = (!empty($config['unbound']['unwanted_reply_threshold'])) ? $config['unbound']['unwanted_reply_threshold'] : "0";
222 b9608ab6 Phil Davis
	if ($unwanted_reply_threshold == "disabled")
223
		$unwanted_reply_threshold = "0";
224
	$msg_cache_size = (!empty($config['unbound']['msgcachesize'])) ? $config['unbound']['msgcachesize'] : "4";
225
	$verbosity = isset($config['unbound']['log_verbosity']) ? $config['unbound']['log_verbosity'] : 1;
226 a771a6ae Warren Baker
	$use_caps = isset($config['unbound']['use_caps']) ? "yes" : "no";
227 fe9d4894 Renato Botelho
228
	// Set up forwarding if it configured
229
	if (isset($config['unbound']['forwarding'])) {
230
		$dnsservers = array();
231
		if (isset($config['system']['dnsallowoverride'])) {
232
			$ns = array_unique(get_nameservers());
233
			foreach($ns as $nameserver) {
234
				if ($nameserver)
235
					$dnsservers[] = $nameserver;
236
			}
237
		} else {
238
			$ns = array_unique(get_dns_servers());
239
			foreach($ns as $nameserver) {
240
				if ($nameserver)
241
					$dnsservers[] = $nameserver;
242
			}
243
		}
244
245
		if (!empty($dnsservers)) {
246
			$forward_conf .=<<<EOD
247 75e6d1b2 Warren Baker
# Forwarding
248 be5aa310 Warren Baker
forward-zone:
249 fe9d4894 Renato Botelho
	name: "."
250 be5aa310 Warren Baker
251
EOD;
252 fe9d4894 Renato Botelho
			foreach($dnsservers as $dnsserver)
253
				$forward_conf .= "\tforward-addr: $dnsserver\n";
254
		}
255
	} else
256
		$forward_conf = "";
257 be5aa310 Warren Baker
258 2597415b Chris Buechler
	// Size of the RRset cache == 2 * msg-cache-size per Unbound's recommendations
259
	$rrset_cache_size = $msg_cache_size * 2;
260
261 fe9d4894 Renato Botelho
	$unboundconf = <<<EOD
262 f20afeb6 Warren Baker
##########################
263
# Unbound Configuration
264
##########################
265
266
##
267
# Server configuration
268
##
269
server:
270 984abd66 Phil Davis
{$reverse_zones}
271 f20afeb6 Warren Baker
chroot: {$g['unbound_chroot_path']}
272
username: "unbound"
273 56a87b19 Warren Baker
directory: "{$g['unbound_chroot_path']}"
274 f20afeb6 Warren Baker
pidfile: "/var/run/unbound.pid"
275
use-syslog: yes
276 d12889b0 Warren Baker
port: {$port}
277 56a87b19 Warren Baker
verbosity: {$verbosity}
278 b9608ab6 Phil Davis
hide-identity: {$hide_identity}
279
hide-version: {$hide_version}
280
harden-glue: {$harden_glue}
281 f20afeb6 Warren Baker
do-ip4: yes
282
do-ip6: yes
283
do-udp: yes
284
do-tcp: yes
285
do-daemonize: yes
286
module-config: "{$module_config}"
287 b9608ab6 Phil Davis
unwanted-reply-threshold: {$unwanted_reply_threshold}
288
num-queries-per-thread: {$num_queries_per_thread}
289
jostle-timeout: {$jostle_timeout}
290
infra-host-ttl: {$infra_host_ttl}
291
infra-cache-numhosts: {$infra_cache_numhosts}
292
outgoing-num-tcp: {$outgoing_num_tcp}
293
incoming-num-tcp: {$incoming_num_tcp}
294
edns-buffer-size: {$edns_buffer_size}
295 56a87b19 Warren Baker
cache-max-ttl: {$cache_max_ttl}
296
cache-min-ttl: {$cache_min_ttl}
297 b9608ab6 Phil Davis
harden-dnssec-stripped: {$harden_dnssec_stripped}
298
msg-cache-size: {$msg_cache_size}m
299 2597415b Chris Buechler
rrset-cache-size: {$rrset_cache_size}m
300
301 f20afeb6 Warren Baker
{$optimization['number_threads']}
302
{$optimization['msg_cache_slabs']}
303
{$optimization['rrset_cache_slabs']}
304
{$optimization['infra_cache_slabs']}
305
{$optimization['key_cache_slabs']}
306 2cbcc256 Warren Baker
outgoing-range: 4096
307 f20afeb6 Warren Baker
{$optimization['so_rcvbuf']}
308
{$anchor_file}
309 56a87b19 Warren Baker
prefetch: {$prefetch}
310
prefetch-key: {$prefetch_key}
311 a771a6ae Warren Baker
use-caps-for-id: {$use_caps}
312 f20afeb6 Warren Baker
# Statistics
313
{$statistics}
314
# Interface IP(s) to bind to
315 16a3108f Warren Baker
{$bindints}
316 6374fb57 Warren Baker
{$outgoingints}
317 f20afeb6 Warren Baker
318
# DNS Rebinding
319
{$private_addr}
320
{$private_domains}
321
322 4e8e8cc8 Warren Baker
# Access lists
323
include: {$g['unbound_chroot_path']}/access_lists.conf
324
325 f20afeb6 Warren Baker
# Static host entries
326 56a87b19 Warren Baker
include: {$g['unbound_chroot_path']}/host_entries.conf
327 f20afeb6 Warren Baker
328 b3977493 Renato Botelho
# dhcp lease entries
329
include: {$g['unbound_chroot_path']}/dhcpleases_entries.conf
330
331 f20afeb6 Warren Baker
# Domain overrides
332 ae5bbb64 Warren Baker
include: {$g['unbound_chroot_path']}/domainoverrides.conf
333 be5aa310 Warren Baker
{$forward_conf}
334
335 f20afeb6 Warren Baker
{$custom_options}
336
337
###
338
# Remote Control Config
339
###
340 56a87b19 Warren Baker
include: {$g['unbound_chroot_path']}/remotecontrol.conf
341 f20afeb6 Warren Baker
342
EOD;
343
344 e318d592 Phil Davis
	create_unbound_chroot_path();
345 fe9d4894 Renato Botelho
	file_put_contents("{$g['unbound_chroot_path']}/unbound.conf", $unboundconf);
346 f20afeb6 Warren Baker
347 fe9d4894 Renato Botelho
	return 0;
348 f20afeb6 Warren Baker
}
349
350
function unbound_remote_control_setup() {
351 fe9d4894 Renato Botelho
	global $g;
352 f20afeb6 Warren Baker
353 fe9d4894 Renato Botelho
	if (!file_exists("{$g['unbound_chroot_path']}/remotecontrol.conf") || !file_exists("{$g['unbound_chroot_path']}/unbound_control.key")) {
354
		$remotcfg = <<<EOF
355 f20afeb6 Warren Baker
remote-control:
356 fe9d4894 Renato Botelho
	control-enable: yes
357
	control-interface: 127.0.0.1
358
	control-port: 953
359
	server-key-file: "{$g['unbound_chroot_path']}/unbound_server.key"
360
	server-cert-file: "{$g['unbound_chroot_path']}/unbound_server.pem"
361
	control-key-file: "{$g['unbound_chroot_path']}/unbound_control.key"
362
	control-cert-file: "{$g['unbound_chroot_path']}/unbound_control.pem"
363 56a87b19 Warren Baker
364 f20afeb6 Warren Baker
EOF;
365
366 e318d592 Phil Davis
		create_unbound_chroot_path();
367 fe9d4894 Renato Botelho
		file_put_contents("{$g['unbound_chroot_path']}/remotecontrol.conf", $remotcfg);
368 f20afeb6 Warren Baker
369 fe9d4894 Renato Botelho
		// Generate our keys
370
		do_as_unbound_user("unbound-control-setup");
371 f20afeb6 Warren Baker
372 fe9d4894 Renato Botelho
	}
373 56a87b19 Warren Baker
}
374 f20afeb6 Warren Baker
375 56a87b19 Warren Baker
// Read /etc/hosts
376 f20afeb6 Warren Baker
function read_hosts() {
377
378 fe9d4894 Renato Botelho
	/* Open /etc/hosts and extract the only dhcpleases info
379
	 * XXX - to convert to an unbound C library which reads /etc/hosts automatically
380
	 */
381
	$etc_hosts = array();
382
	foreach (file('/etc/hosts') as $line) {
383 b3977493 Renato Botelho
		if (strpos($line, "dhcpleases automatically entered"))
384
			break;
385
		$d = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
386 fe9d4894 Renato Botelho
		if (empty($d) || substr(reset($d), 0, 1) == "#")
387
			continue;
388 b3977493 Renato Botelho
		$ip = array_shift($d);
389
		$fqdn = array_shift($d);
390
		$name = array_shift($d);
391
		if (!empty($fqdn) && $fqdn != "empty") {
392
			if (!empty($name) && $name != "empty")
393
				array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn", name => "$name"));
394
			else
395
				array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn"));
396 fe9d4894 Renato Botelho
		}
397
	}
398
	return $etc_hosts;
399 f20afeb6 Warren Baker
}
400
401
function sync_unbound_service() {
402 fe9d4894 Renato Botelho
	global $config, $g;
403
404 e318d592 Phil Davis
	create_unbound_chroot_path();
405 fe9d4894 Renato Botelho
406
	// Configure our Unbound service
407
	do_as_unbound_user("unbound-anchor");
408
	unbound_remote_control_setup();
409
	unbound_generate_config();
410
	do_as_unbound_user("start");
411
	require_once("service-utils.inc");
412
	if (is_service_running("unbound"))
413
		do_as_unbound_user("restore_cache");
414 f20afeb6 Warren Baker
415
}
416
417
function unbound_acl_id_used($id) {
418 fe9d4894 Renato Botelho
	global $config;
419 f20afeb6 Warren Baker
420 fe9d4894 Renato Botelho
	if (is_array($config['unbound']['acls']))
421
		foreach($config['unbound']['acls'] as & $acls)
422
			if ($id == $acls['aclid'])
423
				return true;
424 f20afeb6 Warren Baker
425 fe9d4894 Renato Botelho
	return false;
426 f20afeb6 Warren Baker
}
427
428
function unbound_get_next_id() {
429 fe9d4894 Renato Botelho
	$aclid = 0;
430
	while(unbound_acl_id_used($aclid))
431
		$aclid++;
432
	return $aclid;
433 f20afeb6 Warren Baker
}
434
435
// Execute commands as the user unbound
436
function do_as_unbound_user($cmd) {
437 fe9d4894 Renato Botelho
	global $g;
438
439
	switch ($cmd) {
440
	case "start":
441 3ba07784 Renato Botelho
		mwexec("/usr/local/sbin/unbound -c {$g['unbound_chroot_path']}/unbound.conf");
442 fe9d4894 Renato Botelho
		break;
443
	case "stop":
444 3ba07784 Renato Botelho
		mwexec("echo '/usr/local/sbin/unbound-control stop' | /usr/bin/su -m unbound", true);
445 fe9d4894 Renato Botelho
		break;
446 0a5a8df9 Warren Baker
	case "reload":
447
		mwexec("echo '/usr/local/sbin/unbound-control reload' | /usr/bin/su -m unbound", true);
448
		break;
449 fe9d4894 Renato Botelho
	case "unbound-anchor":
450 3ba07784 Renato Botelho
		mwexec("echo '/usr/local/sbin/unbound-anchor -a {$g['unbound_chroot_path']}/root.key' | /usr/bin/su -m unbound", true);
451 fe9d4894 Renato Botelho
		break;
452
	case "unbound-control-setup":
453 3ba07784 Renato Botelho
		mwexec("echo '/usr/local/sbin/unbound-control-setup -d {$g['unbound_chroot_path']}' | /usr/bin/su -m unbound", true);
454 fe9d4894 Renato Botelho
		break;
455
	default:
456
		break;
457
	}
458 f20afeb6 Warren Baker
}
459
460 984abd66 Phil Davis
function unbound_add_domain_overrides($pvt_rev="") {
461 fe9d4894 Renato Botelho
	global $config, $g;
462
463
	$domains = $config['unbound']['domainoverrides'];
464
465
	$sorted_domains = msort($domains, "domain");
466
	$result = array();
467
	foreach($sorted_domains as $domain) {
468
		$domain_key = current($domain);
469
		if (!isset($result[$domain_key]))
470
			$result[$domain_key] = array();
471
		$result[$domain_key][] = $domain['ip'];
472
	}
473
474
	// Domain overrides that have multiple entries need multiple stub-addr: added
475
	$domain_entries = "";
476
	foreach($result as $domain=>$ips) {
477 984abd66 Phil Davis
		if ($pvt_rev == "private") {
478 fe9d4894 Renato Botelho
			$domain_entries .= "private-domain: \"$domain\"\n";
479
			$domain_entries .= "domain-insecure: \"$domain\"\n";
480 984abd66 Phil Davis
		} else if ($pvt_rev == "reverse") {
481
			if ((substr($domain,-14) == ".in-addr.arpa.") || (substr($domain,-13) == ".in-addr.arpa")) {
482
				$domain_entries .= "local-zone: \"$domain\" typetransparent\n";
483
			}
484 fe9d4894 Renato Botelho
		} else {
485
			$domain_entries .= "stub-zone:\n";
486
			$domain_entries .= "\tname: \"$domain\"\n";
487
			foreach($ips as $ip)
488
				$domain_entries .= "\tstub-addr: $ip\n";
489
			$domain_entries .= "\tstub-prime: no\n";
490
		}
491
	}
492
493 a0e387a5 Phil Davis
	if ($pvt_rev != "")
494 fe9d4894 Renato Botelho
		return $domain_entries;
495 e318d592 Phil Davis
	else {
496
		create_unbound_chroot_path();
497 fe9d4894 Renato Botelho
		file_put_contents("{$g['unbound_chroot_path']}/domainoverrides.conf", $domain_entries);
498 e318d592 Phil Davis
	}
499 f20afeb6 Warren Baker
}
500
501
function unbound_add_host_entries() {
502 fe9d4894 Renato Botelho
	global $config, $g;
503
504
	$unbound_entries = "local-zone: \"{$config['system']['domain']}\" transparent\n";
505
506 b3977493 Renato Botelho
	$hosts = read_hosts();
507 06266c34 Lorenz Schori
	$added_ptr = array();
508 b3977493 Renato Botelho
	foreach ($hosts as $host) {
509
		if (is_ipaddrv4($host['ipaddr']))
510
			$type = 'A';
511
		else if (is_ipaddrv6($host['ipaddr']))
512
			$type = 'AAAA';
513
		else
514
			continue;
515 fe9d4894 Renato Botelho
516 06266c34 Lorenz Schori
		if(!$added_ptr[$host['ip']]) {
517
			$unbound_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['fqdn']}\"\n";
518
			$added_ptr[$host['ip']] = true;
519
		}
520 b3977493 Renato Botelho
		$unbound_entries .= "local-data: \"{$host['fqdn']} {$type} {$host['ipaddr']}\"\n";
521
		if (isset($host['name']))
522
			$unbound_entries .= "local-data: \"{$host['name']} {$type} {$host['ipaddr']}\"\n";
523 fe9d4894 Renato Botelho
	}
524
525
	// Write out entries
526 e318d592 Phil Davis
	create_unbound_chroot_path();
527 fe9d4894 Renato Botelho
	file_put_contents("{$g['unbound_chroot_path']}/host_entries.conf", $unbound_entries);
528 b3977493 Renato Botelho
529
	/* dhcpleases will write to this config file, make sure it exists */
530
	@touch("{$g['unbound_chroot_path']}/dhcpleases_entries.conf");
531 f20afeb6 Warren Baker
}
532
533 56a87b19 Warren Baker
function unbound_control($action) {
534 fe9d4894 Renato Botelho
	global $config, $g;
535
536
	$cache_dumpfile = "/var/tmp/unbound_cache";
537
538
	switch ($action) {
539
	case "start":
540
		// Start Unbound
541
		if ($config['unbound']['enable'] == "on") {
542
			if (!is_service_running("unbound"))
543
				do_as_unbound_user("start");
544
		}
545
		break;
546
	case "stop":
547
		if ($config['unbound']['enable'] == "on")
548
			do_as_unbound_user("stop");
549
		break;
550
	case "reload":
551
		if ($config['unbound']['enable'] == "on")
552
			do_as_unbound_user("reload");
553
		break;
554
	case "dump_cache":
555
		// Dump Unbound's Cache
556
		if ($config['unbound']['dumpcache'] == "on")
557
			do_as_unbound_user("dump_cache");
558
		break;
559
	case "restore_cache":
560
		// Restore Unbound's Cache
561
		if ((is_service_running("unbound")) && ($config['unbound']['dumpcache'] == "on")) {
562
			if (file_exists($cache_dumpfile) && filesize($cache_dumpfile) > 0)
563
				do_as_unbound_user("load_cache < /var/tmp/unbound_cache");
564
		}
565
		break;
566
	default:
567
		break;
568
569
	}
570 56a87b19 Warren Baker
}
571
572
// Generation of Unbound statistics
573
function unbound_statistics() {
574 fe9d4894 Renato Botelho
	global $config;
575
576
	if ($config['stats'] == "on") {
577
		$stats_interval = $config['unbound']['stats_interval'];
578
		$cumulative_stats = $config['cumulative_stats'];
579
		if ($config['extended_stats'] == "on")
580
			$extended_stats = "yes";
581
		else
582
			$extended_stats = "no";
583
	} else {
584
		$stats_interval = "0";
585
		$cumulative_stats = "no";
586
		$extended_stats = "no";
587
	}
588
	/* XXX To do - add RRD graphs */
589
	$stats = <<<EOF
590 56a87b19 Warren Baker
# Unbound Statistics
591
statistics-interval: {$stats_interval}
592
extended-statistics: yes
593
statistics-cumulative: yes
594
595
EOF;
596
597 fe9d4894 Renato Botelho
	return $stats;
598 56a87b19 Warren Baker
}
599
600 8fccab67 Warren Baker
// Unbound Access lists
601
function unbound_acls_config() {
602 fe9d4894 Renato Botelho
	global $g, $config;
603
604 f8f5ba1a Chris Buechler
	if (!isset($config['unbound']['disable_auto_added_access_control'])) {
605
		$aclcfg = "access-control: 127.0.0.1/32 allow\n";
606
		$aclcfg .= "access-control: ::1 allow\n";
607
		// Add our networks for active interfaces including localhost
608 8c2a5a73 Phil Davis
		if (!empty($config['unbound']['active_interface'])) {
609 f8f5ba1a Chris Buechler
			$active_interfaces = array_flip(explode(",", $config['unbound']['active_interface']));
610 7fd2a0e3 Chris Buechler
			if (in_array("all", $active_interfaces))
611 80075b9e Chris Buechler
				$active_interfaces = get_configured_interface_with_descr();
612 8c2a5a73 Phil Davis
		} else
613 f8f5ba1a Chris Buechler
			$active_interfaces = get_configured_interface_with_descr();
614
	
615
		$bindints = "";
616
		foreach($active_interfaces as $ubif => $ifdesc) {
617
			$ifip = get_interface_ip($ubif);
618
			if (is_ipaddrv4($ifip)) {
619
				// IPv4 is handled via NAT networks below
620
			}
621
			$ifip = get_interface_ipv6($ubif);
622
			if (is_ipaddrv6($ifip)) {
623 f302a333 Jean Cyr
				if (!is_linklocal($ifip)) {
624
					$subnet_bits = get_interface_subnetv6($ubif);
625
					$subnet_ip = gen_subnetv6($ifip, $subnet_bits);
626
					// only add LAN-type interfaces 
627
					if (!interface_has_gateway($ubif))
628
						$aclcfg .= "access-control: {$subnet_ip}/{$subnet_bits} allow\n";
629
				}
630 f8f5ba1a Chris Buechler
				// add for IPv6 static routes to local networks
631
				// for safety, we include only routes reachable on an interface with no
632
				// gateway specified - read: not an Internet connection. 
633
				$static_routes = get_staticroutes();
634
				foreach ($static_routes as $route) {
635
					if ((lookup_gateway_interface_by_name($route['gateway']) == $ubif) && !interface_has_gateway($ubif)) {
636
						// route is on this interface, interface doesn't have gateway, add it
637
						$aclcfg .= "access-control: {$route['network']} allow\n";
638
					}
639 e3045c51 Chris Buechler
				}
640
			}
641 fe9d4894 Renato Botelho
		}
642 f8f5ba1a Chris Buechler
		
643
		// Generate IPv4 access-control entries using the same logic as automatic outbound NAT
644
		if (empty($FilterIflist)) {
645
			filter_generate_optcfg_array();
646
		}
647
		$natnetworks_array = array();
648
		$natnetworks_array = filter_nat_rules_automatic_tonathosts();
649
		foreach ($natnetworks_array as $allowednet) {
650
			$aclcfg .= "access-control: $allowednet allow \n";	
651
		}	
652 3bdf2a70 Chris Buechler
	}
653 fe9d4894 Renato Botelho
654
	// Configure the custom ACLs
655
	if (is_array($config['unbound']['acls'])) {
656
		foreach($config['unbound']['acls'] as $unbound_acl) {
657
			$aclcfg .= "#{$unbound_acl['aclname']}\n";
658
			foreach($unbound_acl['row'] as $network) {
659
				if ($unbound_acl['aclaction'] == "allow snoop")
660
					$unbound_acl['aclaction'] = "allow_snoop";
661
				$aclcfg .= "access-control: {$network['acl_network']}/{$network['mask']} {$unbound_acl['aclaction']}\n";
662
			}
663
		}
664
	}
665
	// Write out Access list
666 e318d592 Phil Davis
	create_unbound_chroot_path();
667 fe9d4894 Renato Botelho
	file_put_contents("{$g['unbound_chroot_path']}/access_lists.conf", $aclcfg);
668 58d00e65 Warren Baker
669 8fccab67 Warren Baker
}
670
671 f6248774 Warren Baker
// Generate hosts and reload services
672
function unbound_hosts_generate() {
673 fe9d4894 Renato Botelho
	// Generate our hosts file
674
	unbound_add_host_entries();
675 f6248774 Warren Baker
676 fe9d4894 Renato Botelho
	// Reload our service to read the updates
677
	unbound_control("reload");
678 f6248774 Warren Baker
}
679
680 3f0c20c3 Renato Botelho
?>