Project

General

Profile

Download (12.6 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-2022 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_pppoes_configure() {
44
	global $config;
45

    
46
	if (is_array($config['pppoes']['pppoe'])) {
47
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
48
			vpn_pppoe_configure($pppoe);
49
		}
50
	}
51
}
52

    
53
function vpn_pppoe_configure(&$pppoecfg) {
54
	global $config, $g;
55

    
56
	$syscfg = $config['system'];
57

    
58
	/* create directory if it does not exist */
59
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
60
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
61
	}
62

    
63
	if (platform_booting()) {
64
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
65
			return 0;
66
		}
67

    
68
		echo gettext("Configuring PPPoE Server service... ");
69
	} else {
70
		/* kill mpd */
71
		if (isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
72
			killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
73
		}
74

    
75
		/* wait for process to die */
76
		sleep(2);
77

    
78
	}
79

    
80
	switch ($pppoecfg['mode']) {
81

    
82
		case 'server':
83

    
84
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
85

    
86
			if ($pppoecfg['paporchap'] == "chap") {
87
				$paporchap = "set link enable chap";
88
			} else {
89
				$paporchap = "set link enable pap";
90
			}
91

    
92
			/* write mpd.conf */
93
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
94
			if (!$fd) {
95
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
96
				return 1;
97
			}
98

    
99
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
100
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
101
				$issue_ip_type .= "0.0.0.0/0";
102
			} else {
103
				$issue_ip_type .= "ippool p0";
104
			}
105

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

    
108
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
109
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
110
			} else {
111
				$pppoemaxlogins = 1;
112
			}
113

    
114
			$ipcp_dns = '';
115
			if (!empty($pppoecfg['dns1'])) {
116
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
117
				if (!empty($pppoecfg['dns2'])) {
118
					$ipcp_dns .= " " . $pppoecfg['dns2'];
119
				}
120
			} elseif (isset($config['dnsmasq']['enable']) ||
121
			    isset ($config['unbound']['enable'])) {
122
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
123
				if ($syscfg['dnsserver'][0]) {
124
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
125
				}
126
			} elseif (is_array($syscfg['dnsserver']) &&
127
			    ($syscfg['dnsserver'][0])) {
128
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
129
			}
130

    
131
			$mpdconf = <<<EOD
132
startup:
133

    
134
poes:
135
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
136

    
137
	create bundle template poes_b
138
	set bundle enable compression
139

    
140
	set ccp yes mppc
141
	set mppc yes e40
142
	set mppc yes e128
143
	set mppc yes stateless
144

    
145
	set iface name poes{$pppoecfg['pppoeid']}-
146
	set iface group pppoe
147
	set iface up-script /usr/local/sbin/vpn-linkup-poes
148
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
149
	set iface idle 0
150
	set iface disable on-demand
151
	set iface disable proxy-arp
152
	set iface enable tcpmssfix
153
	set iface mtu 1500
154

    
155
	set ipcp no vjcomp
156
	{$issue_ip_type}
157
	{$ipcp_dns}
158

    
159
	create link template poes_l pppoe
160
	set link action bundle poes_b
161

    
162
	set auth max-logins {$pppoemaxlogins}
163

    
164
	set pppoe iface {$pppoe_interface}
165

    
166
	set link no multilink
167
	set link no pap chap
168
	{$paporchap}
169
	set link keep-alive 60 180
170
	set link max-redial -1
171
	set link mru 1492
172
	set link latency 1
173
	set link enable incoming
174

    
175
EOD;
176

    
177
			if (isset ($pppoecfg['radius']['server']['enable'])) {
178
				$radiusport = "";
179
				$radiusacctport = "";
180
				if (isset($pppoecfg['radius']['server']['port'])) {
181
					$radiusport = $pppoecfg['radius']['server']['port'];
182
				}
183
				if (isset($pppoecfg['radius']['server']['acctport'])) {
184
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
185
				}
186
				$mpdconf .= "\tset radius server {$pppoecfg['radius']['server']['ip']} \"{$pppoecfg['radius']['server']['secret']}\" {$radiusport} {$radiusacctport}\n";
187
				if (isset($pppoecfg['radius']['server2']['enable'])) {
188
					$radiusport = "";
189
					$radiusacctport = "";
190
					if (isset($pppoecfg['radius']['server2']['port'])) {
191
						$radiusport = $pppoecfg['radius']['server2']['port'];
192
					}
193
					if (isset($pppoecfg['radius']['server2']['acctport'])) {
194
						$radiusacctport = $pppoecfg['radius']['server2']['acctport'];
195
					}
196
					$mpdconf .= "\tset radius server {$pppoecfg['radius']['server2']['ip']} \"{$pppoecfg['radius']['server2']['secret2']}\" {$radiusport} {$radiusacctport}\n";
197
				}
198

    
199
				$mpdconf .=<<<EOD
200
	set radius retries 3
201
	set radius timeout 10
202
	set auth enable radius-auth
203

    
204
EOD;
205

    
206
				if (isset ($pppoecfg['radius']['accounting'])) {
207
					$mpdconf .=<<<EOD
208
	set auth enable radius-acct
209

    
210
EOD;
211
				}
212
				if (!empty($pppoecfg['radius']['acct_update'])) {
213
					$mpdconf .= "\tset auth acct-update {$pppoecfg['radius']['acct_update']}\n";
214
				}
215
				if (!empty($pppoecfg['radius']['nasip'])) {
216
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
217
				}
218
			}
219

    
220
			fwrite($fd, $mpdconf);
221
			fclose($fd);
222
			unset($mpdconf);
223

    
224
			vpn_pppoe_updatesecret($pppoecfg);
225

    
226
			/* Check if previous instance is still up */
227
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
228
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
229
			}
230

    
231
			/* fire up mpd */
232
			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");
233

    
234
			break;
235
	}
236

    
237
	if (platform_booting()) {
238
		echo gettext("done") . "\n";
239
	}
240

    
241
	return 0;
242
}
243

    
244
function vpn_pppoe_updatesecret(&$pppoecfg) {
245
	global $config, $g;
246

    
247
	if ($pppoecfg['username']) {
248
		/* write mpd.secret */
249
		$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
250
		if (!$fd) {
251
			printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
252
			return 1;
253
		}
254

    
255
		$mpdsecret = "\n\n";
256

    
257
		if (!empty($pppoecfg['username'])) {
258
			$item = explode(" ", $pppoecfg['username']);
259
			foreach ($item as $userdata) {
260
				$data = explode(":", $userdata);
261
				/* Escape double quotes, do not allow password to start with '!'
262
				 * https://redmine.pfsense.org/issues/10275 */
263
				$pass = str_replace('"', '\"', ltrim(base64_decode($data[1]), '!'));
264
				$mpdsecret .= "{$data[0]} \"{$pass}\" {$data[2]}\n";
265
			}
266
		}
267

    
268
		fwrite($fd, $mpdsecret);
269
		fclose($fd);
270
		unset($mpdsecret);
271
		chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
272
		return 0;
273
	}
274
}
275

    
276
function vpn_l2tp_configure($interface = '') {
277
	global $config, $g;
278

    
279
	$syscfg = $config['system'];
280
	$l2tpcfg = $config['l2tp'];
281

    
282
	if (platform_booting()) {
283
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
284
			return 0;
285
		}
286

    
287
		echo gettext("Configuring l2tp VPN service... ");
288
	} else {
289
		if (!empty($interface) && ($l2tpcfg['interface'] != $interface)) {
290
			return 0;
291
		}
292
		/* kill mpd */
293
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
294
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
295
		}
296

    
297
		/* wait for process to die */
298
		sleep(8);
299

    
300
	}
301

    
302
	switch ($l2tpcfg['mode']) {
303

    
304
		case 'server':
305
			$l2tp_listen="";
306
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
307
			if (is_ipaddrv4($ipaddr)) {
308
				$l2tp_listen="set l2tp self $ipaddr";
309
			}
310

    
311
			switch ($l2tpcfg['paporchap']) {
312
				case 'chap':
313
					$paporchap = "set link enable chap";
314
					break;
315
				case 'chap-msv2':
316
					$paporchap = "set link enable chap-msv2";
317
					break;
318
				default:
319
					$paporchap = "set link enable pap";
320
					break;
321
			}
322

    
323
			/* create directory if it does not exist */
324
			if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
325
				mkdir("{$g['varetc_path']}/l2tp-vpn");
326
			}
327

    
328
			/* write mpd.conf */
329
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
330
			if (!$fd) {
331
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
332
				return 1;
333
			}
334

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

    
337
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
338
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['enable'])) {
339
				$issue_ip_type .= "0.0.0.0/0";
340
				$ippool = "";
341
			} else {
342
				$issue_ip_type .= "ippool p0";
343
				$ippool = "set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}";
344
			}
345

    
346
			$ipcp_dns = '';
347
			if (is_ipaddr($l2tpcfg['dns1'])) {
348
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
349
				if (is_ipaddr($l2tpcfg['dns2'])) {
350
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
351
				}
352
			} elseif (isset ($config['dnsmasq']['enable']) ||
353
			    isset ($config['unbound']['enable'])) {
354
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
355
				if ($syscfg['dnsserver'][0]) {
356
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
357
				}
358
			} elseif (is_array($syscfg['dnsserver']) &&
359
			    ($syscfg['dnsserver'][0])) {
360
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
361
			}
362

    
363
			$mpdconf =<<<EOD
364

    
365
startup:
366

    
367
l2tps:
368
	{$ippool}
369

    
370
	create bundle template l2tp_b
371
	set bundle enable compression
372
	set bundle yes crypt-reqd
373

    
374
	set ccp yes mppc
375

    
376
	set iface name l2tps
377
	set iface group l2tp
378
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
379
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
380
	set iface disable on-demand
381
	set iface enable proxy-arp
382

    
383
	set ipcp yes vjcomp
384
	{$issue_ip_type}
385
	{$ipcp_dns}
386

    
387
	create link template l2tp_l l2tp
388
	set link action bundle l2tp_b
389

    
390
	set link yes acfcomp protocomp
391
	set link enable multilink
392
	set link no pap chap chap-msv2
393
	{$paporchap}
394
	{$l2tp_listen}
395
	set link keep-alive 10 180
396
	set link enable incoming
397

    
398
EOD;
399

    
400
			if (!empty($l2tpcfg['mtu'])) {
401
				$mpdconf .=<<<EOD
402
	set link mtu {$l2tpcfg['mtu']}
403

    
404
EOD;
405
			}
406

    
407
			if (!empty($l2tpcfg['secret'])) {
408
				$secret = str_replace('"', '\"', $l2tpcfg['secret']);
409
				$mpdconf .=<<<EOD
410
	set l2tp secret "{$secret}"
411

    
412
EOD;
413
			}
414

    
415
			if (isset ($l2tpcfg['radius']['enable'])) {
416
				$mpdconf .=<<<EOD
417
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
418
	set radius retries 3
419
	set radius timeout 10
420
	set auth disable internal
421
	set auth enable radius-auth
422

    
423
EOD;
424

    
425
				if (isset ($l2tpcfg['radius']['accounting'])) {
426
					$mpdconf .=<<<EOD
427
	set auth enable radius-acct
428

    
429
EOD;
430
				}
431
			}
432

    
433
			fwrite($fd, $mpdconf);
434
			fclose($fd);
435
			unset($mpdconf);
436

    
437
			vpn_l2tp_updatesecret();
438

    
439
			/* fire up mpd */
440
			mwexec("/usr/local/sbin/mpd5 -b -d {$g['varetc_path']}/l2tp-vpn -p {$g['varrun_path']}/l2tp-vpn.pid -s l2tps l2tps");
441
			break;
442
		default:
443
			rmdir_recursive("{$g['varetc_path']}/l2tp-vpn");
444
			break;
445
	}
446

    
447
	if (platform_booting()) {
448
		echo "done\n";
449
	}
450

    
451
	return 0;
452
}
453

    
454
function vpn_l2tp_updatesecret() {
455
	global $config, $g;
456
	$l2tpcfg = $config['l2tp'];
457

    
458
	if ($l2tpcfg['mode'] != 'server') {
459
		return 0;
460
	}
461

    
462
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
463
	if (!$fd) {
464
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
465
		return 1;
466
	}
467

    
468
	$mpdsecret = "\n\n";
469

    
470
	if (is_array($l2tpcfg['user'])) {
471
		foreach ($l2tpcfg['user'] as $user) {
472
			/* Escape double quotes, do not allow password to start with '!'
473
			 * https://redmine.pfsense.org/issues/10275 */
474
			$pass = str_replace('"', '\"', ltrim($user['password'], '!'));
475
			$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
476
		}
477
	}
478

    
479
	fwrite($fd, $mpdsecret);
480
	fclose($fd);
481
	unset($mpdsecret);
482
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
483

    
484
	return 0;
485
}
486

    
487
function l2tpusercmp($a, $b) {
488
	return strcasecmp($a['name'], $b['name']);
489
}
490

    
491
function l2tp_users_sort() {
492
	global $config;
493

    
494
	if (!is_array($config['l2tp']['user'])) {
495
		return;
496
	}
497

    
498
	usort($config['l2tp']['user'], "l2tpusercmp");
499
}
500

    
501
?>
(55-55/61)