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
	/* create directory if it does not exist */
297
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
298
		mkdir("{$g['varetc_path']}/l2tp-vpn");
299
	}
300

    
301
	if (platform_booting()) {
302
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
303
			return 0;
304
		}
305

    
306
		echo gettext("Configuring l2tp VPN service... ");
307
	} else {
308
		/* kill mpd */
309
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
310
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
311
		}
312

    
313
		/* wait for process to die */
314
		sleep(8);
315

    
316
	}
317

    
318
	/* make sure l2tp-vpn directory exists */
319
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
320
		mkdir("{$g['varetc_path']}/l2tp-vpn");
321
	}
322

    
323
	switch ($l2tpcfg['mode']) {
324

    
325
		case 'server':
326
			$l2tp_listen="";
327
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
328
			if (is_ipaddrv4($ipaddr)) {
329
				$l2tp_listen="set l2tp self $ipaddr";
330
			}
331

    
332
			switch ($l2tpcfg['paporchap']) {
333
				case 'chap':
334
					$paporchap = "set link enable chap";
335
					break;
336
				case 'chap-msv2':
337
					$paporchap = "set link enable chap-msv2";
338
					break;
339
				default:
340
					$paporchap = "set link enable pap";
341
					break;
342
			}
343

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

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

    
353
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
354
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['enable'])) {
355
				$issue_ip_type .= "0.0.0.0/0";
356
				$ippool = "";
357
			} else {
358
				$issue_ip_type .= "ippool p0";
359
				$ippool = "set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}";
360
			}
361

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

    
379
			$mpdconf =<<<EOD
380

    
381
startup:
382

    
383
l2tps:
384
	{$ippool}
385

    
386
	create bundle template l2tp_b
387
	set bundle enable compression
388
	set bundle yes crypt-reqd
389

    
390
	set ccp yes mppc
391

    
392
	set iface name l2tps
393
	set iface group l2tp
394
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
395
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
396
	set iface disable on-demand
397
	set iface enable proxy-arp
398

    
399
	set ipcp yes vjcomp
400
	{$issue_ip_type}
401
	{$ipcp_dns}
402

    
403
	create link template l2tp_l l2tp
404
	set link action bundle l2tp_b
405

    
406
	set link yes acfcomp protocomp
407
	set link enable multilink
408
	set link no pap chap chap-msv2
409
	{$paporchap}
410
	{$l2tp_listen}
411
	set link keep-alive 10 180
412
	set link enable incoming
413

    
414
EOD;
415
			if (!empty($l2tpcfg['secret'])) {
416
				$secret = str_replace('"', '\"', $l2tpcfg['secret']);
417
				$mpdconf .=<<<EOD
418
	set l2tp secret "{$secret}"
419

    
420
EOD;
421
			}
422

    
423

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

    
432
EOD;
433

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

    
438
EOD;
439
				}
440
			}
441

    
442
			fwrite($fd, $mpdconf);
443
			fclose($fd);
444
			unset($mpdconf);
445

    
446
			vpn_l2tp_updatesecret();
447
			vpn_netgraph_support();
448

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

    
452
			break;
453

    
454
		case 'redir':
455
			break;
456
	}
457

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

    
462
	return 0;
463
}
464

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

    
469
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
470
	if (!$fd) {
471
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
472
		return 1;
473
	}
474

    
475
	$mpdsecret = "\n\n";
476

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

    
486
	fwrite($fd, $mpdsecret);
487
	fclose($fd);
488
	unset($mpdsecret);
489
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
490

    
491
	return 0;
492
}
493

    
494
function l2tpusercmp($a, $b) {
495
	return strcasecmp($a['name'], $b['name']);
496
}
497

    
498
function l2tp_users_sort() {
499
	global $config;
500

    
501
	if (!is_array($config['l2tp']['user'])) {
502
		return;
503
	}
504

    
505
	usort($config['l2tp']['user'], "l2tpusercmp");
506
}
507

    
508
?>
(55-55/61)