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-2021 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_netgraph_support() {
44
	$iflist = get_configured_interface_list();
45
	foreach ($iflist as $iface) {
46
		$realif = get_real_interface($iface);
47
		/* Get support for netgraph(4) from the nic */
48
		$ifinfo = pfSense_get_interface_addresses($realif);
49
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) {
50
			pfSense_ngctl_attach(".", $realif);
51
		}
52
	}
53
}
54

    
55
function vpn_pppoes_configure() {
56
	global $config;
57

    
58
	if (is_array($config['pppoes']['pppoe'])) {
59
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
60
			vpn_pppoe_configure($pppoe);
61
		}
62
	}
63
}
64

    
65
function vpn_pppoe_configure(&$pppoecfg) {
66
	global $config, $g;
67

    
68
	$syscfg = $config['system'];
69

    
70
	/* create directory if it does not exist */
71
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
72
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
73
	}
74

    
75
	if (platform_booting()) {
76
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
77
			return 0;
78
		}
79

    
80
		echo gettext("Configuring PPPoE Server service... ");
81
	} else {
82
		/* kill mpd */
83
		if (isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
84
			killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
85
		}
86

    
87
		/* wait for process to die */
88
		sleep(2);
89

    
90
	}
91

    
92
	switch ($pppoecfg['mode']) {
93

    
94
		case 'server':
95

    
96
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
97

    
98
			if ($pppoecfg['paporchap'] == "chap") {
99
				$paporchap = "set link enable chap";
100
			} else {
101
				$paporchap = "set link enable pap";
102
			}
103

    
104
			/* write mpd.conf */
105
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
106
			if (!$fd) {
107
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
108
				return 1;
109
			}
110

    
111
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
112
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
113
				$issue_ip_type .= "0.0.0.0/0";
114
			} else {
115
				$issue_ip_type .= "ippool p0";
116
			}
117

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

    
120
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
121
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
122
			} else {
123
				$pppoemaxlogins = 1;
124
			}
125

    
126
			$ipcp_dns = '';
127
			if (!empty($pppoecfg['dns1'])) {
128
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
129
				if (!empty($pppoecfg['dns2'])) {
130
					$ipcp_dns .= " " . $pppoecfg['dns2'];
131
				}
132
			} elseif (isset($config['dnsmasq']['enable']) ||
133
			    isset ($config['unbound']['enable'])) {
134
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
135
				if ($syscfg['dnsserver'][0]) {
136
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
137
				}
138
			} elseif (is_array($syscfg['dnsserver']) &&
139
			    ($syscfg['dnsserver'][0])) {
140
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
141
			}
142

    
143
			$mpdconf = <<<EOD
144
startup:
145

    
146
poes:
147
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
148

    
149
	create bundle template poes_b
150
	set bundle enable compression
151

    
152
	set ccp yes mppc
153
	set mppc yes e40
154
	set mppc yes e128
155
	set mppc yes stateless
156

    
157
	set iface name poes{$pppoecfg['pppoeid']}-
158
	set iface group pppoe
159
	set iface up-script /usr/local/sbin/vpn-linkup-poes
160
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
161
	set iface idle 0
162
	set iface disable on-demand
163
	set iface disable proxy-arp
164
	set iface enable tcpmssfix
165
	set iface mtu 1500
166

    
167
	set ipcp no vjcomp
168
	{$issue_ip_type}
169
	{$ipcp_dns}
170

    
171
	create link template poes_l pppoe
172
	set link action bundle poes_b
173

    
174
	set auth max-logins {$pppoemaxlogins}
175

    
176
	set pppoe iface {$pppoe_interface}
177

    
178
	set link no multilink
179
	set link no pap chap
180
	{$paporchap}
181
	set link keep-alive 60 180
182
	set link max-redial -1
183
	set link mru 1492
184
	set link latency 1
185
	set link enable incoming
186

    
187
EOD;
188

    
189
			if (isset ($pppoecfg['radius']['server']['enable'])) {
190
				$radiusport = "";
191
				$radiusacctport = "";
192
				if (isset($pppoecfg['radius']['server']['port'])) {
193
					$radiusport = $pppoecfg['radius']['server']['port'];
194
				}
195
				if (isset($pppoecfg['radius']['server']['acctport'])) {
196
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
197
				}
198
				$mpdconf .= "\tset radius server {$pppoecfg['radius']['server']['ip']} \"{$pppoecfg['radius']['server']['secret']}\" {$radiusport} {$radiusacctport}\n";
199
				if (isset($pppoecfg['radius']['server2']['enable'])) {
200
					$radiusport = "";
201
					$radiusacctport = "";
202
					if (isset($pppoecfg['radius']['server2']['port'])) {
203
						$radiusport = $pppoecfg['radius']['server2']['port'];
204
					}
205
					if (isset($pppoecfg['radius']['server2']['acctport'])) {
206
						$radiusacctport = $pppoecfg['radius']['server2']['acctport'];
207
					}
208
					$mpdconf .= "\tset radius server {$pppoecfg['radius']['server2']['ip']} \"{$pppoecfg['radius']['server2']['secret2']}\" {$radiusport} {$radiusacctport}\n";
209
				}
210

    
211
				$mpdconf .=<<<EOD
212
	set radius retries 3
213
	set radius timeout 10
214
	set auth enable radius-auth
215

    
216
EOD;
217

    
218
				if (isset ($pppoecfg['radius']['accounting'])) {
219
					$mpdconf .=<<<EOD
220
	set auth enable radius-acct
221

    
222
EOD;
223
				}
224
				if (!empty($pppoecfg['radius']['acct_update'])) {
225
					$mpdconf .= "\tset auth acct-update {$pppoecfg['radius']['acct_update']}\n";
226
				}
227
				if (!empty($pppoecfg['radius']['nasip'])) {
228
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
229
				}
230
			}
231

    
232
			fwrite($fd, $mpdconf);
233
			fclose($fd);
234
			unset($mpdconf);
235

    
236
			vpn_pppoe_updatesecret($pppoecfg);
237

    
238
			/* Check if previous instance is still up */
239
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
240
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
241
			}
242

    
243
			/* Get support for netgraph(4) from the nic */
244
			pfSense_ngctl_attach(".", $pppoe_interface);
245
			/* fire up mpd */
246
			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");
247

    
248
			break;
249
	}
250

    
251
	if (platform_booting()) {
252
		echo gettext("done") . "\n";
253
	}
254

    
255
	return 0;
256
}
257

    
258
function vpn_pppoe_updatesecret(&$pppoecfg) {
259
	global $config, $g;
260

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

    
269
		$mpdsecret = "\n\n";
270

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

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

    
290
function vpn_l2tp_configure() {
291
	global $config, $g;
292

    
293
	$syscfg = $config['system'];
294
	$l2tpcfg = $config['l2tp'];
295

    
296
	if (platform_booting()) {
297
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
298
			return 0;
299
		}
300

    
301
		echo gettext("Configuring l2tp VPN service... ");
302
	} else {
303
		/* kill mpd */
304
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
305
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
306
		}
307

    
308
		/* wait for process to die */
309
		sleep(8);
310

    
311
	}
312

    
313
	switch ($l2tpcfg['mode']) {
314

    
315
		case 'server':
316
			$l2tp_listen="";
317
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
318
			if (is_ipaddrv4($ipaddr)) {
319
				$l2tp_listen="set l2tp self $ipaddr";
320
			}
321

    
322
			switch ($l2tpcfg['paporchap']) {
323
				case 'chap':
324
					$paporchap = "set link enable chap";
325
					break;
326
				case 'chap-msv2':
327
					$paporchap = "set link enable chap-msv2";
328
					break;
329
				default:
330
					$paporchap = "set link enable pap";
331
					break;
332
			}
333

    
334
			/* create directory if it does not exist */
335
			if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
336
				mkdir("{$g['varetc_path']}/l2tp-vpn");
337
			}
338

    
339
			/* write mpd.conf */
340
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
341
			if (!$fd) {
342
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
343
				return 1;
344
			}
345

    
346
			$ippool_p0 = ip_after($l2tpcfg['remoteip'], $l2tpcfg['n_l2tp_units'] - 1);
347

    
348
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
349
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['enable'])) {
350
				$issue_ip_type .= "0.0.0.0/0";
351
				$ippool = "";
352
			} else {
353
				$issue_ip_type .= "ippool p0";
354
				$ippool = "set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}";
355
			}
356

    
357
			$ipcp_dns = '';
358
			if (is_ipaddr($l2tpcfg['dns1'])) {
359
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
360
				if (is_ipaddr($l2tpcfg['dns2'])) {
361
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
362
				}
363
			} elseif (isset ($config['dnsmasq']['enable']) ||
364
			    isset ($config['unbound']['enable'])) {
365
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
366
				if ($syscfg['dnsserver'][0]) {
367
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
368
				}
369
			} elseif (is_array($syscfg['dnsserver']) &&
370
			    ($syscfg['dnsserver'][0])) {
371
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
372
			}
373

    
374
			$mpdconf =<<<EOD
375

    
376
startup:
377

    
378
l2tps:
379
	{$ippool}
380

    
381
	create bundle template l2tp_b
382
	set bundle enable compression
383
	set bundle yes crypt-reqd
384

    
385
	set ccp yes mppc
386

    
387
	set iface name l2tps
388
	set iface group l2tp
389
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
390
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
391
	set iface disable on-demand
392
	set iface enable proxy-arp
393

    
394
	set ipcp yes vjcomp
395
	{$issue_ip_type}
396
	{$ipcp_dns}
397

    
398
	create link template l2tp_l l2tp
399
	set link action bundle l2tp_b
400

    
401
	set link yes acfcomp protocomp
402
	set link enable multilink
403
	set link no pap chap chap-msv2
404
	{$paporchap}
405
	{$l2tp_listen}
406
	set link keep-alive 10 180
407
	set link enable incoming
408

    
409
EOD;
410

    
411
			if (!empty($l2tpcfg['mtu'])) {
412
				$mpdconf .=<<<EOD
413
	set link mtu {$l2tpcfg['mtu']}
414

    
415
EOD;
416
			}
417

    
418
			if (!empty($l2tpcfg['secret'])) {
419
				$secret = str_replace('"', '\"', $l2tpcfg['secret']);
420
				$mpdconf .=<<<EOD
421
	set l2tp secret "{$secret}"
422

    
423
EOD;
424
			}
425

    
426
			if (isset ($l2tpcfg['radius']['enable'])) {
427
				$mpdconf .=<<<EOD
428
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
429
	set radius retries 3
430
	set radius timeout 10
431
	set auth disable internal
432
	set auth enable radius-auth
433

    
434
EOD;
435

    
436
				if (isset ($l2tpcfg['radius']['accounting'])) {
437
					$mpdconf .=<<<EOD
438
	set auth enable radius-acct
439

    
440
EOD;
441
				}
442
			}
443

    
444
			fwrite($fd, $mpdconf);
445
			fclose($fd);
446
			unset($mpdconf);
447

    
448
			vpn_l2tp_updatesecret();
449
			vpn_netgraph_support();
450

    
451
			/* fire up mpd */
452
			mwexec("/usr/local/sbin/mpd5 -b -d {$g['varetc_path']}/l2tp-vpn -p {$g['varrun_path']}/l2tp-vpn.pid -s l2tps l2tps");
453
			break;
454
		default:
455
			rmdir_recursive("{$g['varetc_path']}/l2tp-vpn");
456
			break;
457
	}
458

    
459
	if (platform_booting()) {
460
		echo "done\n";
461
	}
462

    
463
	return 0;
464
}
465

    
466
function vpn_l2tp_updatesecret() {
467
	global $config, $g;
468
	$l2tpcfg = $config['l2tp'];
469

    
470
	if ($l2tpcfg['mode'] != 'server') {
471
		return 0;
472
	}
473

    
474
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
475
	if (!$fd) {
476
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
477
		return 1;
478
	}
479

    
480
	$mpdsecret = "\n\n";
481

    
482
	if (is_array($l2tpcfg['user'])) {
483
		foreach ($l2tpcfg['user'] as $user) {
484
			/* Escape double quotes, do not allow password to start with '!'
485
			 * https://redmine.pfsense.org/issues/10275 */
486
			$pass = str_replace('"', '\"', ltrim($user['password'], '!'));
487
			$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
488
		}
489
	}
490

    
491
	fwrite($fd, $mpdsecret);
492
	fclose($fd);
493
	unset($mpdsecret);
494
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
495

    
496
	return 0;
497
}
498

    
499
function l2tpusercmp($a, $b) {
500
	return strcasecmp($a['name'], $b['name']);
501
}
502

    
503
function l2tp_users_sort() {
504
	global $config;
505

    
506
	if (!is_array($config['l2tp']['user'])) {
507
		return;
508
	}
509

    
510
	usort($config['l2tp']['user'], "l2tpusercmp");
511
}
512

    
513
?>
(55-55/61)