Project

General

Profile

Download (12.5 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() {
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
		/* kill mpd */
290
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
291
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
292
		}
293

    
294
		/* wait for process to die */
295
		sleep(8);
296

    
297
	}
298

    
299
	switch ($l2tpcfg['mode']) {
300

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

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

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

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

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

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

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

    
360
			$mpdconf =<<<EOD
361

    
362
startup:
363

    
364
l2tps:
365
	{$ippool}
366

    
367
	create bundle template l2tp_b
368
	set bundle enable compression
369
	set bundle yes crypt-reqd
370

    
371
	set ccp yes mppc
372

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

    
380
	set ipcp yes vjcomp
381
	{$issue_ip_type}
382
	{$ipcp_dns}
383

    
384
	create link template l2tp_l l2tp
385
	set link action bundle l2tp_b
386

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

    
395
EOD;
396

    
397
			if (!empty($l2tpcfg['mtu'])) {
398
				$mpdconf .=<<<EOD
399
	set link mtu {$l2tpcfg['mtu']}
400

    
401
EOD;
402
			}
403

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

    
409
EOD;
410
			}
411

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

    
420
EOD;
421

    
422
				if (isset ($l2tpcfg['radius']['accounting'])) {
423
					$mpdconf .=<<<EOD
424
	set auth enable radius-acct
425

    
426
EOD;
427
				}
428
			}
429

    
430
			fwrite($fd, $mpdconf);
431
			fclose($fd);
432
			unset($mpdconf);
433

    
434
			vpn_l2tp_updatesecret();
435

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

    
444
	if (platform_booting()) {
445
		echo "done\n";
446
	}
447

    
448
	return 0;
449
}
450

    
451
function vpn_l2tp_updatesecret() {
452
	global $config, $g;
453
	$l2tpcfg = $config['l2tp'];
454

    
455
	if ($l2tpcfg['mode'] != 'server') {
456
		return 0;
457
	}
458

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

    
465
	$mpdsecret = "\n\n";
466

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

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

    
481
	return 0;
482
}
483

    
484
function l2tpusercmp($a, $b) {
485
	return strcasecmp($a['name'], $b['name']);
486
}
487

    
488
function l2tp_users_sort() {
489
	global $config;
490

    
491
	if (!is_array($config['l2tp']['user'])) {
492
		return;
493
	}
494

    
495
	usort($config['l2tp']['user'], "l2tpusercmp");
496
}
497

    
498
?>
(55-55/61)