Project

General

Profile

Download (26.6 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 b1ad443d Scott Ullrich
3
/* $Id$ */
4
/*
5
	$RCSfile$
6 33ab8aa5 Scott Ullrich
	
7
	Copyright (C) 2008 Scott Ullrich <sullrich@gmail.com>
8
	All rights reserved.
9
	
10 b1ad443d Scott Ullrich
	Copyright (C) 2006  Fernando Lemos
11
	All rights reserved.
12
13 33ab8aa5 Scott Ullrich
	This file was rewritten from scratch by Fernando Lemos but
14
	*MIGHT* contain code previously written by:
15
16 b1ad443d Scott Ullrich
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
17
	All rights reserved.
18
19
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
20
	All rights reserved.
21
22
	Redistribution and use in source and binary forms, with or without
23
	modification, are permitted provided that the following conditions are met:
24
25
	1. Redistributions of source code must retain the above copyright notices,
26
	   this list of conditions and the following disclaimer.
27
28
	2. Redistributions in binary form must reproduce the above copyright
29
	   notices, this list of conditions and the following disclaimer in the
30
	   documentation and/or other materials provided with the distribution.
31
32
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
33
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
34
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
36
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
	POSSIBILITY OF SUCH DAMAGE.
42 523855b0 Scott Ullrich
	
43
	DISABLE_PHP_LINT_CHECKING
44
	
45
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/openvpn	/usr/bin/openssl	/sbin/ifconfig
46
	pfSense_MODULE:	openvpn
47 b1ad443d Scott Ullrich
48 523855b0 Scott Ullrich
*/
49 8dc3ef67 Scott Ullrich
require_once('config.inc');
50 32a7a1f6 Ermal Lu?i
require_once("certs.inc");
51 36df0acc Scott Ullrich
require_once('pfsense-utils.inc');
52 c61e4626 Ermal Lu?i
require_once("auth.inc");
53 8dc3ef67 Scott Ullrich
54 8411b218 Matthew Grooms
$openvpn_prots = array("UDP", "TCP");
55 702a4702 Scott Ullrich
56 691fbf14 Ermal Lu?i
$openvpn_dev_mode = array("tun", "tap");
57
58 3c11bd3c Matthew Grooms
/* 
59
 * The User Auth mode below is disabled because
60
 * OpenVPN erroneously requires that we provide
61
 * a CA configuration parameter. In this mode,
62
 * clients don't send a certificate so there is
63
 * no need for a CA. If we require that admins
64
 * provide one in the pfSense UI due to a bogus
65
 * requirement imposed by OpenVPN, it could be
66
 * considered very confusing ( I know I was ).
67
 *
68
 * -mgrooms
69
 */
70
71 fe787fc7 Matthew Grooms
$openvpn_dh_lengths = array(
72
	1024, 2048, 4096 );
73
74 3c11bd3c Matthew Grooms
$openvpn_server_modes = array(
75
	'p2p_tls' => "Peer to Peer ( SSL/TLS )",
76
	'p2p_shared_key' => "Peer to Peer ( Shared Key )",
77
	'server_tls' => "Remote Access ( SSL/TLS )",
78 54b9de56 Ermal Lu?i
	'server_user' => "Remote Access ( User Auth )",
79 3c11bd3c Matthew Grooms
	'server_tls_user' => "Remote Access ( SSL/TLS + User Auth )");
80
81
$openvpn_client_modes = array(
82
	'p2p_tls' => "Peer to Peer ( SSL/TLS )",
83
	'p2p_shared_key' => "Peer to Peer ( Shared Key )" );
84
85
function openvpn_create_key() {
86
87
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
88
	if (!$fp)
89
		return false;
90
91
	$rslt = stream_get_contents($fp);
92
	pclose($fp);
93
94
	return $rslt;
95
}
96 d799787e Matthew Grooms
97 8411b218 Matthew Grooms
function openvpn_create_dhparams($bits) {
98 34bc1324 Matthew Grooms
99 3c11bd3c Matthew Grooms
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
100 34bc1324 Matthew Grooms
	if (!$fp)
101
		return false;
102
103
	$rslt = stream_get_contents($fp);
104
	pclose($fp);
105
106
	return $rslt;
107
}
108
109 d799787e Matthew Grooms
function openvpn_vpnid_used($vpnid) {
110 8be2d6d3 Ermal Luçi
	global $config;
111
112 d799787e Matthew Grooms
	if (is_array($config['openvpn']['openvpn-server']))
113 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
114 f432e364 Matthew Grooms
			if ($vpnid == $settings['vpnid'])
115 d799787e Matthew Grooms
				return true;
116
117
	if (is_array($config['openvpn']['openvpn-client']))
118 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
119 f432e364 Matthew Grooms
			if ($vpnid == $settings['vpnid'])
120 d799787e Matthew Grooms
				return true;
121 04a6e900 Ermal Luçi
122 d799787e Matthew Grooms
	return false;
123
}
124
125
function openvpn_vpnid_next() {
126
127
	$vpnid = 1;
128
	while(openvpn_vpnid_used($vpnid))
129
		$vpnid++;
130
131
	return $vpnid;
132
}
133
134 f432e364 Matthew Grooms
function openvpn_port_used($prot, $port) {
135
	global $config;
136
137
	if (is_array($config['openvpn']['openvpn-server']))
138 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-server'] as & $settings)
139 f432e364 Matthew Grooms
			if ($port == $settings['local_port'] &&
140
				$prot == $settings['protocol'])
141
				return $settings['vpnid'];
142
143
	if (is_array($config['openvpn']['openvpn-client']))
144 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-client'] as & $settings)
145 f432e364 Matthew Grooms
			if ($port == $settings['local_port'] &&
146
				$prot == $settings['protocol'])
147
				return $settings['vpnid'];
148
149
	return 0;
150
}
151
152
function openvpn_port_next($prot) {
153
154
	$port = 1194;
155
	while(openvpn_port_used($prot, $port))
156
		$port++;
157
158
	return $port;
159
}
160
161 d799787e Matthew Grooms
function openvpn_get_cipherlist() {
162
163
	$ciphers = array();
164
	$cipher_out = shell_exec('openvpn --show-ciphers | grep "default key" | awk \'{print $1, "(" $2 "-" $3 ")";}\'');
165
	$cipher_lines = explode("\n", trim($cipher_out));
166
	sort($cipher_lines);
167
	foreach ($cipher_lines as $line) {
168
		$words = explode(' ', $line);
169
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
170 8be2d6d3 Ermal Luçi
	}
171 2635222d jim-p
	$ciphers["none"] = "None (No Encryption)";
172 d799787e Matthew Grooms
	return $ciphers;
173
}
174
175 582c58ae jim-p
function openvpn_get_engines() {
176
	$openssl_engines = array('none' => 'No Hardware Crypto Acceleration');
177
	exec("/usr/bin/openssl engine", $openssl_engine_output);
178
	foreach ($openssl_engine_output as $oeo) {
179
		$linematch = array();
180
		preg_match("/\((.*)\)\s(.*)/", $oeo, $linematch);
181
		if ($linematch[1] != "dynamic")
182
			$openssl_engines[$linematch[1]] = $linematch[2];
183
	}
184
	return $openssl_engines;
185
}
186
187
function openvpn_validate_engine($engine) {
188
	$engines = openvpn_get_engines();
189
	return array_key_exists($engine, $engines);
190
}
191
192 d799787e Matthew Grooms
function openvpn_validate_host($value, $name) {
193
	$value = trim($value);
194 3e2bd5de Ermal Lu?i
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
195 d799787e Matthew Grooms
		return "The field '$name' must contain a valid IP address or domain name.";
196
	return false;
197 8dc3ef67 Scott Ullrich
}
198
199
function openvpn_validate_port($value, $name) {
200
	$value = trim($value);
201 3e2bd5de Ermal Lu?i
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
202 8dc3ef67 Scott Ullrich
		return "The field '$name' must contain a valid port, ranging from 0 to 65535.";
203 b398bbca Martin Fuchs
	return false;
204 8dc3ef67 Scott Ullrich
}
205
206
function openvpn_validate_cidr($value, $name) {
207
	$value = trim($value);
208
	if (!empty($value)) {
209
		list($ip, $mask) = explode('/', $value);
210
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
211
			return "The field '$name' must contain a valid CIDR range.";
212
	}
213
	return false;
214 afb07cf1 Scott Ullrich
}
215
216 d799787e Matthew Grooms
function openvpn_add_dhcpopts(& $settings, & $conf) {
217 afb07cf1 Scott Ullrich
218 d799787e Matthew Grooms
	if (!empty($settings['dns_domain'])) 
219
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
220 add2e3f7 Scott Ullrich
221 d799787e Matthew Grooms
	if (!empty($settings['dns_server1']))
222
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
223
	if (!empty($settings['dns_server2']))
224
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
225
	if (!empty($settings['dns_server3']))
226
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
227
	if (!empty($settings['dns_server4']))
228
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
229 f9927473 Scott Ullrich
230 d799787e Matthew Grooms
	if (!empty($settings['ntp_server1']))
231 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
232 d799787e Matthew Grooms
	if (!empty($settings['ntp_server2']))
233 c7f70dbc Chris Buechler
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
234 f9927473 Scott Ullrich
235 d799787e Matthew Grooms
	if ($settings['netbios_enable']) {
236 add2e3f7 Scott Ullrich
237 095a95ae Matthew Grooms
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
238
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
239
		if (!empty($settings['dhcp_nbtscope'])) 
240 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
241 8dc3ef67 Scott Ullrich
242 d799787e Matthew Grooms
		if (!empty($settings['wins_server1']))
243
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
244
		if (!empty($settings['wins_server2']))
245
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
246 add2e3f7 Scott Ullrich
247 d799787e Matthew Grooms
		if (!empty($settings['nbdd_server1']))
248
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
249
	}
250 8dc3ef67 Scott Ullrich
251 d799787e Matthew Grooms
	if ($settings['gwredir']) 
252
		$conf .= "push \"redirect-gateway def1\"\n";
253
}
254 24012690 Scott Ullrich
255 d799787e Matthew Grooms
function openvpn_add_custom(& $settings, & $conf) {
256 add2e3f7 Scott Ullrich
257 d799787e Matthew Grooms
	if ($settings['custom_options']) {
258 8dc3ef67 Scott Ullrich
259 d799787e Matthew Grooms
		$options = explode(';', $settings['custom_options']);
260
261
		if (is_array($options)) {
262
			foreach ($options as $option)
263
				$conf .= "$option\n";
264
		} else
265
			$conf .= "{$settings['custom_options']}\n";
266 add2e3f7 Scott Ullrich
	}
267
}
268
269 691fbf14 Ermal Lu?i
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
270 d799787e Matthew Grooms
	global $g;
271 add2e3f7 Scott Ullrich
272 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
273
	file_put_contents($fpath, base64_decode($data));
274 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
275
	//chgrp($fpath, 'nobody');
276 6f27412f Ermal Lu?i
	@chmod($fpath, 0600);
277 d799787e Matthew Grooms
278 691fbf14 Ermal Lu?i
	$conf .= "{$directive} {$fpath} {$opt}\n";
279 4eefa6e8 Scott Ullrich
}
280
281 fc05822b jim-p
function openvpn_reconfigure($mode, $settings) {
282 add2e3f7 Scott Ullrich
	global $g, $config;
283 afb07cf1 Scott Ullrich
284 93a0a028 Ermal Luçi
	if (empty($settings))
285
		return;
286 a1cab2c7 Ermal
	if (isset($settings['disable'])) 
287 4eefa6e8 Scott Ullrich
		return;
288
289 fdd725f0 Ermal Luçi
	/*
290 d799787e Matthew Grooms
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
291
	 * we use a vpnid number which is allocated for a particular client
292
	 * or server configuration. ( see openvpn_vpnid_next() )
293 fdd725f0 Ermal Luçi
	 */
294 8874c692 Ermal Luçi
295 d799787e Matthew Grooms
	$vpnid = $settings['vpnid'];
296
	$mode_id = $mode.$vpnid;
297 8874c692 Ermal Luçi
298 bd7ca506 jim-p
	if (isset($settings['dev_mode']))
299
		$tunname = "{$settings['dev_mode']}{$vpnid}";
300
	else {	/* defaults to tun */
301
		$tunname = "tun{$vpnid}";
302
		$settings['dev_mode'] = "tun";
303 691fbf14 Ermal Lu?i
	}
304
305 bd7ca506 jim-p
	if ($mode == "server")
306
		$devname = "ovpns{$vpnid}";
307
	else
308
		$devname = "ovpnc{$vpnid}";
309 8874c692 Ermal Luçi
310 bd7ca506 jim-p
	/* is our device already configured */
311
	if (mwexec("/sbin/ifconfig {$devname}")) {
312 dc408939 Matthew Grooms
313 bd7ca506 jim-p
		/* create the tap device if required */
314
		if (!file_exists("/dev/{$tunname}"))
315
			exec("/sbin/ifconfig {$tunname} create");
316 98872d89 Ermal Luçi
317 bd7ca506 jim-p
		/* rename the device */
318
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
319 095a95ae Matthew Grooms
320 bd7ca506 jim-p
		/* add the device to the openvpn group */
321
		mwexec("/sbin/ifconfig {$devname} group openvpn");
322 dc408939 Matthew Grooms
	}
323 d799787e Matthew Grooms
324 dc408939 Matthew Grooms
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
325 c0cf27aa Scott Ullrich
	$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
326
	$cipher = $settings['crypto'];
327 d799787e Matthew Grooms
328
	$interface = $settings['interface'];
329 67b0902f pierrepomes
	$ipaddr = $settings['ipaddr'];
330 d799787e Matthew Grooms
331 67b0902f pierrepomes
	// If a specific ip address (VIP) is requested, use it.
332
	// Otherwise, if a specific interface is requested, use it
333
	// If "any" interface was selected, local directive will be ommited.
334
	if (!empty($ipaddr)) {
335
		$iface_ip=$ipaddr;
336 3d06e8f0 pierrepomes
	} else {
337 67b0902f pierrepomes
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
338 507af8dd pierrepomes
			$iface_ip=get_interface_ip($interface);
339 67b0902f pierrepomes
		}
340 3d06e8f0 pierrepomes
	}
341 d799787e Matthew Grooms
342 bd7ca506 jim-p
	$conf  = "dev {$devname}\n";
343
	$conf .= "dev-type {$settings['dev_mode']}\n";
344
	$conf .= "dev-node /dev/{$tunname}\n";
345 3c11bd3c Matthew Grooms
	$conf .= "writepid {$pfile}\n";
346
	$conf .= "#user nobody\n";
347
	$conf .= "#group nobody\n";
348 d1014c18 Chris Buechler
	$conf .= "script-security 3\n";
349 3c11bd3c Matthew Grooms
	$conf .= "daemon\n";
350
	$conf .= "keepalive 10 60\n";
351
	$conf .= "ping-timer-rem\n";
352
	$conf .= "persist-tun\n";
353
	$conf .= "persist-key\n";
354
	$conf .= "proto {$proto}\n";
355
	$conf .= "cipher {$cipher}\n";
356 8d964cea Ermal
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
357
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
358 3c11bd3c Matthew Grooms
359 67b0902f pierrepomes
	if (!empty($iface_ip)) {
360 48a458d2 pierrepomes
		$conf .= "local {$iface_ip}\n";	
361 67b0902f pierrepomes
	}
362 d799787e Matthew Grooms
363 582c58ae jim-p
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none"))
364
		$conf .= "engine {$settings['engine']}\n";
365
366 67b0902f pierrepomes
	// server specific settings
367 8dc3ef67 Scott Ullrich
	if ($mode == 'server') {
368 d799787e Matthew Grooms
369
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
370 8dc3ef67 Scott Ullrich
		$mask = gen_subnet_mask($mask);
371
372 3c11bd3c Matthew Grooms
		// configure tls modes
373
		switch($settings['mode']) {
374
			case 'p2p_tls':
375
			case 'server_tls':
376 e62e2f8b Ermal Lu?i
			case 'server_user':
377 3c11bd3c Matthew Grooms
			case 'server_tls_user':
378 d799787e Matthew Grooms
				$conf .= "tls-server\n";
379 3c11bd3c Matthew Grooms
				break;
380 8dc3ef67 Scott Ullrich
		}
381 d799787e Matthew Grooms
382 3c11bd3c Matthew Grooms
		// configure p2p/server modes
383
		switch($settings['mode']) {
384
			case 'p2p_tls':
385
			case 'p2p_shared_key':
386 96033063 Erik Fonnesbeck
				$baselong = ip2long32($ip) & ip2long($mask);
387
				$ip1 = long2ip32($baselong + 1);
388
				$ip2 = long2ip32($baselong + 2);
389 3c11bd3c Matthew Grooms
				$conf .= "ifconfig $ip1 $ip2\n";
390
				break;
391
			case 'server_tls':
392
			case 'server_user':
393
			case 'server_tls_user':
394
				$conf .= "server {$ip} {$mask}\n";
395
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
396
				break;
397 8dc3ef67 Scott Ullrich
		}
398
399 3c11bd3c Matthew Grooms
		// configure user auth modes
400
		switch($settings['mode']) {
401
			case 'server_user':
402
				$conf .= "client-cert-not-required\n";
403
			case 'server_tls_user':
404
				$conf .= "username-as-common-name\n";
405 8a47c190 Ermal Lu?i
				if (!empty($settings['authmode'])) {
406
					$authcfgs = explode(",", $settings['authmode']);
407
					$sed = "\$authmodes=array(";
408
					$firstsed = 0;
409
					foreach ($authcfgs as $authcfg) {
410
						if ($firstsed > 0)
411
							$sed .= ",";
412
						$firstsed = 1;
413
						$sed .= "\"{$authcfg}\"";
414
					}
415 8901958c jim-p
					$sed .= ");\\\n";
416 53d41b68 Erik Fonnesbeck
					if ($settings['strictusercn'])
417 befad728 Ermal
						$sed .= "\$strictusercn = true;";
418 1bab0df1 jim-p
					$sed .= " \$modeid = \"{$mode_id}\";";
419 8a47c190 Ermal Lu?i
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
420
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
421
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
422 e8a58de4 Ermal Lu?i
				}
423 3c11bd3c Matthew Grooms
				break;
424 8dc3ef67 Scott Ullrich
		}
425
426 63084885 Matthew Grooms
		// The local port to listen on
427 d799787e Matthew Grooms
		$conf .= "lport {$settings['local_port']}\n";
428 c0cf27aa Scott Ullrich
429 63084885 Matthew Grooms
		// The management port to listen on
430 71ca2cb2 Ermal
		// Use unix socket to overcome the problem on any type of server
431
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
432
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
433 63084885 Matthew Grooms
434 3c11bd3c Matthew Grooms
		if ($settings['maxclients'])
435 d799787e Matthew Grooms
			$conf .= "max-clients {$settings['maxclients']}\n";
436
437 3c11bd3c Matthew Grooms
		// Can we push routes
438
		if ($settings['local_network']) {
439
			list($ip, $mask) = explode('/', $settings['local_network']);
440
			$mask = gen_subnet_mask($mask);
441
			$conf .= "push \"route $ip $mask\"\n";
442
		}
443
444
		switch($settings['mode']) {
445
			case 'server_tls':
446
			case 'server_user':
447
			case 'server_tls_user':
448 5d8cd81a jim-p
				// Configure client dhcp options
449 3c11bd3c Matthew Grooms
				openvpn_add_dhcpopts($settings, $conf);
450 5d8cd81a jim-p
				if ($settings['client2client'])
451
					$conf .= "client-to-client\n";
452 3c11bd3c Matthew Grooms
				break;
453
		}
454 bca35cff jim-p
		if (isset($settings['duplicate_cn']))
455
			$conf .= "duplicate-cn\n";
456 d799787e Matthew Grooms
	}
457
458 3c11bd3c Matthew Grooms
	// client specific settings
459 d799787e Matthew Grooms
460 3c11bd3c Matthew Grooms
	if ($mode == 'client') {
461 d799787e Matthew Grooms
462 3c11bd3c Matthew Grooms
		// configure p2p mode
463
		switch($settings['mode']) {
464
			case 'p2p_tls':
465
				$conf .= "tls-client\n";
466
			case 'shared_key':
467
				$conf .= "client\n";
468
				break;
469
		}
470 d799787e Matthew Grooms
471 e3924384 jim-p
		// If there is no bind option at all (ip and/or port), add "nobind" directive
472
		//  Otherwise, use the local port if defined, failing that, use lport 0 to 
473
		//  ensure a random source port.
474
		if ((empty($iface_ip)) && (!$settings['local_port']))
475
			$conf .= "nobind\n";
476
		elseif ($settings['local_port'])
477
			$conf .= "lport {$settings['local_port']}\n";
478
		else
479
			$conf .= "lport 0\n";
480 5708241f jim-p
481 4b887ef4 jim-p
		// Use unix socket to overcome the problem on any type of server
482
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
483 48a458d2 pierrepomes
484 3c11bd3c Matthew Grooms
		// The remote server
485
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
486
487 d799787e Matthew Grooms
		if (!empty($settings['use_shaper']))
488
			$conf .= "shaper {$settings['use_shaper']}\n";
489 ee506044 Scott Ullrich
490 d799787e Matthew Grooms
		if (!empty($settings['tunnel_network'])) {
491
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
492 8dc3ef67 Scott Ullrich
			$mask = gen_subnet_mask($mask);
493 96033063 Erik Fonnesbeck
			$baselong = ip2long32($ip) & ip2long($mask);
494
			$ip1 = long2ip32($baselong + 1);
495
			$ip2 = long2ip32($baselong + 2);
496 d799787e Matthew Grooms
			$conf .= "ifconfig $ip2 $ip1\n";
497 8dc3ef67 Scott Ullrich
		}
498 d799787e Matthew Grooms
499 762a24a3 Ermal Lu?i
		if ($settings['proxy_addr']) {
500
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
501
			if ($settings['proxy_authtype'] != "none") {
502
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
503
				$proxypas = "{$settings['proxy_user']}\n";
504
				$proxypas .= "{$settings['proxy_passwd']}\n";
505
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
506
			}
507
			$conf .= " \n";
508
		}
509 8dc3ef67 Scott Ullrich
	}
510
511 3c11bd3c Matthew Grooms
	// Add a remote network route if set
512
	if ($settings['remote_network']) {
513 8dc3ef67 Scott Ullrich
		list($ip, $mask) = explode('/', $settings['remote_network']);
514
		$mask = gen_subnet_mask($mask);
515 d799787e Matthew Grooms
		$conf .= "route $ip $mask\n";
516 8dc3ef67 Scott Ullrich
	}
517 afb07cf1 Scott Ullrich
518 d799787e Matthew Grooms
	// Write the settings for the keys
519 3c11bd3c Matthew Grooms
	switch($settings['mode']) {
520
		case 'p2p_shared_key':
521
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
522
			break;
523
		case 'p2p_tls':
524
		case 'server_tls':
525
		case 'server_tls_user':
526 e62e2f8b Ermal Lu?i
		case 'server_user':
527 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
528
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
529
			$cert = lookup_cert($settings['certref']);
530
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
531
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
532
			if ($mode == 'server')
533 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
534 6db02381 jim-p
			if (!empty($settings['crlref'])) {
535
				$crl = lookup_crl($settings['crlref']);
536
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
537
			}
538 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
539 756720e2 Pierre POMES
				if ($mode == "server") 
540 db746ce2 Ermal Lu?i
					$tlsopt = 0;
541
				else
542
					$tlsopt = 1;
543
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
544
			}
545 3c11bd3c Matthew Grooms
			break;
546 8dc3ef67 Scott Ullrich
	}
547
548 1cb0b40a Matthew Grooms
	if ($settings['compression'])
549 d799787e Matthew Grooms
		$conf .= "comp-lzo\n";
550
551
	if ($settings['passtos'])
552
		$conf .= "passtos\n";
553
554
	if ($settings['resolve_retry'])
555
		$conf .= "resolv-retry infinite\n";
556
557
	if ($settings['dynamic_ip']) {
558
		$conf .= "persist-remote-ip\n";
559
		$conf .= "float\n";
560 8dc3ef67 Scott Ullrich
	}
561 afb07cf1 Scott Ullrich
562 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
563
564
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
565
	file_put_contents($fpath, $conf);
566 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
567
	//chgrp($fpath, 'nobody');
568 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
569
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
570
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
571
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
572 d799787e Matthew Grooms
}
573
574 fc05822b jim-p
function openvpn_restart($mode, $settings) {
575 d799787e Matthew Grooms
	global $g, $config;
576
577
	$vpnid = $settings['vpnid'];
578
	$mode_id = $mode.$vpnid;
579
580 76369bfc Matthew Grooms
	/* kill the process if running */
581 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
582 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
583 705c8ec9 Matthew Grooms
584 76369bfc Matthew Grooms
		/* read the pid file */
585
		$pid = rtrim(file_get_contents($pfile));
586
		unlink($pfile);
587 705c8ec9 Matthew Grooms
588 76369bfc Matthew Grooms
		/* send a term signal to the process */
589
		posix_kill($pid, SIGTERM);
590
591
		/* wait until the process exits */
592
		while(posix_kill($pid, 0))
593
			usleep(250000);
594
	}
595 d799787e Matthew Grooms
596 a1cab2c7 Ermal
	if (isset($settings['disable']))
597 d799787e Matthew Grooms
		return;
598
599 705c8ec9 Matthew Grooms
	/* start the new process */
600 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
601
	mwexec_bg("nohup openvpn --config {$fpath}");
602 847cd48d Ermal
603
	if (!$g['booting'])
604
		send_event("filter reload");
605 afb07cf1 Scott Ullrich
}
606
607 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
608 d799787e Matthew Grooms
	global $g, $config;
609
610
	$vpnid = $settings['vpnid'];
611
	$mode_id = $mode.$vpnid;
612
613 095a95ae Matthew Grooms
	$tunname = "tun{$vpnid}";
614
	if ($mode == "server")
615
		$devname = "ovpns{$vpnid}";
616
	else
617
		$devname = "ovpnc{$vpnid}";
618 dc408939 Matthew Grooms
619 76369bfc Matthew Grooms
	/* kill the process if running */
620 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
621 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
622 dc408939 Matthew Grooms
623 76369bfc Matthew Grooms
		/* read the pid file */
624
		$pid = trim(file_get_contents($pfile));
625
		unlink($pfile);
626
627
		/* send a term signal to the process */
628
		posix_kill($pid, SIGTERM);
629
	}
630 705c8ec9 Matthew Grooms
631 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
632
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
633
634 dc408939 Matthew Grooms
	/* restore the original adapter name */
635
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
636
637
	/* remove the configuration files */
638
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
639 d799787e Matthew Grooms
}
640 afb07cf1 Scott Ullrich
641 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
642 8dc3ef67 Scott Ullrich
	global $g, $config;
643
644 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
645 8dc3ef67 Scott Ullrich
646 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
647 d799787e Matthew Grooms
		unlink_if_exists($fpath);
648 c876662c Scott Ullrich
		return;
649
	}
650 d799787e Matthew Grooms
651 8dc3ef67 Scott Ullrich
	$conf = '';
652 d799787e Matthew Grooms
	if ($settings['block'])
653
		$conf .= "disable\n";
654
655
	if ($settings['push_reset'])
656
		$conf .= "push-reset\n";
657
658
	if (!empty($settings['tunnel_network'])) {
659
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
660 96033063 Erik Fonnesbeck
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
661
		$ip1 = long2ip32($baselong + 1);
662
		$ip2 = long2ip32($baselong + 2);
663 d799787e Matthew Grooms
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
664 8dc3ef67 Scott Ullrich
	}
665 6d031071 Martin Fuchs
666 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
667 8dc3ef67 Scott Ullrich
668 d799787e Matthew Grooms
	if ($settings['gwredir'])
669
		$conf .= "push \"redirect-gateway def1\"\n";
670 6d031071 Martin Fuchs
671 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
672 8dc3ef67 Scott Ullrich
673 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
674
	chown($fpath, 'nobody');
675
	chgrp($fpath, 'nobody');
676
}
677 8dc3ef67 Scott Ullrich
678 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
679 add2e3f7 Scott Ullrich
	global $g, $config;
680 3c2e5528 Scott Ullrich
681 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
682 d799787e Matthew Grooms
	unlink_if_exists($fpath);
683 267ab13f Ermal Luçi
}
684 afb07cf1 Scott Ullrich
685 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
686 fc05822b jim-p
function openvpn_resync($mode, $settings) {
687 dc408939 Matthew Grooms
	openvpn_reconfigure($mode, $settings);
688
	openvpn_restart($mode, $settings);
689 afb07cf1 Scott Ullrich
}
690
691 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
692 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
693 d799787e Matthew Grooms
	global $g, $config;
694 267ab13f Ermal Luçi
695 3cb54b54 Matthew Grooms
	// delay our setup until the system
696
	// has a chance to init our paths
697
	if (!file_exists($g['varetc_path']."/openvpn") ||
698
		!file_exists($g['varetc_path']."/openvpn-csc"))
699
		return;
700
701 34bc1324 Matthew Grooms
	if (!is_array($config['openvpn']))
702
		$config['openvpn'] = array();
703
704 15b414e6 Matthew Grooms
/*
705 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
706
		echo "Configuring OpenVPN Parameters ...\n";
707 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
708 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
709
		$config['openvpn']['dh-parameters'] = $dh_parameters;
710 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
711 34bc1324 Matthew Grooms
	}
712
713
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
714
	if (!file_exists($path_ovdh)) {
715
		$dh_parameters = $config['openvpn']['dh-parameters'];
716
		$dh_parameters = base64_decode($dh_parameters);
717
		file_put_contents($path_ovdh, $dh_parameters);
718
	}
719 15b414e6 Matthew Grooms
*/
720 739c9efd Ermal
	if ($interface <> "")
721 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances for interface " . convert_friendly_interface_to_friendly_descr($interface) . ".");
722 739c9efd Ermal
	else
723 a82e6d37 Chris Buechler
		log_error("Resyncing OpenVPN instances."); 
724 34bc1324 Matthew Grooms
725 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
726
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
727 739c9efd Ermal
			if ($interface <> "" && $interface != $settings['interface'])
728 c7f60193 Ermal
				continue;
729 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
730 c7f60193 Ermal
		}
731
	}
732 5b237745 Scott Ullrich
733 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
734
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
735 739c9efd Ermal
			if ($interface <> "" && $interface != $settings['interface'])
736 c7f60193 Ermal
				continue;
737 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
738 c7f60193 Ermal
		}
739
	}
740 afb07cf1 Scott Ullrich
741 d799787e Matthew Grooms
	if (is_array($config['openvpn']['openvpn-csc']))
742 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
743
			openvpn_resync_csc($settings);
744 afb07cf1 Scott Ullrich
745 5b237745 Scott Ullrich
}
746 702a4702 Scott Ullrich
747 53663f57 jim-p
function openvpn_get_active_servers() {
748 71ca2cb2 Ermal
	global $config, $g;
749
750 53663f57 jim-p
	$servers = array();
751
	if (is_array($config['openvpn']['openvpn-server'])) {
752
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
753
	
754
			$prot = $settings['protocol'];
755
			$port = $settings['local_port'];
756
	
757
			$server = array();
758
			$server['port'] = $settings['local_port'];
759 41be629f jim-p
			$server['mode'] = $settings['mode'];
760 53663f57 jim-p
			if ($settings['description'])
761
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
762
			else
763
				$server['name'] = "Server {$prot}:{$port}";
764
			$server['conns'] = array();
765
	
766 71ca2cb2 Ermal
			$vpnid = $settings['vpnid'];
767
                        $mode_id = "server{$vpnid}";
768
			$server['mgmt'] = $mode_id;
769
                        $tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
770 53663f57 jim-p
			$errval;
771
			$errstr;
772
	
773
			/* open a tcp connection to the management port of each server */
774
			$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
775
			if ($fp) {
776 19e3d450 Ermal
				stream_set_timeout($fp, 1);
777 53663f57 jim-p
	
778
				/* send our status request */
779
				fputs($fp, "status 2\n");
780
	
781
				/* recv all response lines */
782
				while (!feof($fp)) {
783
	
784
					/* read the next line */
785
					$line = fgets($fp, 1024);
786
	
787 b0140675 Ermal
					$info = stream_get_meta_data($fp);
788
					if ($info['timed_out'])
789
						break;
790
791 53663f57 jim-p
					/* parse header list line */
792
					if (strstr($line, "HEADER"))
793
						continue;
794
	
795
					/* parse end of output line */
796 a8abc4b3 jim-p
					if (strstr($line, "END") || strstr($line, "ERROR"))
797 53663f57 jim-p
						break;
798
	
799
					/* parse client list line */
800
					if (strstr($line, "CLIENT_LIST")) {
801
						$list = explode(",", $line);
802
						$conn = array();
803
						$conn['common_name'] = $list[1];
804
						$conn['remote_host'] = $list[2];
805
						$conn['virtual_addr'] = $list[3];
806
						$conn['bytes_recv'] = $list[4];
807
						$conn['bytes_sent'] = $list[5];
808
						$conn['connect_time'] = $list[6];
809
						$server['conns'][] = $conn;
810
					}
811
				}
812
	
813
				/* cleanup */
814
				fclose($fp);
815
			} else {
816
				$conn = array();
817
				$conn['common_name'] = "[error]";
818
				$conn['remote_host'] = "Management Daemon Unreachable";
819
				$conn['virtual_addr'] = "";
820
				$conn['bytes_recv'] = 0;
821
				$conn['bytes_sent'] = 0;
822
				$conn['connect_time'] = 0;
823
				$server['conns'][] = $conn;
824
			}
825
	
826
			$servers[] = $server;
827
		}
828
	}
829
	return $servers;
830
}
831
832
function openvpn_get_active_clients() {
833 71ca2cb2 Ermal
	global $config, $g;
834
835 53663f57 jim-p
	$clients = array();
836
	if (is_array($config['openvpn']['openvpn-client'])) {
837
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
838
	
839
			$prot = $settings['protocol'];
840
			$port = $settings['local_port'];
841
	
842
			$client = array();
843
			$client['port'] = $settings['local_port'];
844
			if ($settings['description'])
845
				$client['name'] = "{$settings['description']} {$prot}:{$port}";
846
			else
847
				$client['name'] = "Client {$prot}:{$port}";
848
	
849 71ca2cb2 Ermal
			$vpnid = $settings['vpnid'];
850
        		$mode_id = "client{$vpnid}";
851
			$client['mgmt'] = $mode_id;
852
			$tcpcli = "unix://{$g['varetc_path']}/openvpn/{$mode_id}.sock";
853 53663f57 jim-p
			$errval;
854
			$errstr;
855
	
856
			$client['status']="down";
857
	
858
			/* open a tcp connection to the management port of each cli */
859
			$fp = @stream_socket_client($tcpcli, $errval, $errstr, 1);
860
			if ($fp) {
861 19e3d450 Ermal
				stream_set_timeout($fp, 1);
862 53663f57 jim-p
				/* send our status request */
863
				fputs($fp, "state 1\n");
864
	
865
				/* recv all response lines */
866
				while (!feof($fp)) {
867
					/* read the next line */
868
					$line = fgets($fp, 1024);
869 b0140675 Ermal
					
870
					$info = stream_get_meta_data($fp);
871
					if ($info['timed_out'])
872
						break;	
873
874 53663f57 jim-p
					/* Get the client state */
875
					if (strstr($line,"CONNECTED")) {
876
						$client['status']="up";
877
						$list = explode(",", $line);
878
	
879
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
880
						$client['virtual_addr']  = $list[3];
881
						$client['remote_host'] = $list[4];
882
					}
883
					/* parse end of output line */
884 a8abc4b3 jim-p
					if (strstr($line, "END") || strstr($line, "ERROR"))
885 53663f57 jim-p
						break;
886
				}
887
	
888
				/* If up, get read/write stats */
889
				if (strcmp($client['status'], "up") == 0) {
890
					fputs($fp, "status 2\n");
891
					/* recv all response lines */
892
					while (!feof($fp)) {
893
						/* read the next line */
894
						$line = fgets($fp, 1024);
895
	
896 b0140675 Ermal
						$info = stream_get_meta_data($fp);
897
						if ($info['timed_out'])
898
							break;	
899
900 53663f57 jim-p
						if (strstr($line,"TCP/UDP read bytes")) {
901
							$list = explode(",", $line);
902
							$client['bytes_recv'] = $list[1];
903
						}
904
	
905
						if (strstr($line,"TCP/UDP write bytes")) {
906
							$list = explode(",", $line);
907
							$client['bytes_sent'] = $list[1];
908
						}
909
	
910
						/* parse end of output line */
911
						if (strstr($line, "END"))
912
							break;
913
					}
914
				}
915
	
916
				fclose($fp);
917
	
918
			} else {
919
				$DisplayNote=true;
920
				$client['remote_host'] = "No Management Daemon";
921
				$client['virtual_addr'] = "See Note Below";
922
				$client['bytes_recv'] = 0;
923
				$client['bytes_sent'] = 0;
924
				$client['connect_time'] = 0;
925
			}
926
	
927
			$clients[] = $client;
928
		}
929
	}
930
	return $clients;
931
}
932 8e022a76 jim-p
933
function openvpn_refresh_crls() {
934
	global $g, $config;
935
936
	if (!file_exists($g['varetc_path']."/openvpn"))
937
		return;
938
939
	if (is_array($config['openvpn']['openvpn-server'])) {
940
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
941
			if (empty($settings))
942
				continue;
943
			if (isset($settings['disable']))
944
				continue;
945
			// Write the settings for the keys
946
			switch($settings['mode']) {
947
				case 'p2p_tls':
948
				case 'server_tls':
949
				case 'server_tls_user':
950
				case 'server_user':
951
					if (!empty($settings['crlref'])) {
952
						$crl = lookup_crl($settings['crlref']);
953
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
954
						file_put_contents($fpath, base64_decode($crl['text']));
955
						@chmod($fpath, 0644);
956
					}
957
					break;
958
			}
959
		}
960
	}
961
}
962
963 756720e2 Pierre POMES
?>