Project

General

Profile

Download (17.5 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("system.inc");
33

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
135
		if (empty($pconfig['active_interface'])) {
136
			$input_errors[] = gettext("One or more Network Interfaces must be selected for binding.");
137
		} else if (!isset($config['system']['dnslocalhost']) && (!in_array("lo0", $pconfig['active_interface']) && !in_array("all", $pconfig['active_interface']))) {
138
			$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.");
139
		}
140

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

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

    
149
		if (is_array($pconfig['active_interface']) && !empty($pconfig['active_interface'])) {
150
			$display_active_interface = $pconfig['active_interface'];
151
			$pconfig['active_interface'] = implode(",", $pconfig['active_interface']);
152
		}
153

    
154
		$display_custom_options = $pconfig['custom_options'];
155
		$pconfig['custom_options'] = base64_encode(str_replace("\r\n", "\n", $pconfig['custom_options']));
156

    
157
		if (is_array($pconfig['outgoing_interface']) && !empty($pconfig['outgoing_interface'])) {
158
			$display_outgoing_interface = $pconfig['outgoing_interface'];
159
			$pconfig['outgoing_interface'] = implode(",", $pconfig['outgoing_interface']);
160
		}
161

    
162
		$test_output = array();
163
		if (test_unbound_config($pconfig, $test_output)) {
164
			$input_errors[] = gettext("The generated config file cannot be parsed by unbound. Please correct the following errors:");
165
			$input_errors = array_merge($input_errors, $test_output);
166
		}
167

    
168
		if (!$input_errors) {
169
			$a_unboundcfg['enable'] = isset($pconfig['enable']);
170
			$a_unboundcfg['port'] = $pconfig['port'];
171
			$a_unboundcfg['dnssec'] = isset($pconfig['dnssec']);
172
			$a_unboundcfg['forwarding'] = isset($pconfig['forwarding']);
173
			$a_unboundcfg['regdhcp'] = isset($pconfig['regdhcp']);
174
			$a_unboundcfg['regdhcpstatic'] = isset($pconfig['regdhcpstatic']);
175
			$a_unboundcfg['active_interface'] = $pconfig['active_interface'];
176
			$a_unboundcfg['outgoing_interface'] = $pconfig['outgoing_interface'];
177
			$a_unboundcfg['system_domain_local_zone_type'] = $pconfig['system_domain_local_zone_type'];
178
			$a_unboundcfg['custom_options'] = $pconfig['custom_options'];
179

    
180
			write_config(gettext("DNS Resolver configured."));
181
			mark_subsystem_dirty('unbound');
182
		}
183

    
184
		$pconfig['active_interface'] = $display_active_interface;
185
		$pconfig['outgoing_interface'] = $display_outgoing_interface;
186
		$pconfig['custom_options'] = $display_custom_options;
187
	}
188
}
189

    
190
if ($pconfig['custom_options']) {
191
	$customoptions = true;
192
} else {
193
	$customoptions = false;
194
}
195

    
196
if ($_GET['act'] == "del") {
197
	if ($_GET['type'] == 'host') {
198
		if ($a_hosts[$_GET['id']]) {
199
			unset($a_hosts[$_GET['id']]);
200
			write_config();
201
			mark_subsystem_dirty('unbound');
202
			header("Location: services_unbound.php");
203
			exit;
204
		}
205
	} elseif ($_GET['type'] == 'doverride') {
206
		if ($a_domainOverrides[$_GET['id']]) {
207
			unset($a_domainOverrides[$_GET['id']]);
208
			write_config();
209
			mark_subsystem_dirty('unbound');
210
			header("Location: services_unbound.php");
211
			exit;
212
		}
213
	}
214
}
215

    
216
function build_if_list($selectedifs) {
217
	$interface_addresses = get_possible_listen_ips(true);
218
	$iflist = array('options' => array(), 'selected' => array());
219

    
220
	$iflist['options']['all']	= gettext("All");
221
	if (empty($selectedifs) || empty($selectedifs[0]) || in_array("all", $selectedifs)) {
222
		array_push($iflist['selected'], "all");
223
	}
224

    
225
	foreach ($interface_addresses as $laddr => $ldescr) {
226
		$iflist['options'][$laddr] = htmlspecialchars($ldescr);
227

    
228
		if ($selectedifs && in_array($laddr, $selectedifs)) {
229
			array_push($iflist['selected'], $laddr);
230
		}
231
	}
232

    
233
	unset($interface_addresses);
234

    
235
	return($iflist);
236
}
237

    
238
$pgtitle = array(gettext("Services"), gettext("DNS Resolver"), gettext("General Settings"));
239
$pglinks = array("", "@self", "@self");
240
$shortcut_section = "resolver";
241

    
242
include_once("head.inc");
243

    
244
if ($input_errors) {
245
	print_input_errors($input_errors);
246
}
247

    
248
if ($_POST['apply']) {
249
	print_apply_result_box($retval);
250
}
251

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

    
256
$tab_array = array();
257
$tab_array[] = array(gettext("General Settings"), true, "services_unbound.php");
258
$tab_array[] = array(gettext("Advanced Settings"), false, "services_unbound_advanced.php");
259
$tab_array[] = array(gettext("Access Lists"), false, "/services_unbound_acls.php");
260
display_top_tabs($tab_array, true);
261

    
262
$form = new Form();
263

    
264
$section = new Form_Section('General DNS Resolver Options');
265

    
266
$section->addInput(new Form_Checkbox(
267
	'enable',
268
	'Enable',
269
	'Enable DNS resolver',
270
	$pconfig['enable']
271
));
272

    
273
$section->addInput(new Form_Input(
274
	'port',
275
	'Listen Port',
276
	'number',
277
	$pconfig['port'],
278
	['placeholder' => '53']
279
))->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.');
280

    
281
$activeiflist = build_if_list($pconfig['active_interface']);
282

    
283
$section->addInput(new Form_Select(
284
	'active_interface',
285
	'Network Interfaces',
286
	$activeiflist['selected'],
287
	$activeiflist['options'],
288
	true
289
))->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. ' .
290
			'The default behavior is to respond to queries on every available IPv4 and IPv6 address.');
291

    
292
$outiflist = build_if_list($pconfig['outgoing_interface']);
293

    
294
$section->addInput(new Form_Select(
295
	'outgoing_interface',
296
	'Outgoing Network Interfaces',
297
	$outiflist['selected'],
298
	$outiflist['options'],
299
	true
300
))->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.');
301

    
302
$section->addInput(new Form_Select(
303
	'system_domain_local_zone_type',
304
	'System Domain Local Zone Type',
305
	$pconfig['system_domain_local_zone_type'],
306
	unbound_local_zone_types()
307
))->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.');
308

    
309
$section->addInput(new Form_Checkbox(
310
	'dnssec',
311
	'DNSSEC',
312
	'Enable DNSSEC Support',
313
	$pconfig['dnssec']
314
));
315

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

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

    
334
$section->addInput(new Form_Checkbox(
335
	'regdhcpstatic',
336
	'Static DHCP',
337
	'Register DHCP static mappings in the DNS Resolver',
338
	$pconfig['regdhcpstatic']
339
))->setHelp(sprintf('If this option is set, then DHCP static mappings will be registered in the DNS Resolver, so that their name can be resolved. '.
340
					'The domain in %sSystem &gt; General Setup%s should also be set to the proper value.','<a href="system.php">','</a>'));
341

    
342
$btnadv = new Form_Button(
343
	'btnadvcustom',
344
	'Custom options',
345
	null,
346
	'fa-cog'
347
);
348

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

    
351
$section->addInput(new Form_StaticText(
352
	'Display Custom Options',
353
	$btnadv
354
));
355

    
356
$section->addInput(new Form_Textarea (
357
	'custom_options',
358
	'Custom options',
359
	$pconfig['custom_options']
360
))->setHelp('Enter any additional configuration parameters to add to the DNS Resolver configuration here, separated by a newline.');
361

    
362
$form->add($section);
363
print($form);
364
?>
365

    
366
<script type="text/javascript">
367
//<![CDATA[
368
events.push(function() {
369

    
370
	// Show advanced custom options ==============================================
371
	var showadvcustom = false;
372

    
373
	function show_advcustom(ispageload) {
374
		var text;
375
		// On page load decide the initial state based on the data.
376
		if (ispageload) {
377
			showadvcustom = <?=($customoptions ? 'true' : 'false');?>;
378
		} else {
379
			// It was a click, swap the state.
380
			showadvcustom = !showadvcustom;
381
		}
382

    
383
		hideInput('custom_options', !showadvcustom);
384

    
385
		if (showadvcustom) {
386
			text = "<?=gettext('Hide Custom Options');?>";
387
		} else {
388
			text = "<?=gettext('Display Custom Options');?>";
389
		}
390
		$('#btnadvcustom').html('<i class="fa fa-cog"></i> ' + text);
391
	}
392

    
393
	// If the enable checkbox is not checked, hide all inputs
394
	function hideGeneral() {
395
		var hide = ! $('#enable').prop('checked');
396

    
397
		hideMultiClass('general', hide);
398
		hideInput('port', hide);
399
		hideSelect('system_domain_local_zone_type', hide);
400
		hideCheckbox('dnssec', hide);
401
		hideCheckbox('forwarding', hide);
402
		hideCheckbox('regdhcp', hide);
403
		hideCheckbox('regdhcpstatic', hide);
404
		hideInput('btnadvcustom', hide);
405
		hideInput('custom_options', hide || !showadvcustom);
406
	}
407

    
408
	// Un-hide additional controls
409
	$('#btnadvcustom').click(function(event) {
410
		show_advcustom();
411
	});
412

    
413
	// When 'enable' is clicked, disable/enable the following hide inputs
414
	$('#enable').click(function() {
415
		hideGeneral();
416
	});
417

    
418
	// On initial load
419
	if ($('#custom_options').val().length == 0) {
420
		hideInput('custom_options', true);
421
	}
422

    
423
	hideGeneral();
424
	show_advcustom(true);
425

    
426
});
427
//]]>
428
</script>
429

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

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

    
500
<nav class="action-buttons">
501
	<a href="services_unbound_host_edit.php" class="btn btn-sm btn-success">
502
		<i class="fa fa-plus icon-embed-btn"></i>
503
		<?=gettext('Add')?>
504
	</a>
505
</nav>
506

    
507
<div class="panel panel-default">
508
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Domain Overrides")?></h2></div>
509
	<div class="panel-body table-responsive">
510
		<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap table-rowdblclickedit" data-sortable>
511
			<thead>
512
				<tr>
513
					<th><?=gettext("Domain")?></th>
514
					<th><?=gettext("IP")?></th>
515
					<th><?=gettext("Description")?></th>
516
					<th><?=gettext("Actions")?></th>
517
				</tr>
518
			</thead>
519

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

    
549
<nav class="action-buttons">
550
	<a href="services_unbound_domainoverride_edit.php" class="btn btn-sm btn-success">
551
		<i class="fa fa-plus icon-embed-btn"></i>
552
		<?=gettext('Add')?>
553
	</a>
554
</nav>
555

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

    
567
<?php include("foot.inc");
(140-140/225)