Project

General

Profile

Download (12.7 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-2020 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 group pppoe
158
	set iface up-script /usr/local/sbin/vpn-linkup-poes
159
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
160
	set iface idle 0
161
	set iface disable on-demand
162
	set iface disable proxy-arp
163
	set iface enable tcpmssfix
164
	set iface mtu 1500
165

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

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

    
173
	set auth max-logins {$pppoemaxlogins}
174

    
175
	set pppoe iface {$pppoe_interface}
176

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

    
186
EOD;
187

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

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

    
215
EOD;
216

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

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

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

    
235
			vpn_pppoe_updatesecret($pppoecfg);
236

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

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

    
247
			break;
248
	}
249

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

    
254
	return 0;
255
}
256

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

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

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

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

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

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

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

    
295
	/* create directory if it does not exist */
296
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
297
		mkdir("{$g['varetc_path']}/l2tp-vpn");
298
	}
299

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

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

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

    
315
	}
316

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

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

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

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

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

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

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

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

    
378
			$mpdconf =<<<EOD
379

    
380
startup:
381

    
382
l2tps:
383
	{$ippool}
384

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

    
389
	set ccp yes mppc
390

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

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

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

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

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

    
419
EOD;
420
			}
421

    
422

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

    
431
EOD;
432

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

    
437
EOD;
438
				}
439
			}
440

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

    
445
			vpn_l2tp_updatesecret();
446
			vpn_netgraph_support();
447

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

    
451
			break;
452

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

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

    
461
	return 0;
462
}
463

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

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

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

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

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

    
490
	return 0;
491
}
492

    
493
?>
(55-55/61)