Update OpenVPNConnect to 1.1 (#47)

pull/51/head
Casey Erdmann 2018-10-28 19:36:42 -04:00 committed by Sebastian Kinne
parent 024854bb42
commit c7ae8dc93c
6 changed files with 166 additions and 28 deletions

View File

@ -20,35 +20,50 @@ class OpenVPNConnect extends Module{
case 'stopVPN': case 'stopVPN':
$this->stopVPN(); $this->stopVPN();
break; break;
case 'checkVPNStatus':
$this->checkVPNStatus();
break;
case 'initializeModule': case 'initializeModule':
$this->initializeModule(); $this->initializeModule();
break; break;
case 'handleDependencies': case 'handleDependencies':
$this->handleDependencies(); $this->handleDependencies();
break; break;
case 'handleDependenciesSDCard':
$this->handleDependenciesSDCard();
break;
case 'checkDependencies': case 'checkDependencies':
$this->checkDependencies(); $this->checkDependencies();
break; break;
case 'uploadFile': case 'uploadFile':
$this->uploadFile(); $this->uploadFile();
break;
} }
} }
// Checks the dependencies using the pineapple API functions // Checks the dependencies using the pineapple API functions
private function checkDependencies(){ private function checkDependencies(){
$installedFlag = false;
if($this->checkDependency('openvpn')){ if($this->checkDependency('openvpn')){
$installLabel = 'success'; $installLabel = 'success';
$installLabelText = 'Installed'; $installLabelText = 'Installed';
$installButtonWidth = "90px";
$installLabelSDText = "Installed (SD Card)";
$installedFlag = true;
}else{ }else{
$installLabel = 'danger'; $installLabel = 'danger';
$installLabelText = 'Not Installed'; $installLabelText = 'Not Installed (Local Storage)';
$installButtonWidth = "210px";
$installLabelSDText = "Not Installed (SD Card)";
} }
$this->response = array("success" => true, $this->response = array("success" => true,
"label" => $installLabel, "label" => $installLabel,
"text" => $installLabelText); "text" => $installLabelText,
"buttonWidth" => $installButtonWidth,
"textSD" => $installLabelSDText,
"installed" => $installedFlag);
} }
@ -87,27 +102,60 @@ class OpenVPNConnect extends Module{
} }
// Handles dependency installation and removal // Handles dependency installation and removal
private function handleDependencies(){ private function handleDependencies($sd){
if($this->checkDependency('openvpn')){ if($this->checkDependency('openvpn')){
exec('opkg remove openvpn-openssl'); $this->execBackground('opkg remove openvpn-openssl');
$messsage = "Dependencies should now be removed! Note: the vpn_config directory is NOT removed in this process. Please wait for the page to refresh..."; $messsage = "Dependencies should now be removed! Note: the vpn_config directory is NOT removed in this process. Please wait for the page to refresh...";
}else{ }else{
$this->installDependency('openvpn-openssl'); if($sd){
$messsage = "Depedencies should now be installed! Please wait for the page to refresh..."; $this->execBackground('opkg update');
$this->execBackground('opkg install openvpn-openssl --dest sd');
$messsage = "Depedencies should now be installed! (Installed to SD card) Please wait for the page to refresh...";
}else{
$this->installDependency('openvpn-openssl');
$messsage = "Depedencies should now be installed! (Installed to local storage) Please wait for the page to refresh...";
}
} }
$this->response = array("success" => true, $this->response = array("success" => true,
"content" => $messsage); "content" => $messsage,
"test" => $sd);
} }
// Builds the openvpn command string and calls it to star the VPN // Helper function to handle dependency installation and removal for sd card. Passes the SD flag to the real handleDependencies() function
private function handleDependenciesSDCard(){
$sd = true;
return handleDependencies($sd);
}
// Checks whether or not OpenVPN is currently running
private function checkVPNStatus(){
$result = exec("pgrep openvpn");
if($result){
$this->response = array("success" => true,
"content" => "VPN Running...");
return;
}
$this->response = array("success" => true,
"content" => "VPN Stopped...");
}
// Builds the openvpn command string and calls it to start the VPN
private function startVPN(){ private function startVPN(){
$inputData = $this->request->data; $inputData = $this->request->data;
$open_vpn_cmd = "openvpn --config "; $open_vpn_cmd = "openvpn --log /pineapple/modules/OpenVPNConnect/log/vpn.log --status /pineapple/modules/OpenVPNConnect/log/status.log --config ";
if($inputData[0] != ''){ if($inputData[0] != ''){
$config_name = $inputData[0]; $config_name = $inputData[0];
@ -118,27 +166,42 @@ class OpenVPNConnect extends Module{
return; return;
} }
if($inputData[1] != ''){
if($inputData[1] != '' && $inputData[2] != ''){
//Create auth.txt file for openvpn command to read in
$config_user = $inputData[1];
$config_pass = $inputData[2];
$config_string = $config_user . PHP_EOL . $config_pass;
$auth_file = fopen("/tmp/vpn_auth.txt", "w");
fwrite($auth_file, $config_string);
fclose($auth_file);
$open_vpn_cmd .= "--auth-nocache --auth-user-pass /tmp/vpn_auth.txt ";
}else if($inputData[2] != ''){
//Create password file for openvpn command to read in //Create password file for openvpn command to read in
$config_pass = $inputData[1]; $config_pass = $inputData[2];
$pass_file = fopen("/tmp/vpn_pass.txt", "w"); $pass_file = fopen("/tmp/vpn_pass.txt", "w");
fwrite($pass_file, $config_pass); fwrite($pass_file, $config_pass);
fclose($pass_file); fclose($pass_file);
$open_vpn_cmd .= "--auth-nocache --askpass /tmp/vpn_pass.txt "; $open_vpn_cmd .= "--auth-nocache --askpass /tmp/vpn_pass.txt ";
} }
if($inputData[2] != ''){
$openvpn_flags = $inputData[2]; if($inputData[3] != ''){
$openvpn_flags = $inputData[3];
$open_vpn_cmd .= $openvpn_flags; $open_vpn_cmd .= $openvpn_flags;
} }
if($inputData[3] == true){ if($inputData[4] == true){
//Share VPN With Clients Connecting //Share VPN With Clients Connecting
$this->execBackground("iptables -t nat -A POSTROUTING -s 172.16.42.0/24 -o tun0 -j MASQUERADE"); $gateway = $this->uciGet("network.lan.gateway");
$this->execBackground("iptables -A FORWARD -s 172.16.42.0/24 -o tun0 -j ACCEPT"); $netmask = $this->uciGet("network.lan.netmask");
$this->execBackground("iptables -A FORWARD -d 172.16.42.0/24 -m state --state ESTABLISHED,RELATED -i tun0 -j ACCEPT");
$this->execBackground("iptables -t nat -A POSTROUTING -s ". $gateway ."/". $netmask. " -o tun0 -j MASQUERADE");
$this->execBackground("iptables -A FORWARD -s ". $gateway ."/". $netmask . " -o tun0 -j ACCEPT");
$this->execBackground("iptables -A FORWARD -d ". $gateway ."/". $netmask ." -m state --state ESTABLISHED,RELATED -i tun0 -j ACCEPT");
} }
$result = $this->execBackground($open_vpn_cmd); $result = $this->execBackground($open_vpn_cmd);
@ -151,10 +214,20 @@ class OpenVPNConnect extends Module{
// Calls pkill to kill the OpenVPN process and stop the VPN // Calls pkill to kill the OpenVPN process and stop the VPN
private function stopVPN(){ private function stopVPN(){
//Remove password file that could have been created, don't want any creds lying around ;) //Remove any creds files that could have been created, don't want any creds lying around ;)
unlink("/tmp/vpn_auth.txt");
unlink("/tmp/vpn_pass.txt"); unlink("/tmp/vpn_pass.txt");
exec("pkill openvpn"); //Delete any iptable rules that may have been created for sharing connection with clients
$gateway = $this->uciGet("network.lan.gateway");
$netmask = $this->uciGet("network.lan.netmask");
$this->execBackground("iptables -t nat -D POSTROUTING -s ". $gateway ."/". $netmask. " -o tun0 -j MASQUERADE");
$this->execBackground("iptables -D FORWARD -s ". $gateway ."/". $netmask . " -o tun0 -j ACCEPT");
$this->execBackground("iptables -D FORWARD -d ". $gateway ."/". $netmask ." -m state --state ESTABLISHED,RELATED -i tun0 -j ACCEPT");
//Kill openvpn
$this->execBackground("pkill openvpn");
$this->response = array("success" => true, $this->response = array("success" => true,
"content" => "VPN Stopped..."); "content" => "VPN Stopped...");

View File

@ -4,6 +4,7 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
// Workspace Variables. Each value is populated by the form or displays to the form. // Workspace Variables. Each value is populated by the form or displays to the form.
$scope.workspace = {config: "", $scope.workspace = {config: "",
user: "",
pass: "", pass: "",
flags: "", flags: "",
sharedconnection: false, sharedconnection: false,
@ -18,14 +19,17 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
*/ */
$scope.content = ""; $scope.content = "";
$scope.installLabel = "default"; $scope.installLabel = "default";
$scope.installLabelText = "Checking..." $scope.installLabelText = "Checking...";
$scope.installSDLabelText = "Checking...";
$scope.selectedFiles = []; $scope.selectedFiles = [];
$scope.hideSDDependency = false;
$scope.uploading = false; $scope.uploading = false;
$scope.installButtonWidth = "210px";
// Call a function to install/uninstall dependencies for the module // Call a function to install/uninstall dependencies for the module (install to local storage)
$scope.handleDependencies = function(){ $scope.handleDependencies = function(){
$scope.workspace.setupcontent = "Handling dependencies please wait..."; $scope.workspace.setupcontent = "Handling dependencies (local storage) please wait...";
$api.request({ $api.request({
module: 'OpenVPNConnect', module: 'OpenVPNConnect',
@ -44,6 +48,28 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
} }
// Call a function to install/uninstall dependencies for the module (install to the SD card)
$scope.handleDependenciesSDCard = function(){
$scope.workspace.setupcontent = "Handling dependencies (SD card) please wait...";
$api.request({
module: 'OpenVPNConnect',
action: 'handleDependenciesSDCard',
}, function(response) {
if (response.success === true) {
$scope.workspace.setupcontent = response.content;
checkDependencies();
$timeout(function() {$window.location.reload();}, 5000);
}
//console.log(response) //Log the response to the console, this is useful for debugging.
});
}
/* Checks the current status of the dependencies for the module and displays /* Checks the current status of the dependencies for the module and displays
it via the dependency install/uninstall button to the user. it via the dependency install/uninstall button to the user.
This is checked each time the app is loaded or when the user This is checked each time the app is loaded or when the user
@ -57,6 +83,11 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
if (response.success === true) { if (response.success === true) {
$scope.installLabel = response.label; $scope.installLabel = response.label;
$scope.installLabelText = response.text; $scope.installLabelText = response.text;
$scope.installSDLabelText = response.textSD;
$scope.installButtonWidth = response.buttonWidth;
if(response.installed){
$scope.hideSDDependency = true;
}
} }
//console.log(response) //Log the response to the console, this is useful for debugging. //console.log(response) //Log the response to the console, this is useful for debugging.
}); });
@ -65,6 +96,22 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
// Call the checkDependencies function on page load // Call the checkDependencies function on page load
checkDependencies(); checkDependencies();
// Function to check if the VPN is currently running or not when re-visiting the module
var checkVPNStatus = function() {
$api.request({
module: 'OpenVPNConnect',
action: 'checkVPNStatus'
}, function(response) {
if (response.success === true) {
$scope.workspace.outputcontent = response.content;
}
//console.log(response) //Log the response to the console, this is useful for debugging.
});
}
// Call checkVPNStatus function on page load
checkVPNStatus();
/* Initializes module by creating necessary folder structures and scanning for uploaded certs /* Initializes module by creating necessary folder structures and scanning for uploaded certs
this function is called each time the app is loaded to make sure the module is set up correctly this function is called each time the app is loaded to make sure the module is set up correctly
*/ */
@ -100,7 +147,6 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
$scope.workspace.config = cert; $scope.workspace.config = cert;
} }
/* Calls the startVPN function, passes all the form params to the API to run the OpenVPN command /* Calls the startVPN function, passes all the form params to the API to run the OpenVPN command
Users can pass a config, an option password, and optional command line flags to run with the Users can pass a config, an option password, and optional command line flags to run with the
openvpn command line utility. Also the shared connection open lets the user share the openvpn command line utility. Also the shared connection open lets the user share the
@ -111,6 +157,7 @@ registerController('openVPNConnectController', ['$api', '$scope', '$timeout', '$
module: 'OpenVPNConnect', module: 'OpenVPNConnect',
action: 'startVPN', action: 'startVPN',
data: [$scope.workspace.config, data: [$scope.workspace.config,
$scope.workspace.user,
$scope.workspace.pass, $scope.workspace.pass,
$scope.workspace.flags, $scope.workspace.flags,
$scope.workspace.sharedconnection] $scope.workspace.sharedconnection]

View File

View File

View File

@ -13,7 +13,8 @@
<div class="panel-body"> <div class="panel-body">
<div class="form-group"> <div class="form-group">
<label class="control-label text-center">Dependencies:</label> <label class="control-label text-center">Dependencies:</label>
<button type="button" style="width: 90px;" class="btn btn-{{installLabel}} btn-xs" ng-click="handleDependencies()">{{installLabelText}}</button> <button type="button" style="width: {{installButtonWidth}};" class="btn btn-{{installLabel}} btn-xs" ng-click="handleDependencies()">{{installLabelText}}</button>
<button type="button" style="width: 160px;" class="btn btn-{{installLabel}} btn-xs" ng-hide="hideSDDependency" ng-click="handleDependenciesSDCard()">{{installSDLabelText}}</button>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label text-center">Setup Status</label> <label class="control-label text-center">Setup Status</label>
@ -58,7 +59,12 @@
<p> <p>
<input class="form-control" ng-model="workspace.config" placeholder="Enter input"></input> <input class="form-control" ng-model="workspace.config" placeholder="Enter input"></input>
</p> </p>
<label class="control-label text-center">VPN Config Password (Optional):</label> <label class="control-label text-center">VPN Config User (Optional, makes use of --auth-user-pass):</label>
<a href="javascript:;" ng-click="workspace.user = ''">Clear</a>
<p>
<input class="form-control" ng-model="workspace.user" placeholder="Enter input"></input>
</p>
<label class="control-label text-center">VPN Config Password (Optional, falls back to --askpass if no user is provided):</label>
<a href="javascript:;" ng-click="workspace.pass = ''">Clear</a> <a href="javascript:;" ng-click="workspace.pass = ''">Clear</a>
<p> <p>
<input class="form-control" type="password" ng-model="workspace.pass" placeholder="Enter input"></input> <input class="form-control" type="password" ng-model="workspace.pass" placeholder="Enter input"></input>
@ -136,6 +142,18 @@
<div id="collapseChangelog" class="panel-collapse collapse"> <div id="collapseChangelog" class="panel-collapse collapse">
<div class="panel-body"> <div class="panel-body">
<ul> <ul>
<li>
<b>1.0.2 </b>
</li>
<ul>
<li class="text-muted">Added in current status when revisiting page, logging, and ability to install dependencies to SD card or local storage. Also squashed some bugs :)</li>
</ul>
<li>
<b>1.0.1 </b>
</li>
<ul>
<li class="text-muted">Minor Revisions: Added better iptables management with dynamic gateway and the ability to use auth-user-pass. Unofficial Release (Github Only)</li>
</ul>
<li> <li>
<b>1.0</b> <b>1.0</b>
</li> </li>

View File

@ -6,5 +6,5 @@
"tetra" "tetra"
], ],
"title": "OpenVPNConnect", "title": "OpenVPNConnect",
"version": "1.0" "version": "1.1"
} }