Project

General

Profile

Download (11.8 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 .=<<<EOD
198
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
199
	set radius retries 3
200
	set radius timeout 10
201
	set auth enable radius-auth
202

    
203
EOD;
204

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

    
209
EOD;
210
				}
211
				if (!empty($pppoecfg['radius']['nasip'])) {
212
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
213
				}
214
			}
215

    
216
			fwrite($fd, $mpdconf);
217
			fclose($fd);
218
			unset($mpdconf);
219

    
220
			if ($pppoecfg['username']) {
221
				/* write mpd.secret */
222
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
223
				if (!$fd) {
224
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
225
					return 1;
226
				}
227

    
228
				$mpdsecret = "\n\n";
229

    
230
				if (!empty($pppoecfg['username'])) {
231
					$item = explode(" ", $pppoecfg['username']);
232
					foreach ($item as $userdata) {
233
						$data = explode(":", $userdata);
234
						/* Escape double quotes, do not allow password to start with '!'
235
						 * https://redmine.pfsense.org/issues/10275 */
236
						$pass = str_replace('"', '\"', ltrim(base64_decode($data[1]), '!'));
237
						$mpdsecret .= "{$data[0]} \"{$pass}\" {$data[2]}\n";
238
					}
239
				}
240

    
241
				fwrite($fd, $mpdsecret);
242
				fclose($fd);
243
				unset($mpdsecret);
244
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
245
			}
246

    
247
			/* Check if previous instance is still up */
248
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
249
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
250
			}
251

    
252
			/* Get support for netgraph(4) from the nic */
253
			pfSense_ngctl_attach(".", $pppoe_interface);
254
			/* fire up mpd */
255
			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");
256

    
257
			break;
258
	}
259

    
260
	if (platform_booting()) {
261
		echo gettext("done") . "\n";
262
	}
263

    
264
	return 0;
265
}
266

    
267
function vpn_l2tp_configure() {
268
	global $config, $g;
269

    
270
	$syscfg = $config['system'];
271
	$l2tpcfg = $config['l2tp'];
272

    
273
	/* create directory if it does not exist */
274
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
275
		mkdir("{$g['varetc_path']}/l2tp-vpn");
276
	}
277

    
278
	if (platform_booting()) {
279
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
280
			return 0;
281
		}
282

    
283
		echo gettext("Configuring l2tp VPN service... ");
284
	} else {
285
		/* kill mpd */
286
		if (isvalidpid("{$g['varrun_path']}/l2tp-vpn.pid")) {
287
			killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
288
		}
289

    
290
		/* wait for process to die */
291
		sleep(8);
292

    
293
	}
294

    
295
	/* make sure l2tp-vpn directory exists */
296
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
297
		mkdir("{$g['varetc_path']}/l2tp-vpn");
298
	}
299

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

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

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

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

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

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

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

    
356
			$mpdconf =<<<EOD
357

    
358
startup:
359

    
360
l2tps:
361
	{$ippool}
362

    
363
	create bundle template l2tp_b
364
	set bundle enable compression
365
	set bundle yes crypt-reqd
366

    
367
	set ccp yes mppc
368

    
369
	set iface name l2tp
370
	set iface group l2tp
371
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
372
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
373
	set iface disable on-demand
374
	set iface enable proxy-arp
375

    
376
	set ipcp yes vjcomp
377
	{$issue_ip_type}
378
	{$ipcp_dns}
379

    
380
	create link template l2tp_l l2tp
381
	set link action bundle l2tp_b
382

    
383
	set link yes acfcomp protocomp
384
	set link enable multilink
385
	set link no pap chap chap-msv2
386
	{$paporchap}
387
	{$l2tp_listen}
388
	set link keep-alive 10 180
389
	set link enable incoming
390

    
391
EOD;
392

    
393

    
394
			if (isset ($l2tpcfg['radius']['enable'])) {
395
				$mpdconf .=<<<EOD
396
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
397
	set radius retries 3
398
	set radius timeout 10
399
	set auth disable internal
400
	set auth enable radius-auth
401

    
402
EOD;
403

    
404
				if (isset ($l2tpcfg['radius']['accounting'])) {
405
					$mpdconf .=<<<EOD
406
	set auth enable radius-acct
407

    
408
EOD;
409
				}
410
			}
411

    
412
			fwrite($fd, $mpdconf);
413
			fclose($fd);
414
			unset($mpdconf);
415

    
416
			vpn_l2tp_updatesecret();
417
			vpn_netgraph_support();
418

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

    
422
			break;
423

    
424
		case 'redir':
425
			break;
426
	}
427

    
428
	if (platform_booting()) {
429
		echo "done\n";
430
	}
431

    
432
	return 0;
433
}
434

    
435
function vpn_l2tp_updatesecret() {
436
	global $config, $g;
437
	$l2tpcfg = $config['l2tp'];
438

    
439
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
440
	if (!$fd) {
441
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
442
		return 1;
443
	}
444

    
445
	$mpdsecret = "\n\n";
446

    
447
	if (is_array($l2tpcfg['user'])) {
448
		foreach ($l2tpcfg['user'] as $user) {
449
			/* Escape double quotes, do not allow password to start with '!'
450
			 * https://redmine.pfsense.org/issues/10275 */
451
			$pass = str_replace('"', '\"', ltrim($user['password'], '!'));
452
			$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
453
		}
454
	}
455

    
456
	fwrite($fd, $mpdsecret);
457
	fclose($fd);
458
	unset($mpdsecret);
459
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
460

    
461
	return 0;
462
}
463

    
464
?>
(55-55/60)