Project

General

Profile

Download (13 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * vpn.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2025 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2008 Shrew Soft Inc
10
 * All rights reserved.
11
 *
12
 * originally part of m0n0wall (http://m0n0.ch/wall)
13
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
 * All rights reserved.
15
 *
16
 * Licensed under the Apache License, Version 2.0 (the "License");
17
 * you may not use this file except in compliance with the License.
18
 * You may obtain a copy of the License at
19
 *
20
 * http://www.apache.org/licenses/LICENSE-2.0
21
 *
22
 * Unless required by applicable law or agreed to in writing, software
23
 * distributed under the License is distributed on an "AS IS" BASIS,
24
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
 * See the License for the specific language governing permissions and
26
 * limitations under the License.
27
 */
28

    
29
require_once("ipsec.inc");
30
require_once("filter.inc");
31
require_once("auth.inc");
32
require_once("certs.inc");
33

    
34
/* master setup for vpn (mpd) */
35
function vpn_setup() {
36
	/* start pppoe server */
37
	vpn_pppoes_configure();
38

    
39
	/* setup l2tp */
40
	vpn_l2tp_configure();
41
}
42

    
43
function vpn_ppp_server_get_dns($dns1 = '', $dns2 = '') {
44
	$ipcp_dns = '';
45
	$dns_servers = [];
46

    
47
	if (is_ipaddrv4($dns1)) {
48
		/* Use manual DNS servers if they are valid */
49
		$dns_servers[] = $dns1;
50
		if (is_ipaddrv4($dns2)) {
51
			$dns_servers[] = $dns2;
52
		}
53
	} else {
54
		/* Get system defined DNS servers */
55
		$host_dns_servers = get_dns_nameservers(false, true);
56

    
57
		/* Add LAN address if the Resolver or Forwarder are enabled */
58
		if (config_path_enabled('unbound') ||
59
		    config_path_enabled('dnsmasq')) {
60
			$dns_servers[] = get_interface_ip("lan");
61
		}
62

    
63
		/* Add host DNS servers if they are usable */
64
		foreach ($host_dns_servers as $dns) {
65
			if (is_ipaddrv4($dns) && !ip_in_subnet($dns, "127.0.0.0/8")) {
66
				$dns_servers[] = $dns;
67
			}
68
		}
69
	}
70

    
71
	if (!empty($dns_servers)) {
72
		/* Use the first two DNS servers since that is all MPD currently allows */
73
		$ipcp_dns = 'set ipcp dns ' . join(' ', array_slice($dns_servers, 0, 2));
74
	}
75
	return $ipcp_dns;
76
}
77

    
78
function vpn_pppoes_configure() {
79
	foreach (config_get_path("pppoes/pppoe", []) as $pppoe) {
80
		if (!empty($pppoe)) {
81
			vpn_pppoe_configure($pppoe);
82
		}
83
	}
84
}
85

    
86
function vpn_pppoe_configure(&$pppoecfg) {
87
	global $g;
88

    
89
	if (empty($pppoecfg) || !is_array($pppoecfg)) {
90
		return false;
91
	}
92

    
93
	/* create directory if it does not exist */
94
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
95
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
96
	}
97

    
98
	if (is_platform_booting()) {
99
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
100
			return 0;
101
		}
102

    
103
		echo gettext("Configuring PPPoE Server service... ");
104
	} else {
105
		/* kill mpd */
106
		if (isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
107
			killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
108
		}
109

    
110
		/* wait for process to die */
111
		sleep(2);
112

    
113
	}
114

    
115
	if ($pppoecfg['mode'] != 'server') {
116
		if (is_platform_booting()) {
117
			echo gettext("done") . "\n";
118
		}
119
		return true;
120
	}
121

    
122
	$pppoe_interface = get_real_interface($pppoecfg['interface']);
123

    
124
	if ($pppoecfg['paporchap'] == "chap") {
125
		$paporchap = "set link enable chap";
126
	} else {
127
		$paporchap = "set link enable pap";
128
	}
129

    
130
	/* write mpd.conf */
131
	$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
132
	if (!$fd) {
133
		printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
134
		return 1;
135
	}
136

    
137
	$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
138

    
139
	if (array_path_enabled($pppoecfg, 'radius', 'radiusissueips') &&
140
	    array_path_enabled($pppoecfg, 'radius/server')) {
141
		$issue_ip_type .= "0.0.0.0/0";
142
	} else {
143
		$issue_ip_type .= "ippool p0";
144
	}
145

    
146
	$ippool_p0 = ip_after($pppoecfg['remoteip'], $pppoecfg['n_pppoe_units'] - 1);
147

    
148
	if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
149
		$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
150
	} else {
151
		$pppoemaxlogins = 1;
152
	}
153

    
154
	$ipcp_dns = vpn_ppp_server_get_dns($pppoecfg['dns1'], $pppoecfg['dns2']);
155

    
156
	$mpdconf = <<<EOD
157
startup:
158

    
159
poes:
160
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
161

    
162
	create bundle template poes_b
163
	set bundle enable compression
164

    
165
	set ccp yes mppc
166
	set mppc yes e40
167
	set mppc yes e128
168
	set mppc yes stateless
169

    
170
	set iface name poes{$pppoecfg['pppoeid']}-
171
	set iface group pppoe
172
	set iface up-script /usr/local/sbin/vpn-linkup-poes
173
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
174
	set iface idle 0
175
	set iface disable on-demand
176
	set iface disable proxy-arp
177
	set iface enable tcpmssfix
178
	set iface mtu 1500
179

    
180
	set ipcp no vjcomp
181
	{$issue_ip_type}
182
	{$ipcp_dns}
183

    
184
	create link template poes_l pppoe
185
	set link action bundle poes_b
186

    
187
	set auth max-logins {$pppoemaxlogins}
188

    
189
	set pppoe iface {$pppoe_interface}
190

    
191
	set link no multilink
192
	set link no pap chap
193
	{$paporchap}
194
	set link keep-alive 60 180
195
	set link max-redial -1
196
	set link mru 1492
197
	set link latency 1
198
	set link enable incoming
199

    
200
EOD;
201

    
202
	if (array_path_enabled($pppoecfg, 'radius/server')) {
203
		$radiusport = array_get_path($pppoecfg, 'radius/server/port', '');
204
		$radiusacctport = array_get_path($pppoecfg, 'radius/server/acctport', '');
205
		$radiusip = array_get_path($pppoecfg, 'radius/server/ip', '');
206
		$radiussecret = array_get_path($pppoecfg, 'radius/server/secret', '');
207
		$mpdconf .= "\tset radius server {$radiusip} \"{$radiussecret}\" {$radiusport} {$radiusacctport}\n";
208

    
209
		if (array_path_enabled($pppoecfg, 'radius/server2')) {
210
			$radiusport = array_get_path($pppoecfg, 'radius/server2/port', '');
211
			$radiusacctport = array_get_path($pppoecfg, 'radius/server2/acctport', '');
212
			$radiusip = array_get_path($pppoecfg, 'radius/server2/ip', '');
213
			$radiussecret = array_get_path($pppoecfg, 'radius/server2/secret', '');
214
			$mpdconf .= "\tset radius server {$radiusip} \"{$radiussecret}\" {$radiusport} {$radiusacctport}\n";
215
		}
216

    
217
		$mpdconf .=<<<EOD
218
	set radius retries 3
219
	set radius timeout 10
220
	set auth enable radius-auth
221

    
222
EOD;
223

    
224
		if (array_path_enabled($pppoecfg, 'radius', 'accounting')) {
225
			$mpdconf .=<<<EOD
226
	set auth enable radius-acct
227

    
228
EOD;
229
		}
230
		$radiusacctupdate = array_get_path($pppoecfg, 'radius/server/acct_update', '');
231
		if (!empty($radiusacctupdate)) {
232
			$mpdconf .= "\tset auth acct-update {$radiusacctupdate}\n";
233
		}
234
		$radiusnasip = array_get_path($pppoecfg, 'radius/server/nasip', '');
235
		if (!empty($radiusnasip)) {
236
			$mpdconf .= "\tset radius me {$radiusnasip}\n";
237
		}
238
	}
239

    
240
	fwrite($fd, $mpdconf);
241
	fclose($fd);
242
	unset($mpdconf);
243

    
244
	vpn_pppoe_updatesecret($pppoecfg);
245

    
246
	/* Check if previous instance is still up */
247
	while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
248
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
249
	}
250

    
251
	/* fire up mpd */
252
	mwexec("/usr/local/sbin/mpd5 -b -d {$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn -p {$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid -s poes poes");
253

    
254
	if (is_platform_booting()) {
255
		echo gettext("done") . "\n";
256
	}
257

    
258
	return 0;
259
}
260

    
261
function vpn_pppoe_updatesecret(&$pppoecfg) {
262
	global $g;
263

    
264
	if ($pppoecfg['username']) {
265
		/* write mpd.secret */
266
		$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
267
		if (!$fd) {
268
			printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
269
			return 1;
270
		}
271

    
272
		$mpdsecret = "\n\n";
273

    
274
		if (!empty($pppoecfg['username'])) {
275
			$item = explode(" ", $pppoecfg['username']);
276
			foreach ($item as $userdata) {
277
				$data = explode(":", $userdata);
278
				/* Escape double quotes, do not allow password to start with '!'
279
				 * https://redmine.pfsense.org/issues/10275 */
280
				$pass = str_replace('"', '\"', ltrim(base64_decode($data[1]), '!'));
281
				$mpdsecret .= "{$data[0]} \"{$pass}\" {$data[2]}\n";
282
			}
283
		}
284

    
285
		fwrite($fd, $mpdsecret);
286
		fclose($fd);
287
		unset($mpdsecret);
288
		chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
289
		return 0;
290
	}
291
}
292

    
293
function vpn_l2tp_configure($interface = '') {
294
	global $g;
295

    
296
	$l2tpcfg = config_get_path('l2tp', []);
297
	if (empty($l2tpcfg)) {
298
		return false;
299
	}
300

    
301
	$dns_servers = get_dns_nameservers(false, true);
302
	if (empty($dns_servers) || !is_array($dns_servers)) {
303
		$dns_servers = ['127.0.0.1'];
304
	}
305

    
306
	$mode = array_get_path($l2tpcfg, 'mode', 'off');
307
	if (is_platform_booting()) {
308
		if ($mode == 'off') {
309
			rmdir_recursive("{$g['varetc_path']}/l2tp-vpn");
310
			return 0;
311
		}
312

    
313
		echo gettext("Configuring l2tp VPN service... ");
314
	} else {
315
		if (!empty($interface) &&
316
		    (array_get_path($l2tpcfg, 'interface') != $interface)) {
317
			return 0;
318
		}
319
		/* kill mpd */
320
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
321
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
322
		}
323

    
324
		/* wait for process to die */
325
		sleep(8);
326

    
327
	}
328

    
329
	if ($mode != 'server') {
330
		rmdir_recursive("{$g['varetc_path']}/l2tp-vpn");
331
		if (is_platform_booting()) {
332
			echo gettext("done") . "\n";
333
		}
334
		return true;
335
	}
336

    
337
	$l2tp_listen="";
338
	$ipaddr = get_interface_ip(get_failover_interface(array_get_path($l2tpcfg, 'interface')));
339
	if (is_ipaddrv4($ipaddr)) {
340
		$l2tp_listen="set l2tp self {$ipaddr}";
341
	}
342

    
343
	switch (array_get_path($l2tpcfg, 'paporchap')) {
344
		case 'chap':
345
			$paporchap = "set link enable chap";
346
			break;
347
		case 'chap-msv2':
348
			$paporchap = "set link enable chap-msv2";
349
			break;
350
		default:
351
			$paporchap = "set link enable pap";
352
			break;
353
	}
354

    
355
	/* create directory if it does not exist */
356
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
357
		mkdir("{$g['varetc_path']}/l2tp-vpn");
358
	}
359

    
360
	/* write mpd.conf */
361
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
362
	if (!$fd) {
363
		printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
364
		return 1;
365
	}
366

    
367

    
368
	$remoteip = array_get_path($l2tpcfg, 'remoteip');
369
	$ippool_p0 = ip_after($remoteip, (array_get_path($l2tpcfg, 'n_l2tp_units') - 1));
370

    
371
	$issue_ip_type = 'set ipcp ranges ' . array_get_path($l2tpcfg, 'localip') . '/32 ';
372

    
373
	if (array_path_enabled($l2tpcfg, 'radius', 'radiusissueips') &&
374
	    array_path_enabled($l2tpcfg, 'radius')) {
375
		$issue_ip_type .= "0.0.0.0/0";
376
		$ippool = "";
377
	} else {
378
		$issue_ip_type .= "ippool p0";
379
		$ippool = "set ippool add p0 {$remoteip} {$ippool_p0}";
380
	}
381

    
382
	$ipcp_dns = vpn_ppp_server_get_dns($l2tpcfg['dns1'], $l2tpcfg['dns2']);
383

    
384
	$mpdconf =<<<EOD
385

    
386
startup:
387

    
388
l2tps:
389
	{$ippool}
390

    
391
	create bundle template l2tp_b
392
	set bundle enable compression
393
	set bundle yes crypt-reqd
394

    
395
	set ccp yes mppc
396

    
397
	set iface name l2tps
398
	set iface group l2tp
399
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
400
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
401
	set iface disable on-demand
402
	set iface enable proxy-arp
403

    
404
	set ipcp yes vjcomp
405
	{$issue_ip_type}
406
	{$ipcp_dns}
407

    
408
	create link template l2tp_l l2tp
409
	set link action bundle l2tp_b
410

    
411
	set link yes acfcomp protocomp
412
	set link enable multilink
413
	set link no pap chap chap-msv2
414
	{$paporchap}
415
	{$l2tp_listen}
416
	set link keep-alive 10 180
417
	set link enable incoming
418

    
419
EOD;
420

    
421
	if (!empty($l2tpcfg['mtu'])) {
422
		$mpdconf .=<<<EOD
423
	set link mtu {$l2tpcfg['mtu']}
424

    
425
EOD;
426
	}
427

    
428
	if (!empty($l2tpcfg['secret'])) {
429
		$secret = str_replace('"', '\"', $l2tpcfg['secret']);
430
		$mpdconf .=<<<EOD
431
	set l2tp secret "{$secret}"
432

    
433
EOD;
434
	}
435

    
436
	if (array_path_enabled($l2tpcfg, 'radius')) {
437
		$radiusip = array_get_path($l2tpcfg, 'radius/server', '');
438
		$radiussecret = array_get_path($l2tpcfg, 'radius/secret', '');
439
		$mpdconf .=<<<EOD
440
	set radius server {$radiusip} "{$radiussecret}"
441
	set radius retries 3
442
	set radius timeout 10
443
	set auth disable internal
444
	set auth enable radius-auth
445

    
446
EOD;
447

    
448
		if (array_path_enabled($l2tpcfg, 'radius', 'accounting')) {
449
			$mpdconf .=<<<EOD
450
	set auth enable radius-acct
451

    
452
EOD;
453
		}
454
	}
455

    
456
	fwrite($fd, $mpdconf);
457
	fclose($fd);
458
	unset($mpdconf);
459

    
460
	vpn_l2tp_updatesecret();
461

    
462
	/* fire up mpd */
463
	mwexec("/usr/local/sbin/mpd5 -b -d {$g['varetc_path']}/l2tp-vpn -p {$g['varrun_path']}/l2tp-vpn.pid -s l2tps l2tps");
464

    
465
	if (is_platform_booting()) {
466
		echo "done\n";
467
	}
468

    
469
	return 0;
470
}
471

    
472
function vpn_l2tp_updatesecret() {
473
	global $g;
474
	$l2tpcfg = config_get_path('l2tp', []);
475

    
476
	if (empty($l2tpcfg)) {
477
		return false;
478
	}
479

    
480
	if (array_get_path($l2tpcfg, 'mode', 'off') != 'server') {
481
		return 0;
482
	}
483

    
484
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
485
	if (!$fd) {
486
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
487
		return 1;
488
	}
489

    
490
	$mpdsecret = "\n\n";
491

    
492
	foreach (array_get_path($l2tpcfg, 'user', []) as $user) {
493
		if (empty($user)) {
494
			continue;
495
		}
496
		/* Escape double quotes, do not allow password to start with '!'
497
		 * https://redmine.pfsense.org/issues/10275 */
498
		$pass = str_replace('"', '\"', ltrim($user['password'], '!'));
499
		$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
500
	}
501

    
502
	fwrite($fd, $mpdsecret);
503
	fclose($fd);
504
	unset($mpdsecret);
505
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
506

    
507
	return 0;
508
}
509

    
510
function l2tpusercmp($a, $b) {
511
	return strcasecmp($a['name'], $b['name']);
512
}
513

    
514
function l2tp_users_sort() {
515
	$users = config_get_path('l2tp/user', []);
516

    
517
	if (empty($users)) {
518
		return;
519
	}
520

    
521
	usort($users, "l2tpusercmp");
522
	config_set_path('l2tp/user', $users);
523
}
524

    
525
?>
(56-56/61)