Project

General

Profile

Download (12.9 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-2023 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) &&
66
			    ($dns != '127.0.0.1')) {
67
				$dns_servers[] = $dns;
68
			}
69
		}
70
	}
71

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

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

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

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

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

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

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

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

    
114
	}
115

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

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

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

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

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

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

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

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

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

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

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

    
163
	create bundle template poes_b
164
	set bundle enable compression
165

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

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

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

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

    
188
	set auth max-logins {$pppoemaxlogins}
189

    
190
	set pppoe iface {$pppoe_interface}
191

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

    
201
EOD;
202

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

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

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

    
223
EOD;
224

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

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

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

    
245
	vpn_pppoe_updatesecret($pppoecfg);
246

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

    
252
	/* fire up mpd */
253
	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");
254

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

    
259
	return 0;
260
}
261

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

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

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

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

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

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

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

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

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

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

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

    
328
	}
329

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

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

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

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

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

    
368

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

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

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

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

    
385
	$mpdconf =<<<EOD
386

    
387
startup:
388

    
389
l2tps:
390
	{$ippool}
391

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

    
396
	set ccp yes mppc
397

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

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

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

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

    
420
EOD;
421

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

    
426
EOD;
427
	}
428

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

    
434
EOD;
435
	}
436

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

    
447
EOD;
448

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

    
453
EOD;
454
		}
455
	}
456

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

    
461
	vpn_l2tp_updatesecret();
462

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

    
466
	if (platform_booting()) {
467
		echo "done\n";
468
	}
469

    
470
	return 0;
471
}
472

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

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

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

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

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

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

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

    
508
	return 0;
509
}
510

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

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

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

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

    
526
?>
(56-56/61)