Project

General

Profile

Download (23.8 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
function openvpn_validate_host($value, $name) {
176
	$value = trim($value);
177 3e2bd5de Ermal Lu?i
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value)))
178 d799787e Matthew Grooms
		return "The field '$name' must contain a valid IP address or domain name.";
179
	return false;
180 8dc3ef67 Scott Ullrich
}
181
182
function openvpn_validate_port($value, $name) {
183
	$value = trim($value);
184 3e2bd5de Ermal Lu?i
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535))
185 8dc3ef67 Scott Ullrich
		return "The field '$name' must contain a valid port, ranging from 0 to 65535.";
186 b398bbca Martin Fuchs
	return false;
187 8dc3ef67 Scott Ullrich
}
188
189
function openvpn_validate_cidr($value, $name) {
190
	$value = trim($value);
191
	if (!empty($value)) {
192
		list($ip, $mask) = explode('/', $value);
193
		if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
194
			return "The field '$name' must contain a valid CIDR range.";
195
	}
196
	return false;
197 afb07cf1 Scott Ullrich
}
198
199 d799787e Matthew Grooms
function openvpn_add_dhcpopts(& $settings, & $conf) {
200 afb07cf1 Scott Ullrich
201 d799787e Matthew Grooms
	if (!empty($settings['dns_domain'])) 
202
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
203 add2e3f7 Scott Ullrich
204 d799787e Matthew Grooms
	if (!empty($settings['dns_server1']))
205
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
206
	if (!empty($settings['dns_server2']))
207
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
208
	if (!empty($settings['dns_server3']))
209
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
210
	if (!empty($settings['dns_server4']))
211
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
212 f9927473 Scott Ullrich
213 d799787e Matthew Grooms
	if (!empty($settings['ntp_server1']))
214
		$conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
215
	if (!empty($settings['ntp_server2']))
216
		$conf .= "push \"dhcp-option NTP {$settings['dhcp_ntp']}\"\n";
217 f9927473 Scott Ullrich
218 d799787e Matthew Grooms
	if ($settings['netbios_enable']) {
219 add2e3f7 Scott Ullrich
220 095a95ae Matthew Grooms
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0))
221
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
222
		if (!empty($settings['dhcp_nbtscope'])) 
223 d799787e Matthew Grooms
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
224 8dc3ef67 Scott Ullrich
225 d799787e Matthew Grooms
		if (!empty($settings['wins_server1']))
226
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
227
		if (!empty($settings['wins_server2']))
228
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
229 add2e3f7 Scott Ullrich
230 d799787e Matthew Grooms
		if (!empty($settings['nbdd_server1']))
231
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
232
	}
233 8dc3ef67 Scott Ullrich
234 d799787e Matthew Grooms
	if ($settings['gwredir']) 
235
		$conf .= "push \"redirect-gateway def1\"\n";
236
}
237 24012690 Scott Ullrich
238 d799787e Matthew Grooms
function openvpn_add_custom(& $settings, & $conf) {
239 add2e3f7 Scott Ullrich
240 d799787e Matthew Grooms
	if ($settings['custom_options']) {
241 8dc3ef67 Scott Ullrich
242 d799787e Matthew Grooms
		$options = explode(';', $settings['custom_options']);
243
244
		if (is_array($options)) {
245
			foreach ($options as $option)
246
				$conf .= "$option\n";
247
		} else
248
			$conf .= "{$settings['custom_options']}\n";
249 add2e3f7 Scott Ullrich
	}
250
}
251
252 691fbf14 Ermal Lu?i
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
253 d799787e Matthew Grooms
	global $g;
254 add2e3f7 Scott Ullrich
255 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
256
	file_put_contents($fpath, base64_decode($data));
257 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
258
	//chgrp($fpath, 'nobody');
259 6f27412f Ermal Lu?i
	@chmod($fpath, 0600);
260 d799787e Matthew Grooms
261 691fbf14 Ermal Lu?i
	$conf .= "{$directive} {$fpath} {$opt}\n";
262 4eefa6e8 Scott Ullrich
}
263
264 dc408939 Matthew Grooms
function openvpn_reconfigure($mode,& $settings) {
265 add2e3f7 Scott Ullrich
	global $g, $config;
266 afb07cf1 Scott Ullrich
267 93a0a028 Ermal Luçi
	if (empty($settings))
268
		return;
269 a1cab2c7 Ermal
	if (isset($settings['disable'])) 
270 4eefa6e8 Scott Ullrich
		return;
271
272 fdd725f0 Ermal Luçi
	/*
273 d799787e Matthew Grooms
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
274
	 * we use a vpnid number which is allocated for a particular client
275
	 * or server configuration. ( see openvpn_vpnid_next() )
276 fdd725f0 Ermal Luçi
	 */
277 8874c692 Ermal Luçi
278 d799787e Matthew Grooms
	$vpnid = $settings['vpnid'];
279
	$mode_id = $mode.$vpnid;
280 8874c692 Ermal Luçi
281 bd7ca506 jim-p
	if (isset($settings['dev_mode']))
282
		$tunname = "{$settings['dev_mode']}{$vpnid}";
283
	else {	/* defaults to tun */
284
		$tunname = "tun{$vpnid}";
285
		$settings['dev_mode'] = "tun";
286 691fbf14 Ermal Lu?i
	}
287
288 bd7ca506 jim-p
	if ($mode == "server")
289
		$devname = "ovpns{$vpnid}";
290
	else
291
		$devname = "ovpnc{$vpnid}";
292 8874c692 Ermal Luçi
293 bd7ca506 jim-p
	/* is our device already configured */
294
	if (mwexec("/sbin/ifconfig {$devname}")) {
295 dc408939 Matthew Grooms
296 bd7ca506 jim-p
		/* create the tap device if required */
297
		if (!file_exists("/dev/{$tunname}"))
298
			exec("/sbin/ifconfig {$tunname} create");
299 98872d89 Ermal Luçi
300 bd7ca506 jim-p
		/* rename the device */
301
		mwexec("/sbin/ifconfig {$tunname} name {$devname}");
302 095a95ae Matthew Grooms
303 bd7ca506 jim-p
		/* add the device to the openvpn group */
304
		mwexec("/sbin/ifconfig {$devname} group openvpn");
305 dc408939 Matthew Grooms
	}
306 d799787e Matthew Grooms
307 dc408939 Matthew Grooms
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
308 c0cf27aa Scott Ullrich
	$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
309
	$cipher = $settings['crypto'];
310 d799787e Matthew Grooms
311
	$interface = $settings['interface'];
312 67b0902f pierrepomes
	$ipaddr = $settings['ipaddr'];
313 d799787e Matthew Grooms
314 67b0902f pierrepomes
	// If a specific ip address (VIP) is requested, use it.
315
	// Otherwise, if a specific interface is requested, use it
316
	// If "any" interface was selected, local directive will be ommited.
317
	if (!empty($ipaddr)) {
318
		$iface_ip=$ipaddr;
319 3d06e8f0 pierrepomes
	} else {
320 67b0902f pierrepomes
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
321 507af8dd pierrepomes
			$iface_ip=get_interface_ip($interface);
322 67b0902f pierrepomes
		}
323 3d06e8f0 pierrepomes
	}
324 d799787e Matthew Grooms
325 bd7ca506 jim-p
	$conf  = "dev {$devname}\n";
326
	$conf .= "dev-type {$settings['dev_mode']}\n";
327
	$conf .= "dev-node /dev/{$tunname}\n";
328 3c11bd3c Matthew Grooms
	$conf .= "writepid {$pfile}\n";
329
	$conf .= "#user nobody\n";
330
	$conf .= "#group nobody\n";
331 d1014c18 Chris Buechler
	$conf .= "script-security 3\n";
332 3c11bd3c Matthew Grooms
	$conf .= "daemon\n";
333
	$conf .= "keepalive 10 60\n";
334
	$conf .= "ping-timer-rem\n";
335
	$conf .= "persist-tun\n";
336
	$conf .= "persist-key\n";
337
	$conf .= "proto {$proto}\n";
338
	$conf .= "cipher {$cipher}\n";
339 8d964cea Ermal
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
340
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
341 3c11bd3c Matthew Grooms
342 67b0902f pierrepomes
	if (!empty($iface_ip)) {
343 48a458d2 pierrepomes
		$conf .= "local {$iface_ip}\n";	
344 67b0902f pierrepomes
	}
345 d799787e Matthew Grooms
346 67b0902f pierrepomes
	// server specific settings
347 8dc3ef67 Scott Ullrich
	if ($mode == 'server') {
348 d799787e Matthew Grooms
349
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
350 8dc3ef67 Scott Ullrich
		$mask = gen_subnet_mask($mask);
351
352 3c11bd3c Matthew Grooms
		// configure tls modes
353
		switch($settings['mode']) {
354
			case 'p2p_tls':
355
			case 'server_tls':
356 e62e2f8b Ermal Lu?i
			case 'server_user':
357 3c11bd3c Matthew Grooms
			case 'server_tls_user':
358 d799787e Matthew Grooms
				$conf .= "tls-server\n";
359 3c11bd3c Matthew Grooms
				break;
360 8dc3ef67 Scott Ullrich
		}
361 d799787e Matthew Grooms
362 3c11bd3c Matthew Grooms
		// configure p2p/server modes
363
		switch($settings['mode']) {
364
			case 'p2p_tls':
365
			case 'p2p_shared_key':
366 96033063 Erik Fonnesbeck
				$baselong = ip2long32($ip) & ip2long($mask);
367
				$ip1 = long2ip32($baselong + 1);
368
				$ip2 = long2ip32($baselong + 2);
369 3c11bd3c Matthew Grooms
				$conf .= "ifconfig $ip1 $ip2\n";
370
				break;
371
			case 'server_tls':
372
			case 'server_user':
373
			case 'server_tls_user':
374
				$conf .= "server {$ip} {$mask}\n";
375
				$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc\n";
376
				break;
377 8dc3ef67 Scott Ullrich
		}
378
379 3c11bd3c Matthew Grooms
		// configure user auth modes
380
		switch($settings['mode']) {
381
			case 'server_user':
382
				$conf .= "client-cert-not-required\n";
383
			case 'server_tls_user':
384
				$conf .= "username-as-common-name\n";
385 8a47c190 Ermal Lu?i
				if (!empty($settings['authmode'])) {
386
					$authcfgs = explode(",", $settings['authmode']);
387
					$sed = "\$authmodes=array(";
388
					$firstsed = 0;
389
					foreach ($authcfgs as $authcfg) {
390
						if ($firstsed > 0)
391
							$sed .= ",";
392
						$firstsed = 1;
393
						$sed .= "\"{$authcfg}\"";
394
					}
395
					$sed .= ");";
396
					mwexec("/bin/cat /etc/inc/openvpn.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/openvpn/{$mode_id}.php");
397
					mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.php");
398
					$conf .= "auth-user-pass-verify {$g['varetc_path']}/openvpn/{$mode_id}.php via-env\n";
399 e8a58de4 Ermal Lu?i
				}
400 3c11bd3c Matthew Grooms
				break;
401 8dc3ef67 Scott Ullrich
		}
402
403 63084885 Matthew Grooms
		// The local port to listen on
404 d799787e Matthew Grooms
		$conf .= "lport {$settings['local_port']}\n";
405 c0cf27aa Scott Ullrich
406 63084885 Matthew Grooms
		// The management port to listen on
407
		$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
408
409 3c11bd3c Matthew Grooms
		if ($settings['maxclients'])
410 d799787e Matthew Grooms
			$conf .= "max-clients {$settings['maxclients']}\n";
411
412 3c11bd3c Matthew Grooms
		// Can we push routes
413
		if ($settings['local_network']) {
414
			list($ip, $mask) = explode('/', $settings['local_network']);
415
			$mask = gen_subnet_mask($mask);
416
			$conf .= "push \"route $ip $mask\"\n";
417
		}
418
419
		switch($settings['mode']) {
420
			case 'server_tls':
421
			case 'server_user':
422
			case 'server_tls_user':
423 5d8cd81a jim-p
				// Configure client dhcp options
424 3c11bd3c Matthew Grooms
				openvpn_add_dhcpopts($settings, $conf);
425 5d8cd81a jim-p
				if ($settings['client2client'])
426
					$conf .= "client-to-client\n";
427 3c11bd3c Matthew Grooms
				break;
428
		}
429 d799787e Matthew Grooms
	}
430
431 3c11bd3c Matthew Grooms
	// client specific settings
432 d799787e Matthew Grooms
433 3c11bd3c Matthew Grooms
	if ($mode == 'client') {
434 d799787e Matthew Grooms
435 3c11bd3c Matthew Grooms
		// configure p2p mode
436
		switch($settings['mode']) {
437
			case 'p2p_tls':
438
				$conf .= "tls-client\n";
439
			case 'shared_key':
440
				$conf .= "client\n";
441
				break;
442
		}
443 d799787e Matthew Grooms
444
		// The port we'll listen at
445 8fb49e83 pierrepomes
		// If local_port is used, bind the management port
446 d0f6649c pierrepomes
		if ($settings['local_port']) {
447 d799787e Matthew Grooms
			$conf .= "lport {$settings['local_port']}\n";
448 d0f6649c pierrepomes
			$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
449
		}
450 48a458d2 pierrepomes
451
		// If there is no bind option at all (ip and/or port), add "nobind" directive
452
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
453 d799787e Matthew Grooms
			$conf .= "nobind\n";
454 48a458d2 pierrepomes
		}
455 8dc3ef67 Scott Ullrich
456 3c11bd3c Matthew Grooms
		// The remote server
457
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
458
459 d799787e Matthew Grooms
		if (!empty($settings['use_shaper']))
460
			$conf .= "shaper {$settings['use_shaper']}\n";
461 ee506044 Scott Ullrich
462 d799787e Matthew Grooms
		if (!empty($settings['tunnel_network'])) {
463
			list($ip, $mask) = explode('/', $settings['tunnel_network']);
464 8dc3ef67 Scott Ullrich
			$mask = gen_subnet_mask($mask);
465 96033063 Erik Fonnesbeck
			$baselong = ip2long32($ip) & ip2long($mask);
466
			$ip1 = long2ip32($baselong + 1);
467
			$ip2 = long2ip32($baselong + 2);
468 d799787e Matthew Grooms
			$conf .= "ifconfig $ip2 $ip1\n";
469 8dc3ef67 Scott Ullrich
		}
470 d799787e Matthew Grooms
471 762a24a3 Ermal Lu?i
		if ($settings['proxy_addr']) {
472
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
473
			if ($settings['proxy_authtype'] != "none") {
474
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
475
				$proxypas = "{$settings['proxy_user']}\n";
476
				$proxypas .= "{$settings['proxy_passwd']}\n";
477
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
478
			}
479
			$conf .= " \n";
480
		}
481 8dc3ef67 Scott Ullrich
	}
482
483 3c11bd3c Matthew Grooms
	// Add a remote network route if set
484
	if ($settings['remote_network']) {
485 8dc3ef67 Scott Ullrich
		list($ip, $mask) = explode('/', $settings['remote_network']);
486
		$mask = gen_subnet_mask($mask);
487 d799787e Matthew Grooms
		$conf .= "route $ip $mask\n";
488 8dc3ef67 Scott Ullrich
	}
489 afb07cf1 Scott Ullrich
490 d799787e Matthew Grooms
	// Write the settings for the keys
491 3c11bd3c Matthew Grooms
	switch($settings['mode']) {
492
		case 'p2p_shared_key':
493
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
494
			break;
495
		case 'p2p_tls':
496
		case 'server_tls':
497
		case 'server_tls_user':
498 e62e2f8b Ermal Lu?i
		case 'server_user':
499 3c11bd3c Matthew Grooms
			$ca = lookup_ca($settings['caref']);
500
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
501
			$cert = lookup_cert($settings['certref']);
502
			openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
503
			openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
504
			if ($mode == 'server')
505 fe787fc7 Matthew Grooms
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
506 3c11bd3c Matthew Grooms
			if ($settings['crl'])
507
				openvpn_add_keyfile($settings['crl'], $conf, $mode_id, "crl-verify");
508 db746ce2 Ermal Lu?i
			if ($settings['tls']) {
509 e62e2f8b Ermal Lu?i
				if (stristr($settings['mode'], "server"))
510 db746ce2 Ermal Lu?i
					$tlsopt = 0;
511
				else
512
					$tlsopt = 1;
513
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
514
			}
515 3c11bd3c Matthew Grooms
			break;
516 8dc3ef67 Scott Ullrich
	}
517
518 1cb0b40a Matthew Grooms
	if ($settings['compression'])
519 d799787e Matthew Grooms
		$conf .= "comp-lzo\n";
520
521
	if ($settings['passtos'])
522
		$conf .= "passtos\n";
523
524
	if ($settings['resolve_retry'])
525
		$conf .= "resolv-retry infinite\n";
526
527
	if ($settings['dynamic_ip']) {
528
		$conf .= "persist-remote-ip\n";
529
		$conf .= "float\n";
530 8dc3ef67 Scott Ullrich
	}
531 afb07cf1 Scott Ullrich
532 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
533
534
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
535
	file_put_contents($fpath, $conf);
536 f9ac3784 Ermal Lu?i
	//chown($fpath, 'nobody');
537
	//chgrp($fpath, 'nobody');
538 6f27412f Ermal Lu?i
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
539
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
540
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
541
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
542 d799787e Matthew Grooms
}
543
544 dc408939 Matthew Grooms
function openvpn_restart($mode, & $settings) {
545 d799787e Matthew Grooms
	global $g, $config;
546
547
	$vpnid = $settings['vpnid'];
548
	$mode_id = $mode.$vpnid;
549
550 76369bfc Matthew Grooms
	/* kill the process if running */
551 705c8ec9 Matthew Grooms
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
552 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
553 705c8ec9 Matthew Grooms
554 76369bfc Matthew Grooms
		/* read the pid file */
555
		$pid = rtrim(file_get_contents($pfile));
556
		unlink($pfile);
557 705c8ec9 Matthew Grooms
558 76369bfc Matthew Grooms
		/* send a term signal to the process */
559
		posix_kill($pid, SIGTERM);
560
561
		/* wait until the process exits */
562
		while(posix_kill($pid, 0))
563
			usleep(250000);
564
	}
565 d799787e Matthew Grooms
566 a1cab2c7 Ermal
	if (isset($settings['disable']))
567 d799787e Matthew Grooms
		return;
568
569 705c8ec9 Matthew Grooms
	/* start the new process */
570 d799787e Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
571
	mwexec_bg("nohup openvpn --config {$fpath}");
572
	touch("{$g['tmp_path']}/filter_dirty");
573 afb07cf1 Scott Ullrich
}
574
575 dc408939 Matthew Grooms
function openvpn_delete($mode, & $settings) {
576 d799787e Matthew Grooms
	global $g, $config;
577
578
	$vpnid = $settings['vpnid'];
579
	$mode_id = $mode.$vpnid;
580
581 095a95ae Matthew Grooms
	$tunname = "tun{$vpnid}";
582
	if ($mode == "server")
583
		$devname = "ovpns{$vpnid}";
584
	else
585
		$devname = "ovpnc{$vpnid}";
586 dc408939 Matthew Grooms
587 76369bfc Matthew Grooms
	/* kill the process if running */
588 dc408939 Matthew Grooms
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
589 76369bfc Matthew Grooms
	if (file_exists($pfile)) {
590 dc408939 Matthew Grooms
591 76369bfc Matthew Grooms
		/* read the pid file */
592
		$pid = trim(file_get_contents($pfile));
593
		unlink($pfile);
594
595
		/* send a term signal to the process */
596
		posix_kill($pid, SIGTERM);
597
	}
598 705c8ec9 Matthew Grooms
599 095a95ae Matthew Grooms
	/* remove the device from the openvpn group */
600
	mwexec("/sbin/ifconfig {$devname} -group openvpn");
601
602 dc408939 Matthew Grooms
	/* restore the original adapter name */
603
	mwexec("/sbin/ifconfig {$devname} name {$tunname}");
604
605
	/* remove the configuration files */
606
	mwexec("/bin/rm {$g['varetc_path']}/openvpn/{$mode_id}.*");
607 d799787e Matthew Grooms
}
608 afb07cf1 Scott Ullrich
609 dc408939 Matthew Grooms
function openvpn_resync_csc(& $settings) {
610 8dc3ef67 Scott Ullrich
	global $g, $config;
611
612 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
613 8dc3ef67 Scott Ullrich
614 a1cab2c7 Ermal
	if (isset($settings['disable'])) {
615 d799787e Matthew Grooms
		unlink_if_exists($fpath);
616 c876662c Scott Ullrich
		return;
617
	}
618 d799787e Matthew Grooms
619 8dc3ef67 Scott Ullrich
	$conf = '';
620 d799787e Matthew Grooms
	if ($settings['block'])
621
		$conf .= "disable\n";
622
623
	if ($settings['push_reset'])
624
		$conf .= "push-reset\n";
625
626
	if (!empty($settings['tunnel_network'])) {
627
		list($ip, $mask) = explode('/', $settings['tunnel_network']);
628 96033063 Erik Fonnesbeck
		$baselong = ip2long32($ip) & gen_subnet_mask_long($mask);
629
		$ip1 = long2ip32($baselong + 1);
630
		$ip2 = long2ip32($baselong + 2);
631 d799787e Matthew Grooms
		$conf .= "ifconfig-push {$ip1} {$ip2}\n";
632 8dc3ef67 Scott Ullrich
	}
633 6d031071 Martin Fuchs
634 d799787e Matthew Grooms
	openvpn_add_dhcpopts($settings, $conf);
635 8dc3ef67 Scott Ullrich
636 d799787e Matthew Grooms
	if ($settings['gwredir'])
637
		$conf .= "push \"redirect-gateway def1\"\n";
638 6d031071 Martin Fuchs
639 d799787e Matthew Grooms
	openvpn_add_custom($settings, $conf);
640 8dc3ef67 Scott Ullrich
641 d799787e Matthew Grooms
	file_put_contents($fpath, $conf);
642
	chown($fpath, 'nobody');
643
	chgrp($fpath, 'nobody');
644
}
645 8dc3ef67 Scott Ullrich
646 dc408939 Matthew Grooms
function openvpn_delete_csc(& $settings) {
647 add2e3f7 Scott Ullrich
	global $g, $config;
648 3c2e5528 Scott Ullrich
649 ea28182c Matthew Grooms
	$fpath = $g['varetc_path']."/openvpn-csc/".$settings['common_name'];
650 d799787e Matthew Grooms
	unlink_if_exists($fpath);
651 267ab13f Ermal Luçi
}
652 afb07cf1 Scott Ullrich
653 24012690 Scott Ullrich
// Resync the configuration and restart the VPN
654 dc408939 Matthew Grooms
function openvpn_resync($mode, & $settings) {
655
	openvpn_reconfigure($mode, $settings);
656
	openvpn_restart($mode, $settings);
657 afb07cf1 Scott Ullrich
}
658
659 add2e3f7 Scott Ullrich
// Resync and restart all VPNs
660 c7f60193 Ermal
function openvpn_resync_all($interface = "") {
661 d799787e Matthew Grooms
	global $g, $config;
662 267ab13f Ermal Luçi
663 3cb54b54 Matthew Grooms
	// delay our setup until the system
664
	// has a chance to init our paths
665
	if (!file_exists($g['varetc_path']."/openvpn") ||
666
		!file_exists($g['varetc_path']."/openvpn-csc"))
667
		return;
668
669 34bc1324 Matthew Grooms
	if (!is_array($config['openvpn']))
670
		$config['openvpn'] = array();
671
672 15b414e6 Matthew Grooms
/*
673 34bc1324 Matthew Grooms
	if (!$config['openvpn']['dh-parameters']) {
674
		echo "Configuring OpenVPN Parameters ...\n";
675 035e4289 Matthew Grooms
		$dh_parameters = openvpn_create_dhparams(1024);
676 34bc1324 Matthew Grooms
		$dh_parameters = base64_encode($dh_parameters);
677
		$config['openvpn']['dh-parameters'] = $dh_parameters;
678 c67dd94e Bill Marquette
		write_config("OpenVPN DH parameters");
679 34bc1324 Matthew Grooms
	}
680
681
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
682
	if (!file_exists($path_ovdh)) {
683
		$dh_parameters = $config['openvpn']['dh-parameters'];
684
		$dh_parameters = base64_decode($dh_parameters);
685
		file_put_contents($path_ovdh, $dh_parameters);
686
	}
687 15b414e6 Matthew Grooms
*/
688 34bc1324 Matthew Grooms
689 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-server'])) {
690
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
691
			if (!empty($interface) && $interface != $settings['interface'])
692
				continue;
693 dc408939 Matthew Grooms
			openvpn_resync('server', $settings);
694 c7f60193 Ermal
		}
695
	}
696 5b237745 Scott Ullrich
697 c7f60193 Ermal
	if (is_array($config['openvpn']['openvpn-client'])) {
698
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
699
			if (!empty($interface) && $interface != $settings['interface'])
700
				continue;
701 dc408939 Matthew Grooms
			openvpn_resync('client', $settings);
702 c7f60193 Ermal
		}
703
	}
704 afb07cf1 Scott Ullrich
705 d799787e Matthew Grooms
	if (is_array($config['openvpn']['openvpn-csc']))
706 dc408939 Matthew Grooms
		foreach ($config['openvpn']['openvpn-csc'] as & $settings)
707
			openvpn_resync_csc($settings);
708 afb07cf1 Scott Ullrich
709 5b237745 Scott Ullrich
}
710 702a4702 Scott Ullrich
711 53663f57 jim-p
function openvpn_get_active_servers() {
712
	$servers = array();
713
	global $config;
714
	if (is_array($config['openvpn']['openvpn-server'])) {
715
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
716
	
717
			$prot = $settings['protocol'];
718
			$port = $settings['local_port'];
719
	
720
			$server = array();
721
			$server['port'] = $settings['local_port'];
722
			if ($settings['description'])
723
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
724
			else
725
				$server['name'] = "Server {$prot}:{$port}";
726
			$server['conns'] = array();
727
	
728
			$tcpsrv = "tcp://127.0.0.1:{$port}";
729
			$errval;
730
			$errstr;
731
	
732
			/* open a tcp connection to the management port of each server */
733
			$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
734
			if ($fp) {
735
	
736
				/* send our status request */
737
				fputs($fp, "status 2\n");
738
	
739
				/* recv all response lines */
740
				while (!feof($fp)) {
741
	
742
					/* read the next line */
743
					$line = fgets($fp, 1024);
744
	
745
					/* parse header list line */
746
					if (strstr($line, "HEADER"))
747
						continue;
748
	
749
					/* parse end of output line */
750
					if (strstr($line, "END"))
751
						break;
752
	
753
					/* parse client list line */
754
					if (strstr($line, "CLIENT_LIST")) {
755
						$list = explode(",", $line);
756
						$conn = array();
757
						$conn['common_name'] = $list[1];
758
						$conn['remote_host'] = $list[2];
759
						$conn['virtual_addr'] = $list[3];
760
						$conn['bytes_recv'] = $list[4];
761
						$conn['bytes_sent'] = $list[5];
762
						$conn['connect_time'] = $list[6];
763
						$server['conns'][] = $conn;
764
					}
765
				}
766
	
767
				/* cleanup */
768
				fclose($fp);
769
			} else {
770
				$conn = array();
771
				$conn['common_name'] = "[error]";
772
				$conn['remote_host'] = "Management Daemon Unreachable";
773
				$conn['virtual_addr'] = "";
774
				$conn['bytes_recv'] = 0;
775
				$conn['bytes_sent'] = 0;
776
				$conn['connect_time'] = 0;
777
				$server['conns'][] = $conn;
778
			}
779
	
780
			$servers[] = $server;
781
		}
782
	}
783
	return $servers;
784
}
785
786
function openvpn_get_active_clients() {
787
	$clients = array();
788
	global $config;
789
	if (is_array($config['openvpn']['openvpn-client'])) {
790
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
791
	
792
			$prot = $settings['protocol'];
793
			$port = $settings['local_port'];
794
	
795
			$client = array();
796
			$client['port'] = $settings['local_port'];
797
			if ($settings['description'])
798
				$client['name'] = "{$settings['description']} {$prot}:{$port}";
799
			else
800
				$client['name'] = "Client {$prot}:{$port}";
801
	
802
			$tcpcli = "tcp://127.0.0.1:{$port}";
803
			$errval;
804
			$errstr;
805
	
806
			$client['status']="down";
807
	
808
			/* open a tcp connection to the management port of each cli */
809
			$fp = @stream_socket_client($tcpcli, $errval, $errstr, 1);
810
			if ($fp) {
811
	
812
				/* send our status request */
813
				fputs($fp, "state 1\n");
814
	
815
				/* recv all response lines */
816
				while (!feof($fp)) {
817
					/* read the next line */
818
					$line = fgets($fp, 1024);
819
	
820
					/* Get the client state */
821
					if (strstr($line,"CONNECTED")) {
822
						$client['status']="up";
823
						$list = explode(",", $line);
824
	
825
						$client['connect_time']  = date("D M j G:i:s Y", $list[0]);
826
						$client['virtual_addr']  = $list[3];
827
						$client['remote_host'] = $list[4];
828
					}
829
					/* parse end of output line */
830
					if (strstr($line, "END"))
831
						break;
832
				}
833
	
834
				/* If up, get read/write stats */
835
				if (strcmp($client['status'], "up") == 0) {
836
					fputs($fp, "status 2\n");
837
					/* recv all response lines */
838
					while (!feof($fp)) {
839
						/* read the next line */
840
						$line = fgets($fp, 1024);
841
	
842
						if (strstr($line,"TCP/UDP read bytes")) {
843
							$list = explode(",", $line);
844
							$client['bytes_recv'] = $list[1];
845
						}
846
	
847
						if (strstr($line,"TCP/UDP write bytes")) {
848
							$list = explode(",", $line);
849
							$client['bytes_sent'] = $list[1];
850
						}
851
	
852
						/* parse end of output line */
853
						if (strstr($line, "END"))
854
							break;
855
					}
856
				}
857
	
858
				fclose($fp);
859
	
860
			} else {
861
				$DisplayNote=true;
862
				$client['remote_host'] = "No Management Daemon";
863
				$client['virtual_addr'] = "See Note Below";
864
				$client['bytes_recv'] = 0;
865
				$client['bytes_sent'] = 0;
866
				$client['connect_time'] = 0;
867
			}
868
	
869
			$clients[] = $client;
870
		}
871
	}
872
	return $clients;
873
}
874 8874c692 Ermal Luçi
?>