Project

General

Profile

Download (17.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * services_unbound.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2014 Warren Baker (warren@pfsense.org)
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

    
23
##|+PRIV
24
##|*IDENT=page-services-dnsresolver
25
##|*NAME=Services: DNS Resolver
26
##|*DESCR=Allow access to the 'Services: DNS Resolver' page.
27
##|*MATCH=services_unbound.php*
28
##|-PRIV
29

    
30
require_once("guiconfig.inc");
31
require_once("unbound.inc");
32
require_once("pfsense-utils.inc");
33
require_once("system.inc");
34

    
35
if (!is_array($config['unbound'])) {
36
	$config['unbound'] = array();
37
}
38

    
39
$a_unboundcfg =& $config['unbound'];
40

    
41
if (!is_array($a_unboundcfg['hosts'])) {
42
	$a_unboundcfg['hosts'] = array();
43
}
44

    
45
$a_hosts =& $a_unboundcfg['hosts'];
46

    
47
if (!is_array($a_unboundcfg['domainoverrides'])) {
48
	$a_unboundcfg['domainoverrides'] = array();
49
}
50

    
51
$a_domainOverrides = &$a_unboundcfg['domainoverrides'];
52

    
53
if (isset($a_unboundcfg['enable'])) {
54
	$pconfig['enable'] = true;
55
}
56
if (isset($a_unboundcfg['dnssec'])) {
57
	$pconfig['dnssec'] = true;
58
}
59
if (isset($a_unboundcfg['forwarding'])) {
60
	$pconfig['forwarding'] = true;
61
}
62
if (isset($a_unboundcfg['regdhcp'])) {
63
	$pconfig['regdhcp'] = true;
64
}
65
if (isset($a_unboundcfg['regdhcpstatic'])) {
66
	$pconfig['regdhcpstatic'] = true;
67
}
68

    
69
$pconfig['port'] = $a_unboundcfg['port'];
70
$pconfig['custom_options'] = base64_decode($a_unboundcfg['custom_options']);
71

    
72
if (empty($a_unboundcfg['active_interface'])) {
73
	$pconfig['active_interface'] = array();
74
} else {
75
	$pconfig['active_interface'] = explode(",", $a_unboundcfg['active_interface']);
76
}
77

    
78
if (empty($a_unboundcfg['outgoing_interface'])) {
79
	$pconfig['outgoing_interface'] = array();
80
} else {
81
	$pconfig['outgoing_interface'] = explode(",", $a_unboundcfg['outgoing_interface']);
82
}
83

    
84
if (empty($a_unboundcfg['system_domain_local_zone_type'])) {
85
	$pconfig['system_domain_local_zone_type'] = "transparent";
86
} else {
87
	$pconfig['system_domain_local_zone_type'] = $a_unboundcfg['system_domain_local_zone_type'];
88
}
89

    
90

    
91
if ($_POST['apply']) {
92
	$retval = 0;
93
	$retval |= services_unbound_configure();
94
	if ($retval == 0) {
95
		clear_subsystem_dirty('unbound');
96
	}
97
	/* Update resolv.conf in case the interface bindings exclude localhost. */
98
	system_resolvconf_generate();
99
	/* Start or restart dhcpleases when it's necessary */
100
	system_dhcpleases_configure();
101
}
102

    
103
if ($_POST['save']) {
104
	$pconfig = $_POST;
105
	unset($input_errors);
106

    
107
	if (isset($pconfig['enable']) && isset($config['dnsmasq']['enable'])) {
108
		if ($pconfig['port'] == $config['dnsmasq']['port']) {
109
			$input_errors[] = gettext("The DNS Forwarder is enabled using this port. Choose a non-conflicting port, or disable the DNS Forwarder.");
110
		}
111
	}
112

    
113
	// forwarding mode requires having valid DNS servers
114
	if (isset($pconfig['forwarding'])) {
115
		$founddns = false;
116
		if (isset($config['system']['dnsallowoverride'])) {
117
			$dns_servers = get_dns_servers();
118
			if (is_array($dns_servers)) {
119
				foreach ($dns_servers as $dns_server) {
120
					if (!ip_in_subnet($dns_server, "127.0.0.0/8")) {
121
						$founddns = true;
122
					}
123
				}
124
			}
125
		}
126
		if (is_array($config['system']['dnsserver'])) {
127
			foreach ($config['system']['dnsserver'] as $dnsserver) {
128
				if (is_ipaddr($dnsserver)) {
129
					$founddns = true;
130
				}
131
			}
132
		}
133
		if ($founddns == false) {
134
			$input_errors[] = gettext("At least one DNS server must be specified under System &gt; General Setup to enable Forwarding mode.");
135
		}
136
	}
137

    
138
	if (empty($pconfig['active_interface'])) {
139
		$input_errors[] = gettext("One or more Network Interfaces must be selected for binding.");
140
	} else if (!isset($config['system']['dnslocalhost']) && (!in_array("lo0", $pconfig['active_interface']) && !in_array("all", $pconfig['active_interface']))) {
141
		$input_errors[] = gettext("This system is configured to use the DNS Resolver as its DNS server, so Localhost or All must be selected in Network Interfaces.");
142
	}
143

    
144
	if (empty($pconfig['outgoing_interface'])) {
145
		$input_errors[] = gettext("One or more Outgoing Network Interfaces must be selected.");
146
	}
147

    
148
	if ($pconfig['port'] && !is_port($pconfig['port'])) {
149
		$input_errors[] = gettext("A valid port number must be specified.");
150
	}
151

    
152
	if (is_array($pconfig['active_interface']) && !empty($pconfig['active_interface'])) {
153
		$display_active_interface = $pconfig['active_interface'];
154
		$pconfig['active_interface'] = implode(",", $pconfig['active_interface']);
155
	}
156

    
157
	if ((isset($pconfig['regdhcp']) || isset($pconfig['regdhcpstatic'])) && !is_dhcp_server_enabled()) {
158
		$input_errors[] = gettext("DHCP Server must be enabled for DHCP Registration to work in DNS Resolver.");
159
	}
160

    
161
	$display_custom_options = $pconfig['custom_options'];
162
	$pconfig['custom_options'] = base64_encode(str_replace("\r\n", "\n", $pconfig['custom_options']));
163

    
164
	if (is_array($pconfig['outgoing_interface']) && !empty($pconfig['outgoing_interface'])) {
165
		$display_outgoing_interface = $pconfig['outgoing_interface'];
166
		$pconfig['outgoing_interface'] = implode(",", $pconfig['outgoing_interface']);
167
	}
168

    
169
	$test_output = array();
170
	if (test_unbound_config($pconfig, $test_output)) {
171
		$input_errors[] = gettext("The generated config file cannot be parsed by unbound. Please correct the following errors:");
172
		$input_errors = array_merge($input_errors, $test_output);
173
	}
174

    
175
	if (!$input_errors) {
176
		$a_unboundcfg['enable'] = isset($pconfig['enable']);
177
		$a_unboundcfg['port'] = $pconfig['port'];
178
		$a_unboundcfg['dnssec'] = isset($pconfig['dnssec']);
179
		$a_unboundcfg['forwarding'] = isset($pconfig['forwarding']);
180
		$a_unboundcfg['regdhcp'] = isset($pconfig['regdhcp']);
181
		$a_unboundcfg['regdhcpstatic'] = isset($pconfig['regdhcpstatic']);
182
		$a_unboundcfg['active_interface'] = $pconfig['active_interface'];
183
		$a_unboundcfg['outgoing_interface'] = $pconfig['outgoing_interface'];
184
		$a_unboundcfg['system_domain_local_zone_type'] = $pconfig['system_domain_local_zone_type'];
185
		$a_unboundcfg['custom_options'] = $pconfig['custom_options'];
186

    
187
		write_config(gettext("DNS Resolver configured."));
188
		mark_subsystem_dirty('unbound');
189
	}
190

    
191
	$pconfig['active_interface'] = $display_active_interface;
192
	$pconfig['outgoing_interface'] = $display_outgoing_interface;
193
	$pconfig['custom_options'] = $display_custom_options;
194
}
195

    
196

    
197
if ($pconfig['custom_options']) {
198
	$customoptions = true;
199
} else {
200
	$customoptions = false;
201
}
202

    
203
if ($_POST['act'] == "del") {
204
	if ($_POST['type'] == 'host') {
205
		if ($a_hosts[$_POST['id']]) {
206
			unset($a_hosts[$_POST['id']]);
207
			write_config();
208
			mark_subsystem_dirty('unbound');
209
			header("Location: services_unbound.php");
210
			exit;
211
		}
212
	} elseif ($_POST['type'] == 'doverride') {
213
		if ($a_domainOverrides[$_POST['id']]) {
214
			unset($a_domainOverrides[$_POST['id']]);
215
			write_config();
216
			mark_subsystem_dirty('unbound');
217
			header("Location: services_unbound.php");
218
			exit;
219
		}
220
	}
221
}
222

    
223
function build_if_list($selectedifs) {
224
	$interface_addresses = get_possible_listen_ips(true);
225
	$iflist = array('options' => array(), 'selected' => array());
226

    
227
	$iflist['options']['all']	= gettext("All");
228
	if (empty($selectedifs) || empty($selectedifs[0]) || in_array("all", $selectedifs)) {
229
		array_push($iflist['selected'], "all");
230
	}
231

    
232
	foreach ($interface_addresses as $laddr => $ldescr) {
233
		$iflist['options'][$laddr] = htmlspecialchars($ldescr);
234

    
235
		if ($selectedifs && in_array($laddr, $selectedifs)) {
236
			array_push($iflist['selected'], $laddr);
237
		}
238
	}
239

    
240
	unset($interface_addresses);
241

    
242
	return($iflist);
243
}
244

    
245
$pgtitle = array(gettext("Services"), gettext("DNS Resolver"), gettext("General Settings"));
246
$pglinks = array("", "@self", "@self");
247
$shortcut_section = "resolver";
248

    
249
include_once("head.inc");
250

    
251
if ($input_errors) {
252
	print_input_errors($input_errors);
253
}
254

    
255
if ($_POST['apply']) {
256
	print_apply_result_box($retval);
257
}
258

    
259
if (is_subsystem_dirty('unbound')) {
260
	print_apply_box(gettext("The DNS resolver configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
261
}
262

    
263
$tab_array = array();
264
$tab_array[] = array(gettext("General Settings"), true, "services_unbound.php");
265
$tab_array[] = array(gettext("Advanced Settings"), false, "services_unbound_advanced.php");
266
$tab_array[] = array(gettext("Access Lists"), false, "/services_unbound_acls.php");
267
display_top_tabs($tab_array, true);
268

    
269
$form = new Form();
270

    
271
$section = new Form_Section('General DNS Resolver Options');
272

    
273
$section->addInput(new Form_Checkbox(
274
	'enable',
275
	'Enable',
276
	'Enable DNS resolver',
277
	$pconfig['enable']
278
));
279

    
280
$section->addInput(new Form_Input(
281
	'port',
282
	'Listen Port',
283
	'number',
284
	$pconfig['port'],
285
	['placeholder' => '53']
286
))->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.');
287

    
288
$activeiflist = build_if_list($pconfig['active_interface']);
289

    
290
$section->addInput(new Form_Select(
291
	'active_interface',
292
	'*Network Interfaces',
293
	$activeiflist['selected'],
294
	$activeiflist['options'],
295
	true
296
))->addClass('general', 'resizable')->setHelp('Interface IPs used by the DNS Resolver for responding to queries from clients. If an interface has both IPv4 and IPv6 IPs, both are used. Queries to other interface IPs not selected below are discarded. ' .
297
			'The default behavior is to respond to queries on every available IPv4 and IPv6 address.');
298

    
299
$outiflist = build_if_list($pconfig['outgoing_interface']);
300

    
301
$section->addInput(new Form_Select(
302
	'outgoing_interface',
303
	'*Outgoing Network Interfaces',
304
	$outiflist['selected'],
305
	$outiflist['options'],
306
	true
307
))->addClass('general', 'resizable')->setHelp('Utilize different network interface(s) that the DNS Resolver will use to send queries to authoritative servers and receive their replies. By default all interfaces are used.');
308

    
309
$section->addInput(new Form_Select(
310
	'system_domain_local_zone_type',
311
	'*System Domain Local Zone Type',
312
	$pconfig['system_domain_local_zone_type'],
313
	unbound_local_zone_types()
314
))->setHelp('The local-zone type used for the pfSense system domain (System | General Setup | Domain).  Transparent is the default.  Local-Zone type descriptions are available in the unbound.conf(5) manual pages.');
315

    
316
$section->addInput(new Form_Checkbox(
317
	'dnssec',
318
	'DNSSEC',
319
	'Enable DNSSEC Support',
320
	$pconfig['dnssec']
321
));
322

    
323
$section->addInput(new Form_Checkbox(
324
	'forwarding',
325
	'DNS Query Forwarding',
326
	'Enable Forwarding Mode',
327
	$pconfig['forwarding']
328
))->setHelp('If this option is set, DNS queries will be forwarded to the upstream DNS servers defined under'.
329
					' %1$sSystem &gt; General Setup%2$s or those obtained via DHCP/PPP on WAN'.
330
					' (if DNS Server Override is enabled there).','<a href="system.php">','</a>');
331

    
332
$section->addInput(new Form_Checkbox(
333
	'regdhcp',
334
	'DHCP Registration',
335
	'Register DHCP leases in the DNS Resolver',
336
	$pconfig['regdhcp']
337
))->setHelp('If this option is set, then machines that specify their hostname when requesting a DHCP lease will be registered'.
338
					' in the DNS Resolver, so that their name can be resolved.'.
339
					' The domain in %1$sSystem &gt; General Setup%2$s should also be set to the proper value.','<a href="system.php">','</a>');
340

    
341
$section->addInput(new Form_Checkbox(
342
	'regdhcpstatic',
343
	'Static DHCP',
344
	'Register DHCP static mappings in the DNS Resolver',
345
	$pconfig['regdhcpstatic']
346
))->setHelp('If this option is set, then DHCP static mappings will be registered in the DNS Resolver, so that their name can be resolved. '.
347
					'The domain in %1$sSystem &gt; General Setup%2$s should also be set to the proper value.','<a href="system.php">','</a>');
348

    
349
$btnadv = new Form_Button(
350
	'btnadvcustom',
351
	'Custom options',
352
	null,
353
	'fa-cog'
354
);
355

    
356
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
357

    
358
$section->addInput(new Form_StaticText(
359
	'Display Custom Options',
360
	$btnadv
361
));
362

    
363
$section->addInput(new Form_Textarea (
364
	'custom_options',
365
	'Custom options',
366
	$pconfig['custom_options']
367
))->setHelp('Enter any additional configuration parameters to add to the DNS Resolver configuration here, separated by a newline.');
368

    
369
$form->add($section);
370
print($form);
371
?>
372

    
373
<script type="text/javascript">
374
//<![CDATA[
375
events.push(function() {
376

    
377
	// Show advanced custom options ==============================================
378
	var showadvcustom = false;
379

    
380
	function show_advcustom(ispageload) {
381
		var text;
382
		// On page load decide the initial state based on the data.
383
		if (ispageload) {
384
			showadvcustom = <?=($customoptions ? 'true' : 'false');?>;
385
		} else {
386
			// It was a click, swap the state.
387
			showadvcustom = !showadvcustom;
388
		}
389

    
390
		hideInput('custom_options', !showadvcustom);
391

    
392
		if (showadvcustom) {
393
			text = "<?=gettext('Hide Custom Options');?>";
394
		} else {
395
			text = "<?=gettext('Display Custom Options');?>";
396
		}
397
		$('#btnadvcustom').html('<i class="fa fa-cog"></i> ' + text);
398
	}
399

    
400
	// If the enable checkbox is not checked, hide all inputs
401
	function hideGeneral() {
402
		var hide = ! $('#enable').prop('checked');
403

    
404
		hideMultiClass('general', hide);
405
		hideInput('port', hide);
406
		hideSelect('system_domain_local_zone_type', hide);
407
		hideCheckbox('dnssec', hide);
408
		hideCheckbox('forwarding', hide);
409
		hideCheckbox('regdhcp', hide);
410
		hideCheckbox('regdhcpstatic', hide);
411
		hideInput('btnadvcustom', hide);
412
		hideInput('custom_options', hide || !showadvcustom);
413
	}
414

    
415
	// Un-hide additional controls
416
	$('#btnadvcustom').click(function(event) {
417
		show_advcustom();
418
	});
419

    
420
	// When 'enable' is clicked, disable/enable the following hide inputs
421
	$('#enable').click(function() {
422
		hideGeneral();
423
	});
424

    
425
	// On initial load
426
	if ($('#custom_options').val().length == 0) {
427
		hideInput('custom_options', true);
428
	}
429

    
430
	hideGeneral();
431
	show_advcustom(true);
432

    
433
});
434
//]]>
435
</script>
436

    
437
<div class="panel panel-default">
438
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Host Overrides")?></h2></div>
439
	<div class="panel-body table-responsive">
440
		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
441
			<thead>
442
				<tr>
443
					<th><?=gettext("Host")?></th>
444
					<th><?=gettext("Domain")?></th>
445
					<th><?=gettext("IP")?></th>
446
					<th><?=gettext("Description")?></th>
447
					<th><?=gettext("Actions")?></th>
448
				</tr>
449
			</thead>
450
			<tbody>
451
<?php
452
$i = 0;
453
foreach ($a_hosts as $hostent):
454
?>
455
				<tr>
456
					<td>
457
						<?=$hostent['host']?>
458
					</td>
459
					<td>
460
						<?=$hostent['domain']?>
461
					</td>
462
					<td>
463
						<?=$hostent['ip']?>
464
					</td>
465
					<td>
466
						<?=htmlspecialchars($hostent['descr'])?>
467
					</td>
468
					<td>
469
						<a class="fa fa-pencil"	title="<?=gettext('Edit host override')?>" href="services_unbound_host_edit.php?id=<?=$i?>"></a>
470
						<a class="fa fa-trash"	title="<?=gettext('Delete host override')?>" href="services_unbound.php?type=host&amp;act=del&amp;id=<?=$i?>" usepost></a>
471
					</td>
472
				</tr>
473

    
474
<?php
475
	if ($hostent['aliases']['item'] && is_array($hostent['aliases']['item'])):
476
		foreach ($hostent['aliases']['item'] as $alias):
477
?>
478
				<tr>
479
					<td>
480
						<?=$alias['host']?>
481
					</td>
482
					<td>
483
						<?=$alias['domain']?>
484
					</td>
485
					<td>
486
						<?=gettext("Alias for ");?><?=$hostent['host'] ? $hostent['host'] . '.' . $hostent['domain'] : $hostent['domain']?>
487
					</td>
488
					<td>
489
						<i class="fa fa-angle-double-right text-info"></i>
490
						<?=htmlspecialchars($alias['description'])?>
491
					</td>
492
					<td>
493
						<a class="fa fa-pencil"	title="<?=gettext('Edit host override')?>" 	href="services_unbound_host_edit.php?id=<?=$i?>"></a>
494
					</td>
495
				</tr>
496
<?php
497
		endforeach;
498
	endif;
499
	$i++;
500
endforeach;
501
?>
502
			</tbody>
503
		</table>
504
	</div>
505
</div>
506

    
507
<nav class="action-buttons">
508
	<a href="services_unbound_host_edit.php" class="btn btn-sm btn-success">
509
		<i class="fa fa-plus icon-embed-btn"></i>
510
		<?=gettext('Add')?>
511
	</a>
512
</nav>
513

    
514
<div class="panel panel-default">
515
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Domain Overrides")?></h2></div>
516
	<div class="panel-body table-responsive">
517
		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
518
			<thead>
519
				<tr>
520
					<th><?=gettext("Domain")?></th>
521
					<th><?=gettext("IP")?></th>
522
					<th><?=gettext("Description")?></th>
523
					<th><?=gettext("Actions")?></th>
524
				</tr>
525
			</thead>
526

    
527
			<tbody>
528
<?php
529
$i = 0;
530
foreach ($a_domainOverrides as $doment):
531
?>
532
				<tr>
533
					<td>
534
						<?=$doment['domain']?>&nbsp;
535
					</td>
536
					<td>
537
						<?=$doment['ip']?>&nbsp;
538
					</td>
539
					<td>
540
						<?=htmlspecialchars($doment['descr'])?>&nbsp;
541
					</td>
542
					<td>
543
						<a class="fa fa-pencil"	title="<?=gettext('Edit domain override')?>" href="services_unbound_domainoverride_edit.php?id=<?=$i?>"></a>
544
						<a class="fa fa-trash"	title="<?=gettext('Delete domain override')?>" href="services_unbound.php?act=del&amp;type=doverride&amp;id=<?=$i?>" usepost></a>
545
					</td>
546
				</tr>
547
<?php
548
	$i++;
549
endforeach;
550
?>
551
			</tbody>
552
		</table>
553
	</div>
554
</div>
555

    
556
<nav class="action-buttons">
557
	<a href="services_unbound_domainoverride_edit.php" class="btn btn-sm btn-success">
558
		<i class="fa fa-plus icon-embed-btn"></i>
559
		<?=gettext('Add')?>
560
	</a>
561
</nav>
562

    
563
<div class="infoblock">
564
	<?php print_info_box(sprintf(gettext('If the DNS Resolver is enabled, the DHCP'.
565
		' service (if enabled) will automatically serve the LAN IP'.
566
		' address as a DNS server to DHCP clients so they will use'.
567
		' the DNS Resolver. If Forwarding is enabled, the DNS Resolver will use the DNS servers'.
568
		' entered in %1$sSystem &gt; General Setup%2$s'.
569
		' or those obtained via DHCP or PPP on WAN if &quot;Allow'.
570
		' DNS server list to be overridden by DHCP/PPP on WAN&quot;'.
571
		' is checked.'), '<a href="system.php">', '</a>'), 'info', false); ?>
572
</div>
573

    
574
<?php include("foot.inc");
(138-138/223)