diff options
-rw-r--r-- | etc/inc/openvpn.inc | 482 | ||||
-rwxr-xr-x | usr/local/www/vpn_openvpn_cli.php | 68 | ||||
-rwxr-xr-x | usr/local/www/vpn_openvpn_cli_edit.php | 106 |
3 files changed, 437 insertions, 219 deletions
diff --git a/etc/inc/openvpn.inc b/etc/inc/openvpn.inc index 966c948..ce3dcf8 100644 --- a/etc/inc/openvpn.inc +++ b/etc/inc/openvpn.inc @@ -1,5 +1,4 @@ <?php -/* $Id$ */ /* openvpn.inc @@ -33,10 +32,10 @@ require_once("globals.inc"); require_once("config.inc"); require_once("functions.inc"); -function ovpn_configure() { +function ovpn_configure($reconfigure) { global $config; if (is_array($config['ovpn']['server'])) - ovpn_config_server(); + ovpn_config_server($reconfigure); if (is_array($config['ovpn']['client'])) ovpn_config_client(); return; @@ -80,91 +79,165 @@ function ovpn_unlink_tap() { } /*****************************/ -/* Server-related functions */ +/* Server related functions */ +/*****************************/ -/* Configure the server */ -function ovpn_config_server() { - global $config, $g; - - if (isset($config['ovpn']['server']['enable'])) { - - if ($g['booting']) - echo "Configuring OpenVPN... "; - - /* kill any running openvpn daemon */ - killbypid($g['varrun_path']."/ovpn_srv.pid"); - - /* Remove old certs & keys */ - unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_dh.pem"); - - /* Copy the TLS-Server certs & keys to disk */ - $fd = @fopen("{$g['vardb_path']}/ovpn_ca_cert.pem", "w"); - if ($fd) { - fwrite($fd, base64_decode($config['ovpn']['server']['ca_cert'])."\n"); - fclose($fd); - } - $fd = @fopen("{$g['vardb_path']}/ovpn_srv_cert.pem", "w"); - if ($fd) { - fwrite($fd, base64_decode($config['ovpn']['server']['srv_cert'])."\n"); - fclose($fd); - } - $fd = @fopen("{$g['vardb_path']}/ovpn_srv_key.pem", "w"); - if ($fd) { - fwrite($fd, base64_decode($config['ovpn']['server']['srv_key'])."\n"); - fclose($fd); +function getnxt_server_if($type) { + /* find the first available device of type $type */ + global $config; + $a_server = $config['ovpn']['server']['tunnel']; + $max = ($type == 'tun') ? 9 : 4; + for ($i = 0; $i < $max ; $i++) { + $hit = false; + foreach ($a_server as $server) { + if ($server['tun_iface'] == $type . $i) { + $hit = true; + break; + } } - $fd = @fopen("{$g['vardb_path']}/ovpn_dh.pem", "w"); - if ($fd) { - fwrite($fd, base64_decode($config['ovpn']['server']['dh_param'])."\n"); - fclose($fd); + if (!$hit) + return $type . $i; + } + return false; +} + +function getnxt_server_port() { + /* Get first unused port */ + global $config; + $a_server = $config['ovpn']['server']['tunnel']; + $port = 1194; + while (true) { + $hit = false; + foreach ($a_server as $server) { + if ($server['port'] == $port) { + $hit = true; + break; + } } - - /* Start the openvpn daemon */ - mwexec("/usr/local/sbin/openvpn " . ovpn_srv_config_generate()); - - if ($g['booting']) - /* Send the boot message */ - echo "done.\n"; + if (!$hit) + if (!ovpn_port_inuse_client($port)) + return $port; + $port++; } - else { - if (!$g['booting']){ - /* stop any processes, unload the tap module */ + return false; /* should never get here */ +} + +/* Configure the server */ +function ovpn_config_server($reconfigure) { + global $config, $g; + + foreach ($config['ovpn']['server']['tunnel'] as $id => $server) { + /* get tunnel interface */ + $tun = $server['tun_iface']; + + /* kill any running openvpn daemon */ + killbypid($g['varrun_path']."/ovpn_srv_{$tun}.pid"); + + if (isset($server['enable'])) { + + if ($g['booting']) + echo "Starting OpenVPN server $id... "; + + /* send SIGUSR1 to running openvpn daemon */ + if ( $reconfigure == "true" && isset($server['dynip'])) { + sigkillbypid($g['varrun_path']."/ovpn_srv_{$tun}.pid", "SIGUSR1"); + continue; + } + /* Remove old certs & keys */ - unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_dh.pem"); - killbypid("{$g['varrun_path']}/ovpn_srv.pid"); - if ($config['ovpn']['server']['tun_iface'] == 'tap0') - ovpn_unlink_tap(); + unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_dh_{$tun}.pem"); + + /* Copy the TLS-Server certs & keys to disk */ + $fd = fopen("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem", "w"); + if ($fd) { + fwrite($fd, base64_decode($server['ca_cert'])."\n"); + fclose($fd); + } + $fd = fopen("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem", "w"); + if ($fd) { + fwrite($fd, base64_decode($server['srv_cert'])."\n"); + fclose($fd); + } + touch ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem"); + chmod ("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", 0600); + $fd = fopen("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem", "w"); + if ($fd) { + fwrite($fd, base64_decode($server['srv_key'])."\n"); + fclose($fd); + } + $fd = fopen("{$g['vardb_path']}/ovpn_dh_{$tun}.pem", "w"); + if ($fd) { + fwrite($fd, base64_decode($server['dh_param'])."\n"); + fclose($fd); + } + + /* Start the openvpn daemon */ + mwexec("/usr/local/sbin/openvpn " . ovpn_srv_config_generate($id)); + + if ($g['booting']) + /* Send the boot message */ + echo "done\n"; + } + else { + if (!$g['booting']){ + /* stop any processes, unload the tap module */ + /* Remove old certs & keys */ + ovpn_server_kill($tun); + + if ($server['type'] == "tap") + ovpn_unlink_tap(); + } } } return 0; } +/* Kill off a running server process */ +function ovpn_server_kill($tun) { + global $g; + + killbypid("{$g['varrun_path']}/ovpn_srv_{$tun}.pid"); + + /* Remove old certs & keys */ + unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_srv_key_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_dh_{$tun}.pem"); + + return 0; +} + /* Generate the config for a OpenVPN server */ -function ovpn_srv_config_generate() { +function ovpn_srv_config_generate($id) { global $config, $g; - $server = $config['ovpn']['server']; - + $server = $config['ovpn']['server']['tunnel'][$id]; + + /* get tunnel interface */ + $tun = $server['tun_iface']; + /* First the generic stuff: - We are a server - We are a TLS Server (for authentication) - We will run without privilege */ - $ovpn_config = "--daemon --user nobody --group nobody --verb {$server['verb']} "; + $ovpn_config = "--daemon --user nobody --group nobody --verb {$server['verb']} --persist-tun --persist-key "; /* pid file */ - $ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_srv.pid "; + $ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_srv_{$tun}.pid "; /* interface */ $ovpn_config .= "--dev {$server['tun_iface']} "; /* port */ $ovpn_config .= "--port {$server['port']} "; + + /* Set protocol being used (p = udp (default), tcp-server) + if ($server['proto'] == 'tcp') { + $ovpn_config .= "--proto tcp-server"; + } /* Interface binding - 1 or all */ if ($server['bind_iface'] != 'all') { @@ -172,9 +245,12 @@ function ovpn_srv_config_generate() { $ovpn_config .= "--local $ipaddr "; else return "Interface bridged"; - } - + + /* are we using dynamic ip addresses? */ + if (isset($server['dynip'])) + $ovpn_config .= "--persist-remote-ip "; + /* Client to client routing (off by default) */ if (isset($server['cli2cli'])) $ovpn_config .= "--client-to-client "; @@ -187,10 +263,10 @@ function ovpn_srv_config_generate() { $ovpn_config .= "--server {$server['ipblock']} {$mask} "; /* TLS-Server params */ - $ovpn_config .= "--ca {$g['vardb_path']}/ovpn_ca_cert.pem "; - $ovpn_config .= "--cert {$g['vardb_path']}/ovpn_srv_cert.pem "; - $ovpn_config .= "--key {$g['vardb_path']}/ovpn_srv_key.pem "; - $ovpn_config .= "--dh {$g['vardb_path']}/ovpn_dh.pem "; + $ovpn_config .= "--ca {$g['vardb_path']}/ovpn_ca_cert_{$tun}.pem "; + $ovpn_config .= "--cert {$g['vardb_path']}/ovpn_srv_cert_{$tun}.pem "; + $ovpn_config .= "--key {$g['vardb_path']}/ovpn_srv_key_{$tun}.pem "; + $ovpn_config .= "--dh {$g['vardb_path']}/ovpn_dh_{$tun}.pem "; /* Data channel encryption cipher*/ $ovpn_config .= "--cipher {$server['crypto']} "; @@ -202,7 +278,7 @@ function ovpn_srv_config_generate() { /* Client push - redirect gateway */ if (isset($server['psh_options']['redir'])){ if (isset($server['psh_options']['redir_loc'])) - $ovpn_config .= "--push \"redirect-gateway 'local'\" "; + $ovpn_config .= "--push \"redirect-gateway local\" "; else $ovpn_config .= "--push \"redirect-gateway\" "; } @@ -235,12 +311,7 @@ function ovpn_srv_config_generate() { $ovpn_config .= "--inactive {$server['psh_options']['pingexit']} "; $ovpn_config .= "--push \"inactive {$server['psh_options']['inact']}\" "; } - - /* Set protocol being used (TCP or UDP) */ - if ($server['psh_options']['proto'] == 'TCP') { - $ovpn_config .= "--proto tcp-server "; - } - + //trigger_error("OVPN: $ovpn_config", E_USER_NOTICE); return $ovpn_config; } @@ -249,69 +320,166 @@ function ovpn_srv_config_generate() { function ovpn_server_iface(){ global $config, $g; - $i = 1; - while (true) { - $ifname = 'opt' . $i; - if (is_array($config['interfaces'][$ifname])) { - if ((isset($config['interfaces'][$ifname]['ovpn'])) - && ($config['interfaces'][$ifname]['ovpn'] == 'server')) - /* Already an interface defined - overwrite */ - break; + foreach ($config['ovpn']['server']['tunnel'] as $id => $server) { + if (isset($server['enable'])) { + + /* get tunnel interface */ + $tun = $server['tun_iface']; + + $i = 1; + while (true) { + $ifname = 'opt' . $i; + if (is_array($config['interfaces'][$ifname])) { + if ((isset($config['interfaces'][$ifname]['ovpn'])) + && ($config['interfaces'][$ifname]['ovpn'] == "server_{$tun}")) + /* Already an interface defined - overwrite */ + break; + } + else { + /* No existing entry, this is first unused */ + $config['interfaces'][$ifname] = array(); + break; + } + $i++; + } + if (isset($server['descr'])) + $config['interfaces'][$ifname]['descr'] = $server['descr']; + else + $config['interfaces'][$ifname]['descr'] = "OVPN server-{$tun}"; + $config['interfaces'][$ifname]['if'] = $server['tun_iface']; + $config['interfaces'][$ifname]['ipaddr'] = long2ip( ip2long($server['ipblock']) + 1); + $config['interfaces'][$ifname]['subnet'] = $server['prefix']; + $config['interfaces'][$ifname]['enable'] = isset($server['enable']) ? true : false; + $config['interfaces'][$ifname]['ovpn'] = "server_{$tun}"; + + write_config(); } - else { - /* No existing entry, this is first unused */ - $config['interfaces'][$ifname] = array(); + } + return "OpenVPN server interface defined"; +} + +/* Delete a server interface definition */ +function ovpn_server_iface_del($tun) { + global $config; + + for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) { + $ifname = 'opt' . $i; + if ((isset($config['interfaces'][$ifname]['ovpn'])) + && ($config['interfaces'][$ifname]['if'] == "$tun")) { + unset($config['interfaces'][$ifname]); break; } + } + + + /* shift down other OPTn interfaces to get rid of holes */ + $i++; + + /* look at the following OPTn ports */ + while (is_array($config['interfaces']['opt' . $i])) { + $config['interfaces']['opt' . ($i - 1)] = + $config['interfaces']['opt' . $i]; + + unset($config['interfaces']['opt' . $i]); $i++; } - $config['interfaces'][$ifname]['descr'] = "OVPN server"; - $config['interfaces'][$ifname]['if'] = $config['ovpn']['server']['tun_iface']; - $config['interfaces'][$ifname]['ipaddr'] = long2ip( ip2long($config['ovpn']['server']['ipblock']) + 1); - $config['interfaces'][$ifname]['subnet'] = $config['ovpn']['server']['prefix']; - $config['interfaces'][$ifname]['enable'] = isset($config['ovpn']['server']['enable']) ? true : false; - $config['interfaces'][$ifname]['ovpn'] = 'server'; - - write_config(); - - return "OpenVPN server interface defined"; } -/********************************************************/ + +/****************************/ /* Client related functions */ +/****************************/ + +function getnxt_client_if($type) { + /* find the first available device of type $type */ + global $config; + $a_client = $config['ovpn']['client']['tunnel']; + $max = ($type == 'tun') ? 9 : 4; + for ($i = $max; $i < ($max+$max) ; $i++) { + $hit = false; + foreach ($a_client as $client) { + if ($client['if'] == $type . $i) { + $hit = true; + break; + } + } + if (!$hit) + return $type . $i; + } + return false; +} + +function getnxt_client_port() { + /* Get first unused port */ + global $config; + $a_client = $config['ovpn']['client']['tunnel']; + $port = 1194; + while (true) { + $hit = false; + foreach ($a_client as $client) { + if ($client['port'] == $port) { + $hit = true; + break; + } + } + if (!$hit) + if (!ovpn_port_inuse_server($port)) + return $port; + $port++; + } + return false; /* should never get here */ +} + +/* Port in use */ +function ovpn_port_inuse_client($port){ + global $config; + $a_client = $config['ovpn']['client']['tunnel']; + foreach ($a_client as $client) { + if ($client['port'] == $port) { + return true; + } + } + return false; +} + function ovpn_config_client() { /* Boot time configuration */ global $config, $g; foreach ($config['ovpn']['client']['tunnel'] as $id => $client) { + + /* get tunnel interface */ + $tun = $client['if']; + + /* kill any running openvpn daemon */ + killbypid($g['varrun_path']."/ovpn_cli_{$tun}.pid"); + if (isset($client['enable'])) { if ($g['booting']) echo "Starting OpenVPN client $id... "; - /* kill any running openvpn daemon */ - killbypid("{$g['varrun_path']}/ovpn_client{$id}.pid"); - /* Remove old certs & keys */ - unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$id}.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$id}.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$id}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem"); /* Copy the TLS-Client certs & keys to disk */ - /*$fd = @fopen("{$g['vardb_path']}/ovpn_ca_cert_{$id}.pem", "w");*/ - $fd = fopen("{$g['vardb_path']}/ovpn_ca_cert_{$id}.pem", "w"); + $fd = fopen("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem", "w"); if ($fd) { fwrite($fd, base64_decode($client['ca_cert'])."\n"); fclose($fd); } else trigger_error("OVPN: No open for CA", E_USER_NOTICE); - $fd = fopen($g['vardb_path']."/ovpn_cli_cert_".$id.".pem", "w"); + $fd = fopen("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem", "w"); if ($fd) { fwrite($fd, base64_decode($client['cli_cert'])."\n"); fclose($fd); } - $fd = fopen($g['vardb_path']."/ovpn_cli_key_".$id.".pem", "w"); + touch ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem"); + chmod ("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", 0600); + $fd = fopen("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem", "w"); if ($fd) { fwrite($fd, base64_decode($client['cli_key'])."\n"); fclose($fd); @@ -322,16 +490,14 @@ function ovpn_config_client() { if ($g['booting']) /* Send the boot message */ - echo "done.\n"; + echo "done\n"; } else { if (!$g['booting']){ /* stop any processes, unload the tap module */ /* Remove old certs & keys */ - unlink_if_exists("{$g['vardb_path']}/ovpn_ca_cert_{$id}.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$id}.pem"); - unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$id}.pem"); - killbypid("{$g['varrun_path']}/ovpn_client{$id}.pid"); + ovpn_client_kill($tun); + if ($client['type'] == "tap") ovpn_unlink_tap(); } @@ -342,44 +508,57 @@ function ovpn_config_client() { } /* Kill off a running client process */ -function ovpn_client_kill($id) { +function ovpn_client_kill($tun) { global $g; - killbypid("{$g['varrun_path']}/ovpn_client{$id}.pid"); + killbypid("{$g['varrun_path']}/ovpn_cli_{$tun}.pid"); + + /* Remove old certs & keys */ + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem"); + unlink_if_exists("{$g['vardb_path']}/ovpn_cli_key_{$tun}.pem"); + return 0; } +/* Generate the config for a OpenVPN client */ function ovpn_cli_config_generate($id) { /* configure the named client */ global $config, $g; - $client = $config['ovpn']['client']['tunnel']; + $client = $config['ovpn']['client']['tunnel'][$id]; + + /* get tunnel interface */ + $tun = $client['if']; /* Client support in 2.0 is very simple */ $ovpn_config = "--client --daemon --verb 1 "; /* pid file */ - $ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_client{$id}.pid "; + $ovpn_config .= "--writepid {$g['varrun_path']}/ovpn_cli_{$tun}.pid "; /* interface */ - $ovpn_config .= "--dev {$client[$id]['if']} "; + $ovpn_config .= "--dev {$client['if']} "; /* protocol */ - $ovpn_config .= "--proto {$client[$id]['proto']} "; + /* Set protocol being used (p = udp (default), tcp-client) + if ($client['proto'] == 'tcp') { + $ovpn_config .= "--proto tcp-client"; + } /* port */ - $ovpn_config .= "--lport {$client[$id]['cport']} "; + $ovpn_config .= "--lport {$client['port']} "; /* server location */ - $ovpn_config .= "--remote {$client[$id]['saddr']} {$client[$id]['sport']} "; + $ovpn_config .= "--remote {$client['saddr']} {$client['sport']} "; /* TLS-Server params */ - $ovpn_config .= "--ca {$g['vardb_path']}/ovpn_ca_cert_{$id}.pem "; - $ovpn_config .= "--cert {$g['vardb_path']}/ovpn_cli_cert_{$id}.pem "; - $ovpn_config .= "--key {$g['vardb_path']}/ovpn_cli_key_{$id}.pem "; + $ovpn_config .= "--ca {$g['vardb_path']}/ovpn_cli_ca_cert_{$tun}.pem "; + $ovpn_config .= "--cert {$g['vardb_path']}/ovpn_cli_cert_{$tun}.pem "; + $ovpn_config .= "--key {$g['vardb_path']}/ovpn_cli_key_{$tun}.pem "; /* Data channel encryption cipher*/ - $ovpn_config .= "--cipher {$client[$id]['crypto']} "; + $ovpn_config .= "--cipher {$client['crypto']} "; //trigger_error("OVPN: $ovpn_config", E_USER_NOTICE); return $ovpn_config; @@ -391,12 +570,16 @@ function ovpn_client_iface(){ foreach ($config['ovpn']['client']['tunnel'] as $id => $client) { if (isset($client['enable'])) { + + /* get tunnel interface */ + $tun = $client['if']; + $i = 1; while (true) { $ifname = 'opt' . $i; if (is_array($config['interfaces'][$ifname])) { if ((isset($config['interfaces'][$ifname]['ovpn'])) - && ($config['interfaces'][$ifname]['ovpn'] == "client{$id}")) + && ($config['interfaces'][$ifname]['ovpn'] == "client_{$tun}")) /* Already an interface defined - overwrite */ break; } @@ -410,12 +593,12 @@ function ovpn_client_iface(){ if (isset($client['descr'])) $config['interfaces'][$ifname]['descr'] = $client['descr']; else - $config['interfaces'][$ifname]['descr'] = "OVPN client-{$id}"; + $config['interfaces'][$ifname]['descr'] = "OVPN client-{$tun}"; $config['interfaces'][$ifname]['if'] = $client['if']; $config['interfaces'][$ifname]['ipaddr'] = "0.0.0.0"; $config['interfaces'][$ifname]['subnet'] = "0"; $config['interfaces'][$ifname]['enable'] = isset($client['enable']) ? true : false; - $config['interfaces'][$ifname]['ovpn'] = "client{$id}"; + $config['interfaces'][$ifname]['ovpn'] = "client_{$tun}"; write_config(); } } @@ -423,20 +606,33 @@ function ovpn_client_iface(){ } /* Delete a client interface definition */ -function ovpn_client_iface_del($id) { +function ovpn_client_iface_del($tun) { global $config; - - $i = 1; - while (true) { + + for ($i = 1; is_array($config['interfaces']['opt' . $i]); $i++) { $ifname = 'opt' . $i; - if (is_array($config['interfaces'][$ifname])) { - if ((isset($config['interfaces'][$ifname]['ovpn'])) - && ($config['interfaces'][$ifname]['ovpn'] == "client{$id}")) - unset($config['interfaces'][$ifname]); + if ((isset($config['interfaces'][$ifname]['ovpn'])) + && ($config['interfaces'][$ifname]['if'] == "$tun")) { + unset($config['interfaces'][$ifname]); + break; } } + + + /* shift down other OPTn interfaces to get rid of holes */ + $i++; + + /* look at the following OPTn ports */ + while (is_array($config['interfaces']['opt' . $i])) { + $config['interfaces']['opt' . ($i - 1)] = + $config['interfaces']['opt' . $i]; + + unset($config['interfaces']['opt' . $i]); + $i++; + } } + /******************/ /* Misc functions */ @@ -454,6 +650,18 @@ function ovpn_calc_mask($prefix){ return long2ip(ip2long("255.255.255.255") - (pow( 2, (32 - $prefix)) - 1)); } +/* Port in use */ +function ovpn_port_inuse_server($port){ + global $config; + $a_server = $config['ovpn']['server']['tunnel']; + foreach ($a_server as $server) { + if ($server['port'] == $port) { + return true; + } + } + return false; +} + /* Read in a file from the $_FILES array */ function ovpn_get_file($file){ global $g; @@ -539,7 +747,7 @@ function ovpn_lock() { $n = 0; while ($n < 10) { /* open the lock file in append mode to avoid race condition */ - if ($fd = @fopen($lockfile, "x")) { + if ($fd = fopen($lockfile, "x")) { /* succeeded */ fclose($fd); return; diff --git a/usr/local/www/vpn_openvpn_cli.php b/usr/local/www/vpn_openvpn_cli.php index c574483..b9d88f1 100755 --- a/usr/local/www/vpn_openvpn_cli.php +++ b/usr/local/www/vpn_openvpn_cli.php @@ -28,6 +28,7 @@ POSSIBILITY OF SUCH DAMAGE. */ +$pgtitle = array("VPN", "OpenVPN"); require("guiconfig.inc"); require_once("openvpn.inc"); @@ -38,37 +39,48 @@ if (!is_array($config['ovpn']['client'])){ $config['ovpn']['client']['tunnel'] = array(); } +$id = $_GET['id']; +if (isset($_POST['id'])) + $id = $_POST['id']; + $ovpncli =& $config['ovpn']['client']['tunnel']; if ($_POST['apply']) { $retval = 0; - ovpn_lock(); - $retval = ovpn_config_client(); - ovpn_unlock(); + if (file_exists($d_sysrebootreqd_path)) { + /* Rewrite interface definitions */ + $retval = ovpn_client_iface(); + } + else{ + ovpn_lock(); + $retval = ovpn_config_client(); + ovpn_unlock(); + } if (file_exists($d_ovpnclidirty_path)) unlink($d_ovpnclidirty_path); $savemsg = get_std_save_message($retval); } if ($_GET['act'] == "del") { - if ($ovpncli[$_GET['id']]) { - unset($ovpncli[$_GET['id']]); + if ($ovpncli[$id]) { + $ovpnent = $ovpncli[$id]; + unset($ovpncli[$id]); + + /* Kill running processes */ + /* Remove old certs & keys */ + ovpn_client_kill($ovpnent['if']); + + /* Remove interface from list of optional interfaces */ + ovpn_client_iface_del($ovpnent['if']); + write_config(); - ovpn_client_kill($_GET['id']); - touch($d_ovpnclidirty_path); + touch($d_sysrebootreqd_path); header("Location: vpn_openvpn_cli.php"); exit; } } - -$pgtitle = "VPN: OpenVPN: Client"; -include("head.inc"); - ?> - -<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<p class="pgtitle"><?=$pgtitle?></p> <?php if ($input_errors) print_input_errors($input_errors); ?> <?php if (file_exists($d_sysrebootreqd_path) && !file_exists($d_ovpnclidirty_path)) print_info_box(get_std_save_message(0)); ?> <form action="vpn_openvpn_cli.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> @@ -80,7 +92,7 @@ include("head.inc"); <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <ul id="tabnav"> - <li class="tabinact1"><a href="vpn_openvpn.php">Server</a></li> + <li class="tabinact1"><a href="vpn_openvpn_srv.php">Server</a></li> <li class="tabact">Client</li> </ul> </td></tr> @@ -93,9 +105,11 @@ include("head.inc"); <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="10%" class="listhdrr">Interface</td> - <td width="30%" class="listhdrr">Server address</td> - <td width="10%" class="listhdrr" align="middle">Version</td> - <td width="40%" class="listhdr">Description</td> + <td width="10%" class="listhdrr">Protocol</td> + <td width="15%" class="listhdrr">Socket</td> + <td width="15%" class="listhdrr">Server address</td> + <td width="5%" class="listhdrr" align="middle">Version</td> + <td width="35%" class="listhdr">Description</td> <td width="10%" class="list"></td> </tr> @@ -110,7 +124,13 @@ include("head.inc"); <tr> <td class="listlr"><?=$spans;?> - <?= $client['if'].":".$client['cport'];?> + <?= $client['if'];?> + <?=$spane;?></td> + <td class="listr"><?=$spans;?> + <?= strtoupper($client['proto']);?> + <?=$spane;?></td> + <td class="listr"><?=$spans;?> + <?= "0.0.0.0:" . $client['port'];?> <?=$spane;?></td> <td class="listr"><?=$spans;?> <?= $client['saddr'].":".$client['sport'];?> @@ -119,15 +139,15 @@ include("head.inc"); <?= $client['ver'];?> <?=$spane;?></td> <td class="listbg"><?=$spans;?> - <?= $client['descr'];?> + <?= htmlspecialchars($client['descr']);?> <?=$spane;?></td> - <td valign="middle" nowrap class="list"> <a href="vpn_openvpn_cli_edit.php?id=<?=$i;?>"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="edit client configuration" width="17" height="17" border="0"></a> - <a href="vpn_openvpn_cli.php?act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this client configuration?')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="delete client configuration" width="17" height="17" border="0"></a></td> + <td valign="middle" nowrap class="list"> <a href="vpn_openvpn_cli_edit.php?id=<?=$i;?>"><img src="e.gif" title="edit client configuration" width="17" height="17" border="0"></a> + <a href="vpn_openvpn_cli.php?act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this client configuration?')"><img src="x.gif" title="delete client configuration" width="17" height="17" border="0"></a></td> </tr> <?php $i++; endforeach; ?> <tr> - <td class="list" colspan="4"> </td> - <td class="list"> <a href="vpn_openvpn_cli_edit.php"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="add client configuration" width="17" height="17" border="0"></a></td> + <td class="list" colspan="6"> </td> + <td class="list"> <a href="vpn_openvpn_cli_edit.php"><img src="plus.gif" title="add client configuration" width="17" height="17" border="0"></a></td> </tr> </table> </td> diff --git a/usr/local/www/vpn_openvpn_cli_edit.php b/usr/local/www/vpn_openvpn_cli_edit.php index 8221e2a..c4136e4 100755 --- a/usr/local/www/vpn_openvpn_cli_edit.php +++ b/usr/local/www/vpn_openvpn_cli_edit.php @@ -28,6 +28,7 @@ POSSIBILITY OF SUCH DAMAGE. */ +$pgtitle = array("VPN", "OpenVPN", "Edit client"); require("guiconfig.inc"); require_once("openvpn.inc"); @@ -38,47 +39,7 @@ if (!is_array($config['ovpn']['client'])){ $config['ovpn']['client']['tunnel'] = array(); } -function getnxt_if($type) { - /* find the first available device of type $type */ - global $config; - $a_client = $config['ovpn']['client']['tunnel']; - $max = ($type == 'tun') ? 17 : 4; - for ($i = 1; $i < $max ; $i++) { - $hit = false; - foreach ($a_client as $client) { - if ($client['iface'] == $type . $i) { - $hit = true; - break; - } - } - if (!$hit) - return $type . $i; - } - return false; -} - -function getnxt_port() { - /* Get first unused port */ - global $config; - $a_client = $config['ovpn']['client']['tunnel']; - $port = 5001; - while (true) { - $hit = false; - foreach ($a_client as $client) { - if ($client['cport'] == $port) { - $hit = true; - break; - } - } - if (!$hit) - return $port; - $port++; - } - return false; /* should never get here */ -} - - $ovpncli =& $config['ovpn']['client']['tunnel']; $id = $_GET['id']; @@ -95,7 +56,7 @@ else { $pconfig = array(); $pconfig['type'] = 'tun'; $pconfig['proto'] = 'udp'; - $pconfig['sport'] = '5000'; + $pconfig['sport'] = '1194'; $pconfig['ver'] = '2'; $pconfig['crypto'] = 'BF-CBC'; $pconfig['pull'] = true; @@ -103,8 +64,26 @@ else { } if (isset($_POST['pull'])) { + + $pconfig = $_POST; + + $pconfig['ca_cert'] = base64_encode($pconfig['ca_cert']); + $pconfig['cli_cert'] = base64_encode($pconfig['cli_cert']); + $pconfig['cli_key'] = base64_encode($pconfig['cli_key']); + /* Called from form */ unset($input_errors); + + /* input validation */ + $reqdfields = explode(" ", "type saddr sport"); + $reqdfieldsn = explode(",", "Tunnel type,Address,Port"); + + do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + /* valid Port */ + if (($_POST['sport'] && !is_port($_POST['sport']))) + $input_errors[] = "The server's port must be an integer between 1 and 65535 (default 1194)."; + if (is_null($_POST['ca_cert'])) $input_errors[] = "You must provide a CA certificate file"; elseif (!strstr($_POST['ca_cert'], "BEGIN CERTIFICATE") || !strstr($_POST['ca_cert'], "END CERTIFICATE")) @@ -124,20 +103,33 @@ if (isset($_POST['pull'])) { if (isset($id)) { /* Editing an existing entry */ $ovpnent = $ovpncli[$id]; + + if ( $ovpncli[$id]['sport'] != $_POST['sport'] || + $ovpncli[$id]['proto'] != $_POST['proto'] ) { + + /* some entries changed */ + for ($i = 0; isset($config['ovpn']['client']['tunnel'][$i]); $i++) { + $current = &$config['ovpn']['client']['tunnel'][$i]; + + if ($current['sport'] == $_POST['sport']) + if ($current['proto'] == $_POST['proto']) + $input_errors[] = "You already have this combination for port and protocol settings. You can't use it twice"; + } + } + /* Test Server type hasn't changed */ if ($ovpnent['type'] != $_POST['type']) { - $nxt_if = getnxt_if($_POST['type']); + $nxt_if = getnxt_client_if($_POST['type']); if (!$nxt_if) $input_errors[] = "Run out of devices for a tunnel of type {$_POST['type']}"; else $ovpnent['if'] = $nxt_if; - + /* Need to reboot in order to create interfaces cleanly */ + touch($d_sysrebootreqd_path); } /* Has the enable/disable state changed? */ if (isset($ovpnent['enable']) && isset($_POST['disabled'])) { touch($d_ovpnclidirty_path); - ovpn_client_kill($id); - ovpn_client_iface_del($id); } if (!isset($ovpnent['enable']) && !isset($_POST['disabled'])) { touch($d_ovpnclidirty_path); @@ -146,22 +138,25 @@ if (isset($_POST['pull'])) { else { /* Creating a new entry */ $ovpnent = array(); - $nxt_if = getnxt_if($_POST['type']); + $nxt_if = getnxt_client_if($_POST['type']); if (!$nxt_if) $input_errors[] = "Run out of devices for a tunnel of type {$_POST['type']}"; else $ovpnent['if'] = $nxt_if; - $ovpnent['cport'] = getnxt_port(); + $ovpnent['port'] = getnxt_client_port(); + /* I think we have to reboot to have the interface created cleanly */ + touch($d_sysrebootreqd_path); } + $ovpnent['type'] = $_POST['type']; $ovpnent['proto'] = $_POST['proto']; $ovpnent['sport'] = $_POST['sport']; $ovpnent['ver'] = $_POST['ver']; $ovpnent['saddr'] = $_POST['saddr']; $ovpnent['descr'] = $_POST['descr']; - $ovpnent['ca_cert'] = base64_encode($_POST['ca_cert']); - $ovpnent['cli_cert'] = base64_encode($_POST['cli_cert']); - $ovpnent['cli_key'] = base64_encode($_POST['cli_key']); + $ovpnent['ca_cert'] = $pconfig['ca_cert']; + $ovpnent['cli_cert'] = $pconfig['cli_cert']; + $ovpnent['cli_key'] = $pconfig['cli_key']; $ovpnent['crypto'] = $_POST['crypto']; $ovpnent['pull'] = true; //This is a fixed config for this version $ovpnent['enable'] = isset($_POST['disabled']) ? false : true; @@ -176,22 +171,17 @@ if (isset($_POST['pull'])) { write_config(); touch($d_ovpnclidirty_path); + header("Location: vpn_openvpn_cli.php"); exit; } } -$pgtitle = "VPN: OpenVPN: Edit client"; -include("head.inc"); - ?> - -<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<p class="pgtitle"><?=$pgtitle?></p> <?php if ($input_errors) print_input_errors($input_errors); ?> + <form action="vpn_openvpn_cli_edit.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> - <?display_topbar()?> <table width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> <td width="22%" valign="top" class="vncellreq">Disabled</td> @@ -228,7 +218,7 @@ include("head.inc"); <td width="22%" valign="top" class="vncellreq">Port</td> <td width="78%" class="vtable"> <input name="sport" type="text" class="formfld" size="5" maxlength="5" value="<?=htmlspecialchars($pconfig['sport']);?>"><br> - Enter the server's port number (default is 5000).</td> + Enter the server's port number (default is 1194).</td> </tr> <tr> |