Project

General

Profile

Download (26.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	vpn.inc
4
	Copyright (C) 2004 Scott Ullrich
5
	All rights reserved.
6

    
7
	originally part of m0n0wall (http://m0n0.ch/wall)
8
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
/* include all configuration functions */
34
require_once("functions.inc");
35

    
36
function vpn_ipsec_failover_configure() {
37
	global $config, $g;
38

    
39
	$sasyncd_text = "";
40

    
41
	if($config['installedpackages']['sasyncd']['config'] <> "")
42
		foreach($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
43
			$enabled = isset($sasyncd['enable']);
44
			if(!$enabled)
45
				return;
46
			if($sasyncd['peerip'] <> "")
47
				$sasyncd_text .= "peer {$sasyncd['peerip']}\n";
48
			if($sasyncd['interface'])
49
				$sasyncd_text .= "carp interface {$sasyncd['interface']}\n";
50
			if($sasyncd['sharedkey'] <> "")
51
				$sasyncd_text .= "sharedkey {$sasyncd['sharedkey']}\n";
52
			if($sasyncd['mode'] <> "")
53
				$sasyncd_text .= "mode {$sasyncd['mode']}\n";
54
			if($sasyncd['listenon'] <> "")
55
				$sasyncd_text .= "listen on {$sasyncd['listenon']}\n";
56
			if($sasyncd['flushmodesync'] <> "")
57
				$sasyncd_text .= "flushmode sync {$sasyncd['flushmodesync']}\n";
58
		}
59

    
60
	$fd = fopen("{$g['varetc_path']}/sasyncd.conf", "w");
61
	fwrite($fd, $sasyncd_text);
62
	fclose($fd);
63
	chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
64
	
65
	mwexec("killall sasyncd");
66
	
67
	/* launch sasyncd, oh wise one */
68
	mwexec_bg("/usr/local/sbin/sasyncd -d -v -v -v");
69
}
70

    
71
function find_last_gif_device() {
72
        $last_gif_found = -1;
73
        if (!($fp = popen("/sbin/ifconfig -l", "r"))) return -1;
74
        $ifconfig_data = fread($fp, 4096);
75
        pclose($fp);
76
        $ifconfig_array = split(" ", $ifconfig_data);
77
        foreach ($ifconfig_array as $ifconfig) {
78
                ereg("gif(.)", $ifconfig, $regs);
79
                if($regs[0]) {
80
                        if($regs[0] > $last_gif_found)
81
                                $last_gif_found = $regs[1];
82
                }
83
        }
84
        return $last_gif_found;
85
}
86

    
87
function vpn_ipsec_configure($ipchg = false) {
88
	global $config, $g;
89

    
90
	if(isset($config['system']['developer'])) {
91
		if($g['booting'] == true) {
92
			/* determine if we should load the via padlock module */
93
			$dmesg_boot = `cat /var/log/dmesg.boot | grep CPU`;
94
			if(stristr($dmesg_boot, "ACE") == true) {		
95
				echo "Enabling [VIA Padlock] ...";
96
				mwexec("/sbin/kldload padlock");
97
				mwexec("/sbin/sysctl net.inet.ipsec.crypto_support=1");
98
				mwexec("/usr/sbin/setkey -F");
99
				mwexec("/usr/sbin/setkey -FP");
100
				echo " done.\n";
101
			}
102
		}
103
	}
104

    
105
	if(isset($config['ipsec']['preferredoldsa'])) {
106
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
107
	} else {
108
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
109
	}
110

    
111
	$number_of_gifs = find_last_gif_device();
112
	for($x=0; $x<$number_of_gifs; $x++) {
113
		mwexec("/sbin/ifconfig gif" . $x . " delete");
114
	}
115

    
116
	$curwanip = get_current_wan_address();
117
	if($config['installedpackages']['sasyncd']['config'] <> "")
118
		foreach($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
119
			if($sasyncd['ip'] <> "") 
120
				$curwanip = $sasyncd['ip'];
121
		}
122

    
123
	$syscfg = $config['system'];
124
	$ipseccfg = $config['ipsec'];
125
	$lancfg = $config['interfaces']['lan'];
126
	$lanip = $lancfg['ipaddr'];
127
	$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
128
	$lansn = $lancfg['subnet'];
129

    
130
	if ($g['booting']) {
131
		if (!isset($ipseccfg['enable']))
132
			return 0;
133

    
134
		echo "Configuring IPsec VPN... ";
135
	} else {
136
		/* kill racoon */
137
		killbypid("{$g['varrun_path']}/racoon.pid");
138

    
139
		/* wait for process to die */
140
		sleep(2);
141

    
142
		/* send a SIGKILL to be sure */
143
		sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
144
	}
145

    
146
	/* flush SPD and SAD */
147
	mwexec("/usr/sbin/setkey -FP");
148
	mwexec("/usr/sbin/setkey -F");
149

    
150
	if (isset($ipseccfg['enable'])) {
151

    
152
		/* fastforwarding is not compatible with ipsec tunnels */
153
		system("/sbin/sysctl net.inet.ip.fastforwarding=0 >/dev/null 2>&1");
154

    
155
		if (!$curwanip) {
156
			/* IP address not configured yet, exit */
157
			if ($g['booting'])
158
				echo "done\n";
159
			return 0;
160
		}
161

    
162
		if ((is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) ||
163
				isset($ipseccfg['mobileclients']['enable'])) {
164

    
165
			if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel'])) {
166

    
167
				/* generate spd.conf */
168
				$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
169
				if (!$fd) {
170
					printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
171
					return 1;
172
				}
173

    
174
				$spdconf = "";
175

    
176
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
177
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
178

    
179
				foreach ($ipseccfg['tunnel'] as $tunnel) {
180

    
181
					if (isset($tunnel['disabled']))
182
						continue;
183

    
184
					$ep = vpn_endpoint_determine($tunnel, $curwanip);
185
					if (!$ep)
186
						continue;
187

    
188
					vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
189

    
190
					if(is_domain($tunnel['remote-gateway'])) {
191
						$tmp = gethostbyname($tunnel['remote-gateway']);
192
						if($tmp)
193
							$tunnel['remote-gateway'] = $tmp;
194
					}
195

    
196
					if(isset($tunnel['creategif'])) {
197
						$number_of_gifs = find_last_gif_device();
198
						$number_of_gifs++;
199
						$curwanip = get_current_wan_address();
200
						if($config['installedpackages']['sasyncd']['config'] <> "")
201
							foreach($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
202
								if($sasyncd['ip'] <> "") 
203
									$curwanip = $sasyncd['ip'];
204
							}						
205
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $tunnel['remote-gateway']);
206
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
207
					}
208

    
209
					$spdconf .= "spdadd {$sa}/{$sn} " .
210
						"{$tunnel['remote-subnet']} any -P out ipsec " .
211
						"{$tunnel['p2']['protocol']}/tunnel/{$ep}-" .
212
						"{$tunnel['remote-gateway']}/unique;\n";
213

    
214
					$spdconf .= "spdadd {$tunnel['remote-subnet']} " .
215
						"{$sa}/{$sn} any -P in ipsec " .
216
						"{$tunnel['p2']['protocol']}/tunnel/{$tunnel['remote-gateway']}-" .
217
						"{$ep}/unique;\n";
218
				}
219

    
220
				fwrite($fd, $spdconf);
221
				fclose($fd);
222

    
223
				/* load SPD */
224
				mwexec("/usr/sbin/setkey -c < {$g['varetc_path']}/spd.conf");
225
			}
226

    
227
			/* generate racoon.conf */
228
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
229
			if (!$fd) {
230
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
231
				return 1;
232
			}
233

    
234
			$racoonconf = "";
235

    
236

    
237
	if($config['installedpackages']['sasyncd']['config'] <> "")
238
		foreach($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
239
			if($sasyncd['ip'] <> "") 
240
				$curwanip = $sasyncd['ip'];
241

    
242
				$interface_ip = $sasyncd['ip'];
243
				$racoonconf .= <<<EOD
244
listen {
245
	isakmp {$interface_ip} [500];
246
}
247

    
248
EOD;
249
			}
250

    
251
			$racoonconf = "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
252
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
253
			
254
			/* generate CA certificates files */
255
			$cacertnum = 0;
256
			if (is_array($ipseccfg['cacert']) && count($ipseccfg['cacert']))
257
				foreach ($ipseccfg['cacert'] as $cacert) {
258
					++$cacertnum;
259
					if (isset($cacert['cert'])) {
260
						$cert = base64_decode($cacert['cert']);
261
						$x509cert = openssl_x509_parse(openssl_x509_read($cert));
262
						if(is_array($x509cert) && isset($x509cert['hash'])) {
263
							$fd1 = fopen("{$g['varetc_path']}/{$x509cert['hash']}.0", "w");
264
							if (!$fd1) {
265
								printf("Error: cannot open {$x509cert['hash']}.0 in vpn.\n");
266
								return 1;
267
							}
268
							chmod("{$g['varetc_path']}/{$x509cert['hash']}.0", 0600);
269
							fwrite($fd1, $cert);
270
							fclose($fd1);
271
						}
272
					}
273
				}
274
						
275
			$tunnelnumber = 0;
276
			if (is_array($ipseccfg['tunnel']) && count($ipseccfg['tunnel']))
277
				foreach ($ipseccfg['tunnel'] as $tunnel) {
278
				
279
				++$tunnelnumber;
280
			
281
				if (isset($tunnel['disabled']))
282
					continue;
283
				
284
				$ep = vpn_endpoint_determine($tunnel, $curwanip);
285
				if (!$ep)
286
					continue;
287
			
288
				vpn_localnet_determine($tunnel['local-subnet'], $sa, $sn);
289
			
290
				if (isset($tunnel['p1']['myident']['myaddress'])) {
291
					$myidentt = "address";
292
					$myident = $ep;
293
				} else if (isset($tunnel['p1']['myident']['address'])) {
294
					$myidentt = "address";
295
					$myident = $tunnel['p1']['myident']['address'];
296
				} else if (isset($tunnel['p1']['myident']['fqdn'])) {
297
					$myidentt = "fqdn";
298
					$myident = $tunnel['p1']['myident']['fqdn'];
299
				} else if (isset($tunnel['p1']['myident']['ufqdn'])) {
300
					$myidentt = "user_fqdn";
301
					$myident = $tunnel['p1']['myident']['ufqdn'];
302
 				} else if (isset($tunnel['p1']['myident']['dyn_dns'])) {
303
					$myidentt = "dyn_dns";
304
					$myident = gethostbyname($tunnel['p1']['myident']['dyn_dns']);
305
 				}
306
				
307
				if (isset($tunnel['p1']['authentication_method'])) {
308
					$authmethod = $tunnel['p1']['authentication_method'];
309
				} else {$authmethod = 'pre_shared_key';}
310
				
311
				$certline = '';	
312
				
313
				if ($authmethod == 'rsasig') {
314
					if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
315
						$cert = base64_decode($tunnel['p1']['cert']);
316
						$private_key = base64_decode($tunnel['p1']['private-key']);
317
					} else {
318
						/* null certificate/key */
319
						$cert = '';
320
						$private_key = '';
321
					}
322
					
323
					if ($tunnel['p1']['peercert']) 
324
						$peercert = base64_decode($tunnel['p1']['peercert']);
325
					else 
326
						$peercert = '';
327
					
328
					$fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", "w");
329
					if (!$fd1) {
330
						printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
331
						return 1;
332
					}
333
					chmod("{$g['varetc_path']}/server{$tunnelnumber}-signed.pem", 0600);
334
					fwrite($fd1, $cert);
335
					fclose($fd1);
336
					
337
					$fd1 = fopen("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", "w");
338
					if (!$fd1) {
339
						printf("Error: cannot open server{$tunnelnumber}-key.pem in vpn.\n");
340
						return 1;
341
					}
342
					chmod("{$g['varetc_path']}/server{$tunnelnumber}-key.pem", 0600);
343
					fwrite($fd1, $private_key);
344
					fclose($fd1);
345

    
346
					$certline = "certificate_type x509 \"server{$tunnelnumber}-signed.pem\" \"server{$tunnelnumber}-key.pem\";";
347
					
348
					if ($peercert!=''){
349
						$fd1 = fopen("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", "w");
350
						if (!$fd1) {
351
							printf("Error: cannot open server{$tunnelnumber}-signed.pem in vpn.\n");
352
							return 1;
353
						}
354
						chmod("{$g['varetc_path']}/peer{$tunnelnumber}-signed.pem", 0600);
355
						fwrite($fd1, $peercert);
356
						fclose($fd1);		
357
						$certline .= <<<EOD
358
						
359
	peers_certfile "peer{$tunnelnumber}-signed.pem";
360
EOD;
361
					} 					
362
				} 
363
				$racoonconf .= <<<EOD
364
remote {$tunnel['remote-gateway']} \{
365
	exchange_mode {$tunnel['p1']['mode']};
366
	my_identifier {$myidentt} "{$myident}";
367
	{$certline}
368
	peers_identifier address {$tunnel['remote-gateway']};
369
	initial_contact on;
370
	support_proxy on;
371
	proposal_check obey;
372

    
373
	proposal \{
374
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
375
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
376
		authentication_method {$authmethod};
377
		dh_group {$tunnel['p1']['dhgroup']};
378

    
379
EOD;
380
				if ($tunnel['p1']['lifetime'])
381
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
382
				
383
				$racoonconf .= "	}\n";
384
				
385
				if ($tunnel['p1']['lifetime'])
386
					$racoonconf .= "	lifetime time {$tunnel['p1']['lifetime']} secs;\n";
387
					
388
				$racoonconf .= "}\n\n";
389
				
390
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
391
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
392
				
393
				$racoonconf .= <<<EOD
394
sainfo address {$sa}/{$sn} any address {$tunnel['remote-subnet']} any \{
395
	encryption_algorithm {$p2ealgos};
396
	authentication_algorithm {$p2halgos};
397
	compression_algorithm deflate;
398

    
399
EOD;
400

    
401
				if ($tunnel['p2']['pfsgroup'])
402
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
403
					
404
				if ($tunnel['p2']['lifetime'])
405
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
406
					
407
				$racoonconf .= "}\n\n";
408
			}
409
			
410
			/* mobile clients? */
411
			if (isset($ipseccfg['mobileclients']['enable'])) {
412
				
413
				$tunnel = $ipseccfg['mobileclients'];
414
				
415
				if (isset($tunnel['p1']['myident']['myaddress'])) {
416
					$myidentt = "address";
417
					$myident = $curwanip;
418
				} else if (isset($tunnel['p1']['myident']['address'])) {
419
					$myidentt = "address";
420
					$myident = $tunnel['p1']['myident']['address'];
421
				} else if (isset($tunnel['p1']['myident']['fqdn'])) {
422
					$myidentt = "fqdn";
423
					$myident = $tunnel['p1']['myident']['fqdn'];
424
				} else if (isset($tunnel['p1']['myident']['ufqdn'])) {
425
					$myidentt = "user_fqdn";
426
					$myident = $tunnel['p1']['myident']['ufqdn'];
427
 				}
428
				
429
				if (isset($tunnel['p1']['authentication_method'])) {
430
					$authmethod = $tunnel['p1']['authentication_method'];
431
				} else {$authmethod = 'pre_shared_key';}
432
				
433
				$certline = '';					
434
				if ($authmethod == 'rsasig') {
435
					if ($tunnel['p1']['cert'] && $tunnel['p1']['private-key']) {
436
						$cert = base64_decode($tunnel['p1']['cert']);
437
						$private_key = base64_decode($tunnel['p1']['private-key']);
438
					} else {
439
						/* null certificate/key */
440
						$cert = '';
441
						$private_key = '';
442
					}
443
					
444
					if ($tunnel['p1']['peercert']) 
445
						$peercert = base64_decode($tunnel['p1']['peercert']);
446
					else 
447
						$peercert = '';
448
					
449
					$fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", "w");
450
					if (!$fd1) {
451
						printf("Error: cannot open server-mobile{$tunnelnumber}-signed.pem in vpn.\n");
452
						return 1;
453
					}
454
					chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-signed.pem", 0600);
455
					fwrite($fd1, $cert);
456
					fclose($fd1);
457
					
458
					$fd1 = fopen("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", "w");
459
					if (!$fd1) {
460
						printf("Error: cannot open server-mobile{$tunnelnumber}-key.pem in vpn.\n");
461
						return 1;
462
					}
463
					chmod("{$g['varetc_path']}/server-mobile{$tunnelnumber}-key.pem", 0600);
464
					fwrite($fd1, $private_key);
465
					fclose($fd1);
466

    
467
					$certline = "certificate_type x509 \"server-mobile{$tunnelnumber}-signed.pem\" \"server-mobile{$tunnelnumber}-key.pem\";";
468
				}
469
				$racoonconf .= <<<EOD
470
remote anonymous \{
471
	exchange_mode {$tunnel['p1']['mode']};
472
	my_identifier {$myidentt} "{$myident}";
473
	{$certline}
474
	initial_contact on;
475
	passive on;
476
	generate_policy on;
477
	support_proxy on;
478
	proposal_check obey;
479

    
480
	proposal \{
481
		encryption_algorithm {$tunnel['p1']['encryption-algorithm']};
482
		hash_algorithm {$tunnel['p1']['hash-algorithm']};
483
		authentication_method {$authmethod};
484
		dh_group {$tunnel['p1']['dhgroup']};
485

    
486
EOD;
487
				if ($tunnel['p1']['lifetime'])
488
					$racoonconf .= "		lifetime time {$tunnel['p1']['lifetime']} secs;\n";
489
				
490
				$racoonconf .= "	}\n";
491
				
492
				if ($tunnel['p1']['lifetime'])
493
					$racoonconf .= "	lifetime time {$tunnel['p1']['lifetime']} secs;\n";
494
					
495
				$racoonconf .= "}\n\n";
496
				
497
				$p2ealgos = join(",", $tunnel['p2']['encryption-algorithm-option']);
498
				$p2halgos = join(",", $tunnel['p2']['hash-algorithm-option']);
499
				
500
				$racoonconf .= <<<EOD
501
sainfo anonymous \{
502
	encryption_algorithm {$p2ealgos};
503
	authentication_algorithm {$p2halgos};
504
	compression_algorithm deflate;
505

    
506
EOD;
507

    
508
				if ($tunnel['p2']['pfsgroup'])
509
					$racoonconf .= "	pfs_group {$tunnel['p2']['pfsgroup']};\n";
510
					
511
				if ($tunnel['p2']['lifetime'])
512
					$racoonconf .= "	lifetime time {$tunnel['p2']['lifetime']} secs;\n";
513
					
514
				$racoonconf .= "}\n\n";
515
			}
516
			
517
			fwrite($fd, $racoonconf);
518
			fclose($fd);
519
			
520
			/* generate psk.txt */
521
			$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
522
			if (!$fd) {
523
				printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
524
				return 1;
525
			}
526
			
527
			$pskconf = "";
528
			
529
			if (is_array($ipseccfg['tunnel'])) {
530
				foreach ($ipseccfg['tunnel'] as $tunnel) {
531
					if (isset($tunnel['disabled']))
532
						continue;
533
					$pskconf .= "{$tunnel['remote-gateway']}	 {$tunnel['p1']['pre-shared-key']}\n";
534
				}
535
			}
536
			
537
			/* add PSKs for mobile clients */
538
			if (is_array($ipseccfg['mobilekey'])) {
539
				foreach ($ipseccfg['mobilekey'] as $key) {
540
					$pskconf .= "{$key['ident']}	{$key['pre-shared-key']}\n";
541
				}
542
			}
543
			
544
			fwrite($fd, $pskconf);
545
			fclose($fd);
546
			chmod("{$g['varetc_path']}/psk.txt", 0600);
547
			
548
			/* start racoon */
549
			mwexec("/usr/local/sbin/racoon -d -f {$g['varetc_path']}/racoon.conf");
550
			
551
			if (is_array($ipseccfg['tunnel'])) {
552
				foreach ($ipseccfg['tunnel'] as $tunnel) {
553
					if (isset($tunnel['auto'])) {
554
						$remotehost = substr($tunnel['remote-subnet'],0,strpos($tunnel['remote-subnet'],"/"));
555
						$srchost = vpn_endpoint_determine($tunnel, $curwanip);
556
						if ($srchost)
557
							mwexec_bg("/sbin/ping -c 10 -S {$srchost} {$remotehost}");
558
					}
559
				}
560
			}
561
		}
562
	}
563

    
564
	vpn_ipsec_failover_configure();
565

    
566
	if (!$g['booting']) {
567
		/* reload the filter */
568
		touch("{$g["tmp_path"]}/filter_dirty");
569
	}
570

    
571
	if ($g['booting'])
572
		echo "done\n";
573

    
574
	return 0;
575
}
576

    
577
function vpn_pptpd_configure() {
578
	global $config, $g;
579

    
580
	$syscfg = $config['system'];
581
	$pptpdcfg = $config['pptpd'];
582

    
583
	if ($g['booting']) {
584
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
585
			return 0;
586

    
587
		echo "Configuring PPTP VPN service... ";
588
	} else {
589
		/* kill mpd */
590
		killbypid("{$g['varrun_path']}/mpd-vpn.pid");
591

    
592
		/* wait for process to die */
593
		sleep(2);
594

    
595
		/* remove mpd.conf, if it exists */
596
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.conf");
597
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.links");
598
		unlink_if_exists("{$g['varetc_path']}/mpd-vpn/mpd.secret");
599
	}
600

    
601
	/* make sure mpd-vpn directory exists */
602
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
603
		mkdir("{$g['varetc_path']}/mpd-vpn");
604

    
605
	switch ($pptpdcfg['mode']) {
606

    
607
		case 'server':
608

    
609
			/* write mpd.conf */
610
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "w");
611
			if (!$fd) {
612
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
613
				return 1;
614
			}
615

    
616
			$mpdconf = <<<EOD
617
pptpd:
618

    
619
EOD;
620

    
621
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
622
				$mpdconf .= "	load pt{$i}\n";
623
			}
624

    
625
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
626

    
627
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
628
				$ngif = "ng" . ($i+1);
629

    
630
				$mpdconf .= <<<EOD
631

    
632
pt{$i}:
633
	new -i {$ngif} pt{$i} pt{$i}
634
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
635
	load pts
636

    
637
EOD;
638
			}
639

    
640
			$mpdconf .= <<<EOD
641

    
642
pts:
643
	set iface disable on-demand
644
	set iface enable proxy-arp
645
	set iface enable tcpmssfix
646
	set iface idle 1800
647
	set iface up-script /usr/local/sbin/vpn-linkup
648
	set iface down-script /usr/local/sbin/vpn-linkdown
649
	set bundle enable multilink
650
	set bundle enable crypt-reqd
651
	set link yes acfcomp protocomp
652
	set link no pap chap
653
	set link enable chap-msv2
654
	set link mtu 1460
655
	set link keep-alive 10 60
656
	set ipcp yes vjcomp
657
	set bundle enable compression
658
	set ccp yes mppc
659
	set ccp yes mpp-e128
660
	set ccp yes mpp-stateless
661

    
662
EOD;
663

    
664
			if (!isset($pptpdcfg['req128'])) {
665
				$mpdconf .= <<<EOD
666
	set ccp yes mpp-e40
667
	set ccp yes mpp-e56
668

    
669
EOD;
670
			}
671
			if (isset($pptpdcfg["wins"])) 
672
				$mpdconf .= "	set ipcp nbns {$pptpdcfg['wins']}\n";
673
			if (isset($config['dnsmasq']['enable'])) {
674
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
675
				if ($syscfg['dnsserver'][0])
676
					$mpdconf .= " " . $syscfg['dnsserver'][0];
677
				$mpdconf .= "\n";
678
			} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
679
				$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
680
			}
681

    
682
			if (isset($pptpdcfg['radius']['enable'])) {
683
				$mpdconf .= <<<EOD
684
	set radius server {$pptpdcfg['radius']['server']} "{$pptpdcfg['radius']['secret']}"
685
	set radius retries 3
686
	set radius timeout 10
687
	set bundle enable radius-auth
688
	set bundle disable radius-fallback
689

    
690
EOD;
691

    
692
				if (isset($pptpdcfg['radius']['accounting'])) {
693
					$mpdconf .= <<<EOD
694
	set bundle enable radius-acct
695

    
696
EOD;
697
				}
698
			}
699

    
700
			fwrite($fd, $mpdconf);
701
			fclose($fd);
702

    
703
			/* write mpd.links */
704
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "w");
705
			if (!$fd) {
706
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
707
				return 1;
708
			}
709

    
710
			$mpdlinks = "";
711

    
712
			for ($i = 0; $i < $g['n_pptp_units']; $i++) {
713
				$mpdlinks .= <<<EOD
714

    
715
pt{$i}:
716
	set link type pptp
717
	set pptp enable incoming
718
	set pptp disable originate
719
	set pptp disable windowing
720
	set pptp self 127.0.0.1
721

    
722
EOD;
723
			}
724

    
725
			fwrite($fd, $mpdlinks);
726
			fclose($fd);
727

    
728
			/* write mpd.secret */
729
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "w");
730
			if (!$fd) {
731
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
732
				return 1;
733
			}
734

    
735
			$mpdsecret = "";
736

    
737
			if (is_array($pptpdcfg['user'])) {
738
				foreach ($pptpdcfg['user'] as $user)
739
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
740
			}
741

    
742
			fwrite($fd, $mpdsecret);
743
			fclose($fd);
744
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
745

    
746
			/* fire up mpd */
747
			mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']}/mpd-vpn -p {$g['varrun_path']}/mpd-vpn.pid pptpd");
748

    
749
			break;
750

    
751
		case 'redir':
752
			break;
753
	}
754

    
755
	touch("{$g["tmp_path"]}/filter_dirty");
756

    
757
	if ($g['booting'])
758
		echo "done\n";
759

    
760
	return 0;
761
}
762

    
763
function vpn_localnet_determine($adr, &$sa, &$sn) {
764
	global $config, $g;
765

    
766
	if (isset($adr)) {
767
		if ($adr['network']) {
768
			switch ($adr['network']) {
769
				case 'lan':
770
					$sn = $config['interfaces']['lan']['subnet'];
771
					$sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
772
					break;
773
			}
774
		} else if ($adr['address']) {
775
			list($sa,$sn) = explode("/", $adr['address']);
776
			if (is_null($sn))
777
				$sn = 32;
778
		}
779
	} else {
780
		$sn = $config['interfaces']['lan']['subnet'];
781
		$sa = gen_subnet($config['interfaces']['lan']['ipaddr'], $sn);
782
	}
783
}
784

    
785
function vpn_endpoint_determine($tunnel, $curwanip) {
786

    
787
	global $g, $config;
788

    
789
	if ((!$tunnel['interface']) || ($tunnel['interface'] == "wan")) {
790
		if ($curwanip)
791
			return $curwanip;
792
		else
793
			return null;
794
	} else if ($tunnel['interface'] == "lan") {
795
		return $config['interfaces']['lan']['ipaddr'];
796
	} else {
797
		$oc = $config['interfaces'][$tunnel['interface']];
798

    
799
		if (isset($oc['enable']) && $oc['if']) {
800
			return $oc['ipaddr'];
801
		}
802
	}
803

    
804
	return null;
805
}
806

    
807
function vpn_pppoe_configure() {
808
	global $config, $g;
809

    
810
	$syscfg = $config['system'];
811
	$pppoecfg = $config['pppoe'];
812

    
813
	/* create directory if it does not exist */
814
	if(!is_dir("{$g['varetc_path']}/mpd-vpn"))
815
		mkdir("{$g['varetc_path']}/mpd-vpn");
816
	
817
	if ($g['booting']) {
818
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
819
			return 0;
820

    
821
		echo "Configuring PPPoE VPN service... ";
822
	} else {
823
		/* kill mpd */
824
		killbypid("{$g['varrun_path']}/mpd-vpn.pid");
825

    
826
		/* wait for process to die */
827
		sleep(2);
828
		
829
		vpn_pptpd_configure();
830
	}
831

    
832
	/* make sure mpd-vpn directory exists */
833
	if (!file_exists("{$g['varetc_path']}/mpd-vpn"))
834
		mkdir("{$g['varetc_path']}/mpd-vpn");
835

    
836
	switch ($pppoecfg['mode']) {
837

    
838
		case 'server':
839

    
840
			$pppoe_interface = filter_translate_type_to_real_interface($pppoecfg['interface']);
841

    
842
			/* write mpd.conf */
843
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.conf", "a");
844
			if (!$fd) {
845
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
846
				return 1;
847
			}
848
			$mpdconf = "\n\n";
849
			$mpdconf .= <<<EOD
850
pppoe:
851

    
852
EOD;
853

    
854
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
855
				$mpdconf .= "	load pppoe{$i}\n";
856
			}
857

    
858
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
859

    
860
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
861
				$ngif = "ng" . ($i+1);
862

    
863
				$mpdconf .= <<<EOD
864

    
865
pppoe{$i}:
866
	new -i {$ngif} pppoe{$i} pppoe{$i}
867
	set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32
868
	load pppoe_standart
869

    
870
EOD;
871
			}
872

    
873
			$mpdconf .= <<<EOD
874

    
875
pppoe_standart:
876
	set link type pppoe
877
	set pppoe iface {$pppoe_interface}
878
	set pppoe service "*"
879
	set pppoe disable originate
880
	set pppoe enable incoming
881
	set bundle no multilink
882
	set bundle enable compression
883
	set bundle max-logins 1
884
	set iface idle 0
885
	set iface disable on-demand
886
	set iface disable proxy-arp
887
	set iface enable tcpmssfix
888
	set iface mtu 1500
889
	set link mtu 1500
890
	set link no pap chap
891
	set link enable chap
892
	set link keep-alive 60 180
893
	set ipcp yes vjcomp
894
	set ipcp no vjcomp
895
	set link max-redial -1
896
	set link mtu 1492
897
	set ccp yes mpp-e40
898
	set ccp yes mpp-e128
899
	set ccp yes mpp-stateless
900
	set link latency 1
901
	#set ipcp dns 10.10.1.3
902
	#set bundle accept encryption	
903

    
904
EOD;
905

    
906
			if (isset($config['dnsmasq']['enable'])) {
907
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
908
				if ($syscfg['dnsserver'][0])
909
					$mpdconf .= " " . $syscfg['dnsserver'][0];
910
				$mpdconf .= "\n";
911
			} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
912
				$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
913
			}
914

    
915
			if (isset($pppoecfg['radius']['enable'])) {
916
				$mpdconf .= <<<EOD
917
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
918
	set radius retries 3
919
	set radius timeout 10
920
	set bundle enable radius-auth
921
	set bundle disable radius-fallback
922

    
923
EOD;
924

    
925
				if (isset($pppoecfg['radius']['accounting'])) {
926
					$mpdconf .= <<<EOD
927
	set bundle enable radius-acct
928

    
929
EOD;
930
				}
931
			}
932

    
933
			fwrite($fd, $mpdconf);
934
			fclose($fd);
935

    
936
			/* write mpd.links */
937
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.links", "a");
938
			if (!$fd) {
939
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
940
				return 1;
941
			}
942

    
943
			$mpdlinks = "";
944

    
945
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
946
				$mpdlinks .= <<<EOD
947

    
948
pppoe:
949
	set link type pppoe
950
	set pppoe iface {$pppoe_interface}
951

    
952
EOD;
953
			}
954

    
955
			fwrite($fd, $mpdlinks);
956
			fclose($fd);
957

    
958
			/* write mpd.secret */
959
			$fd = fopen("{$g['varetc_path']}/mpd-vpn/mpd.secret", "a");
960
			if (!$fd) {
961
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
962
				return 1;
963
			}
964

    
965
			$mpdsecret = "\n\n";
966

    
967
			if (is_array($pppoecfg['user'])) {
968
				foreach ($pppoecfg['user'] as $user)
969
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
970
			}
971

    
972
			fwrite($fd, $mpdsecret);
973
			fclose($fd);
974
			chmod("{$g['varetc_path']}/mpd-vpn/mpd.secret", 0600);
975

    
976
			/* fire up mpd */
977
			mwexec("/usr/local/sbin/mpd -b -d {$g['varetc_path']}/mpd-vpn -p {$g['varrun_path']}/mpd-vpn.pid pppoe");
978

    
979
			break;
980

    
981
		case 'redir':
982
			break;
983
	}
984

    
985
	touch("{$g["tmp_path"]}/filter_dirty");
986

    
987
	if ($g['booting'])
988
		echo "done\n";
989

    
990
	return 0;
991
}
992

    
993
?>
(18-18/23)