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 = services_unbound_configure();
92
		$savemsg = get_std_save_message($retval);
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
$shortcut_section = "resolver";
240

    
241
include_once("head.inc");
242

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

    
247
if ($savemsg) {
248
	print_info_box($savemsg, 'success');
249
}
250

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

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

    
261
$form = new Form();
262

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

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

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

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

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

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

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

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

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

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

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

    
333
$section->addInput(new Form_Checkbox(
334
	'regdhcpstatic',
335
	'Static DHCP',
336
	'Register DHCP static mappings in the DNS Resolver',
337
	$pconfig['regdhcpstatic']
338
))->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. '.
339
					'The domain in %sSystem &gt; General Setup%s should also be set to the proper value.','<a href="system.php">','</a>'));
340

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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