Project

General

Profile

Download (12.1 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']['acct_update'])) {
212
					$mpdconf .= "\tset auth acct-update {$pppoecfg['radius']['acct_update']}\n";
213
				}
214
				if (!empty($pppoecfg['radius']['nasip'])) {
215
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
216
				}
217
			}
218

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

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

    
231
				$mpdsecret = "\n\n";
232

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

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

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

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

    
260
			break;
261
	}
262

    
263
	if (platform_booting()) {
264
		echo gettext("done") . "\n";
265
	}
266

    
267
	return 0;
268
}
269

    
270
function vpn_l2tp_configure() {
271
	global $config, $g;
272

    
273
	$syscfg = $config['system'];
274
	$l2tpcfg = $config['l2tp'];
275

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

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

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

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

    
296
	}
297

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

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

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

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

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

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

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

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

    
359
			$mpdconf =<<<EOD
360

    
361
startup:
362

    
363
l2tps:
364
	{$ippool}
365

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

    
370
	set ccp yes mppc
371

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

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

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

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

    
394
EOD;
395
			if (!empty($l2tpcfg['secret'])) {
396
				$secret = str_replace('"', '\"', $l2tpcfg['secret']);
397
				$mpdconf .=<<<EOD
398
	set l2tp secret "{$secret}"
399

    
400
EOD;
401
			}
402

    
403

    
404
			if (isset ($l2tpcfg['radius']['enable'])) {
405
				$mpdconf .=<<<EOD
406
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
407
	set radius retries 3
408
	set radius timeout 10
409
	set auth disable internal
410
	set auth enable radius-auth
411

    
412
EOD;
413

    
414
				if (isset ($l2tpcfg['radius']['accounting'])) {
415
					$mpdconf .=<<<EOD
416
	set auth enable radius-acct
417

    
418
EOD;
419
				}
420
			}
421

    
422
			fwrite($fd, $mpdconf);
423
			fclose($fd);
424
			unset($mpdconf);
425

    
426
			vpn_l2tp_updatesecret();
427
			vpn_netgraph_support();
428

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

    
432
			break;
433

    
434
		case 'redir':
435
			break;
436
	}
437

    
438
	if (platform_booting()) {
439
		echo "done\n";
440
	}
441

    
442
	return 0;
443
}
444

    
445
function vpn_l2tp_updatesecret() {
446
	global $config, $g;
447
	$l2tpcfg = $config['l2tp'];
448

    
449
	$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
450
	if (!$fd) {
451
		printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_updatesecret().") . "\n");
452
		return 1;
453
	}
454

    
455
	$mpdsecret = "\n\n";
456

    
457
	if (is_array($l2tpcfg['user'])) {
458
		foreach ($l2tpcfg['user'] as $user) {
459
			/* Escape double quotes, do not allow password to start with '!'
460
			 * https://redmine.pfsense.org/issues/10275 */
461
			$pass = str_replace('"', '\"', ltrim($user['password'], '!'));
462
			$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
463
		}
464
	}
465

    
466
	fwrite($fd, $mpdsecret);
467
	fclose($fd);
468
	unset($mpdsecret);
469
	chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
470

    
471
	return 0;
472
}
473

    
474
?>
(56-56/62)