mirror of
https://github.com/RaspAP/raspap-webgui.git
synced 2024-11-21 23:20:22 +00:00
Merge pull request #45 from RaspAP/feature/wg-extended
Extend WG functionality
This commit is contained in:
commit
78c4dff40b
9 changed files with 779 additions and 114 deletions
|
@ -307,7 +307,6 @@ $('#ovpn-confirm-activate').on('shown.bs.modal', function (e) {
|
|||
});
|
||||
|
||||
$('#ovpn-userpw,#ovpn-certs').on('click', function (e) {
|
||||
// e.stopPropagation();
|
||||
if (this.id == 'ovpn-userpw') {
|
||||
$('#PanelCerts').hide();
|
||||
$('#PanelUserPW').show();
|
||||
|
@ -317,6 +316,20 @@ $('#ovpn-userpw,#ovpn-certs').on('click', function (e) {
|
|||
}
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$("#PanelManual").hide();
|
||||
});
|
||||
|
||||
$('#wg-upload,#wg-manual').on('click', function (e) {
|
||||
if (this.id == 'wg-upload') {
|
||||
$('#PanelManual').hide();
|
||||
$('#PanelUpload').show();
|
||||
} else if (this.id == 'wg-manual') {
|
||||
$('#PanelUpload').hide();
|
||||
$('#PanelManual').show();
|
||||
}
|
||||
});
|
||||
|
||||
// Add the following code if you want the name of the file appear on select
|
||||
$(".custom-file-input").on("change", function() {
|
||||
var fileName = $(this).val().split("\\").pop();
|
||||
|
|
505
app/lib/uploader.php
Normal file
505
app/lib/uploader.php
Normal file
|
@ -0,0 +1,505 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Simple PHP upload class
|
||||
*
|
||||
* Adapted from aivis/PHP-file-upload-class
|
||||
*
|
||||
* @description File upload class for RaspAP
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @author Aivis Silins
|
||||
* @link https://github.com/aivis/PHP-file-upload-class
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace RaspAP\Uploader;
|
||||
|
||||
class Upload
|
||||
{
|
||||
|
||||
/**
|
||||
* Default directory persmissions (destination)
|
||||
*/
|
||||
protected $default_permissions = 0750;
|
||||
|
||||
/**
|
||||
* File post array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $file_post = array();
|
||||
|
||||
/**
|
||||
* Destination directory
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $destination;
|
||||
|
||||
/**
|
||||
* Fileinfo
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $finfo;
|
||||
|
||||
/**
|
||||
* Data about file
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $file = array();
|
||||
|
||||
/**
|
||||
* Max. file size
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $max_file_size;
|
||||
|
||||
/**
|
||||
* Allowed mime types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mimes = array();
|
||||
|
||||
/**
|
||||
* Temp path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tmp_name;
|
||||
|
||||
/**
|
||||
* Validation errors
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $validation_errors = array();
|
||||
|
||||
/**
|
||||
* Filename (new)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* Internal callbacks (filesize check, mime, etc)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $callbacks = array();
|
||||
|
||||
/**
|
||||
* Root dir
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* Return upload object
|
||||
*
|
||||
* $destination = 'path/to/file/destination/';
|
||||
*
|
||||
* @param string $destination
|
||||
* @param string $root
|
||||
* @return Upload
|
||||
*/
|
||||
public static function factory($destination, $root = false)
|
||||
{
|
||||
return new Upload($destination, $root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define root constant and set & create destination path
|
||||
*
|
||||
* @param string $destination
|
||||
* @param string $root
|
||||
*/
|
||||
public function __construct($destination, $root = false)
|
||||
{
|
||||
if ($root) {
|
||||
$this->root = $root;
|
||||
} else {
|
||||
$this->root = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
// set & create destination path
|
||||
if (!$this->set_destination($destination)) {
|
||||
throw new Exception('Upload: Unable to create destination. '.$this->root . $this->destination);
|
||||
}
|
||||
//create finfo object
|
||||
$this->finfo = new \finfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set target filename
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
public function set_filename($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check & Save file
|
||||
*
|
||||
* Return data about current upload
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function upload($filename = false)
|
||||
{
|
||||
if($filename ) {
|
||||
$this->set_filename($filename);
|
||||
}
|
||||
|
||||
$this->set_filename($filename);
|
||||
|
||||
if ($this->check()) {
|
||||
$this->save();
|
||||
}
|
||||
|
||||
// return state data
|
||||
return $this->get_state();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save file on server
|
||||
* Return state data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$this->save_file();
|
||||
return $this->get_state();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate file (execute callbacks)
|
||||
* Returns TRUE if validation successful
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
//execute callbacks (check filesize, mime, also external callbacks
|
||||
$this->validate();
|
||||
|
||||
//add error messages
|
||||
$this->file['errors'] = $this->get_errors();
|
||||
|
||||
//change file validation status
|
||||
$this->file['status'] = empty($this->validation_errors);
|
||||
|
||||
return $this->file['status'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current state data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_state()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save file on server
|
||||
*/
|
||||
protected function save_file()
|
||||
{
|
||||
//create & set new filename
|
||||
if(empty($this->filename)) {
|
||||
$this->create_new_filename();
|
||||
}
|
||||
|
||||
//set filename
|
||||
$this->file['filename'] = $this->filename;
|
||||
|
||||
//set full path
|
||||
$this->file['full_path'] = $this->root . $this->destination . $this->filename;
|
||||
$this->file['path'] = $this->destination . $this->filename;
|
||||
|
||||
$status = move_uploaded_file($this->tmp_name, $this->file['full_path']);
|
||||
|
||||
//checks whether upload successful
|
||||
if (!$status) {
|
||||
throw new Exception('Upload: Failed to upload file.');
|
||||
}
|
||||
|
||||
//done
|
||||
$this->file['status'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data about file
|
||||
*/
|
||||
protected function set_file_data()
|
||||
{
|
||||
$file_size = $this->get_file_size();
|
||||
$this->file = array(
|
||||
'status' => false,
|
||||
'destination' => $this->destination,
|
||||
'size_in_bytes' => $file_size,
|
||||
'size_in_mb' => $this->bytes_to_mb($file_size),
|
||||
'mime' => $this->get_file_mime(),
|
||||
'filename' => $this->file_post['name'],
|
||||
'tmp_name' => $this->file_post['tmp_name'],
|
||||
'post_data' => $this->file_post,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set validation error
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function set_error($message)
|
||||
{
|
||||
$this->validation_errors[] = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return validation errors
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_errors()
|
||||
{
|
||||
return $this->validation_errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set external callback methods
|
||||
*
|
||||
* @param object $instance_of_callback_object
|
||||
* @param array $callback_methods
|
||||
*/
|
||||
public function callbacks($instance_of_callback_object, $callback_methods)
|
||||
{
|
||||
if (empty($instance_of_callback_object)) {
|
||||
throw new Exception('Upload: $instance_of_callback_object cannot be empty.');
|
||||
|
||||
}
|
||||
|
||||
if (!is_array($callback_methods)) {
|
||||
throw new Exception('Upload: $callback_methods data type need to be array.');
|
||||
}
|
||||
|
||||
$this->external_callback_object = $instance_of_callback_object;
|
||||
$this->external_callback_methods = $callback_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute callbacks
|
||||
*/
|
||||
protected function validate()
|
||||
{
|
||||
//get curent errors
|
||||
$errors = $this->get_errors();
|
||||
|
||||
if (empty($errors)) {
|
||||
|
||||
//set data about current file
|
||||
$this->set_file_data();
|
||||
|
||||
//execute internal callbacks
|
||||
$this->execute_callbacks($this->callbacks, $this);
|
||||
|
||||
//execute external callbacks
|
||||
$this->execute_callbacks($this->external_callback_methods, $this->external_callback_object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute callbacks
|
||||
*/
|
||||
protected function execute_callbacks($callbacks, $object)
|
||||
{
|
||||
foreach($callbacks as $method) {
|
||||
$object->$method($this);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* File mime type validation callback
|
||||
*
|
||||
* @param object $object
|
||||
*/
|
||||
protected function check_mime_type($object)
|
||||
{
|
||||
if (!empty($object->mimes)) {
|
||||
if (!in_array($object->file['mime'], $object->mimes)) {
|
||||
$object->set_error('Mime type not allowed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allowed mime types
|
||||
*
|
||||
* @param array $mimes
|
||||
*/
|
||||
public function set_allowed_mime_types($mimes)
|
||||
{
|
||||
$this->mimes = $mimes;
|
||||
//if mime types is set -> set callback
|
||||
$this->callbacks[] = 'check_mime_type';
|
||||
}
|
||||
|
||||
/**
|
||||
* File size validation callback
|
||||
*
|
||||
* @param object $object
|
||||
*/
|
||||
protected function check_file_size($object)
|
||||
{
|
||||
if (!empty($object->max_file_size)) {
|
||||
$file_size_in_mb = $this->bytes_to_mb($object->file['size_in_bytes']);
|
||||
if ($object->max_file_size <= $file_size_in_mb) {
|
||||
$object->set_error('File exceeds maximum allowed size.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set max file size
|
||||
*
|
||||
* @param int $size
|
||||
*/
|
||||
public function set_max_file_size($size)
|
||||
{
|
||||
$this->max_file_size = $size;
|
||||
|
||||
//if max file size is set -> set callback
|
||||
$this->callbacks[] = 'check_file_size';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set File array to object
|
||||
*
|
||||
* @param array $file
|
||||
*/
|
||||
public function file($file)
|
||||
{
|
||||
$this->set_file_array($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file array
|
||||
*
|
||||
* @param array $file
|
||||
*/
|
||||
protected function set_file_array($file)
|
||||
{
|
||||
//checks whether file array is valid
|
||||
if (!$this->check_file_array($file)) {
|
||||
//file not selected or some bigger problems (broken files array)
|
||||
$this->set_error('Please select file.');
|
||||
}
|
||||
|
||||
//set file data
|
||||
$this->file_post = $file;
|
||||
|
||||
//set tmp path
|
||||
$this->tmp_name = $file['tmp_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether Files post array is valid
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function check_file_array($file)
|
||||
{
|
||||
return isset($file['error'])
|
||||
&& !empty($file['name'])
|
||||
&& !empty($file['type'])
|
||||
&& !empty($file['tmp_name'])
|
||||
&& !empty($file['size']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file mime type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_file_mime()
|
||||
{
|
||||
return $this->finfo->file($this->tmp_name, FILEINFO_MIME_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function get_file_size()
|
||||
{
|
||||
return filesize($this->tmp_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination path (return TRUE on success)
|
||||
*
|
||||
* @param string $destination
|
||||
* @return bool
|
||||
*/
|
||||
protected function set_destination($destination)
|
||||
{
|
||||
$this->destination = $destination . DIRECTORY_SEPARATOR;
|
||||
return $this->destination_exist() ? true : $this->create_destination();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether destination folder exists
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function destination_exist()
|
||||
{
|
||||
return is_writable($this->root . $this->destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create path to destination
|
||||
*
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
*/
|
||||
protected function create_destination()
|
||||
{
|
||||
return mkdir($this->root . $this->destination, $this->default_permissions, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set unique filename
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function create_new_filename()
|
||||
{
|
||||
$filename = sha1(mt_rand(1, 9999) . $this->destination . uniqid()) . time();
|
||||
$this->set_filename($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bytes to MB
|
||||
*
|
||||
* @param int $bytes
|
||||
* @return int
|
||||
*/
|
||||
protected function bytes_to_mb($bytes)
|
||||
{
|
||||
return round(($bytes / 1048576), 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -721,13 +721,15 @@ function validateCidr($cidr)
|
|||
}
|
||||
|
||||
// Validates a host or FQDN
|
||||
function validate_host($host) {
|
||||
function validate_host($host)
|
||||
{
|
||||
return preg_match('/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i', $host);
|
||||
}
|
||||
|
||||
// Gets night mode toggle value
|
||||
// @return boolean
|
||||
function getNightmode(){
|
||||
function getNightmode()
|
||||
{
|
||||
if ($_COOKIE['theme'] == 'lightsout.css') {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -736,7 +738,8 @@ function getNightmode(){
|
|||
}
|
||||
|
||||
// search array for matching string and return only first matching group
|
||||
function preg_only_match($pat,$haystack) {
|
||||
function preg_only_match($pat,$haystack)
|
||||
{
|
||||
$match = "";
|
||||
if(!empty($haystack) && !empty($pat)) {
|
||||
if(!is_array($haystack)) $haystack = array($haystack);
|
||||
|
@ -754,10 +757,34 @@ function qr_encode($str)
|
|||
return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str);
|
||||
}
|
||||
|
||||
function evalHexSequence($string) {
|
||||
function evalHexSequence($string)
|
||||
{
|
||||
$evaluator = function ($input) {
|
||||
return hex2bin($input[1]);
|
||||
};
|
||||
return preg_replace_callback('/\\\x(..)/', $evaluator, $string);
|
||||
}
|
||||
|
||||
/* File upload callback object
|
||||
*
|
||||
*/
|
||||
class validation
|
||||
{
|
||||
public function check_name_length($object)
|
||||
{
|
||||
if (strlen($object->file['filename']) > 255) {
|
||||
$object->set_error('File name is too long.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolves public IP address
|
||||
*
|
||||
* @return string $public_ip
|
||||
*/
|
||||
function get_public_ip()
|
||||
{
|
||||
exec('wget https://ipinfo.io/ip -qO -', $public_ip);
|
||||
return $public_ip[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
require_once 'includes/status_messages.php';
|
||||
require_once 'includes/config.php';
|
||||
require_once 'includes/wifi_functions.php';
|
||||
require_once 'app/lib/uploader.php';
|
||||
|
||||
getWifiInterface();
|
||||
|
||||
|
@ -41,11 +42,9 @@ function DisplayOpenVPNConfig()
|
|||
}
|
||||
|
||||
exec('pidof openvpn | wc -l', $openvpnstatus);
|
||||
exec('wget https://ipinfo.io/ip -qO -', $return);
|
||||
|
||||
$serviceStatus = $openvpnstatus[0] == 0 ? "down" : "up";
|
||||
$auth = file(RASPI_OPENVPN_CLIENT_LOGIN, FILE_IGNORE_NEW_LINES);
|
||||
$public_ip = $return[0];
|
||||
$public_ip = get_public_ip();
|
||||
|
||||
// parse client auth credentials
|
||||
if (!empty($auth)) {
|
||||
|
@ -100,8 +99,8 @@ function DisplayOpenVPNConfig()
|
|||
*/
|
||||
function SaveOpenVPNConfig($status, $file, $authUser, $authPassword)
|
||||
{
|
||||
$tmp_ovpnclient = '/tmp/ovpnclient.ovpn';
|
||||
$tmp_authdata = '/tmp/authdata';
|
||||
define('KB', 1024);
|
||||
$tmp_destdir = '/tmp/';
|
||||
$auth_flag = 0;
|
||||
|
||||
try {
|
||||
|
@ -110,66 +109,28 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword)
|
|||
throw new RuntimeException('Invalid parameters');
|
||||
}
|
||||
|
||||
// Parse returned errors
|
||||
switch ($file['error']) {
|
||||
case UPLOAD_ERR_OK:
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
throw new RuntimeException('OpenVPN configuration file not sent');
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
throw new RuntimeException('Exceeded filesize limit');
|
||||
default:
|
||||
throw new RuntimeException('Unknown errors');
|
||||
}
|
||||
$upload = \RaspAP\Uploader\Upload::factory('ovpn',$tmp_destdir);
|
||||
$upload->set_max_file_size(64*KB);
|
||||
$upload->set_allowed_mime_types(array('ovpn' => 'text/plain'));
|
||||
$upload->file($file);
|
||||
|
||||
// Validate extension
|
||||
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
if ($ext != 'ovpn') {
|
||||
throw new RuntimeException('Invalid file extension');
|
||||
}
|
||||
$validation = new validation;
|
||||
$upload->callbacks($validation, array('check_name_length'));
|
||||
$results = $upload->upload();
|
||||
|
||||
// Validate MIME type
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
if (false === $ext = array_search(
|
||||
$finfo->file($file['tmp_name']),
|
||||
array(
|
||||
'ovpn' => 'text/plain'
|
||||
),
|
||||
true
|
||||
)
|
||||
) {
|
||||
throw new RuntimeException('Invalid file format');
|
||||
}
|
||||
|
||||
// Validate filesize
|
||||
define('KB', 1024);
|
||||
if ($file['size'] > 64*KB) {
|
||||
throw new RuntimeException('File size limit exceeded');
|
||||
}
|
||||
|
||||
// Use safe filename, save to /tmp
|
||||
if (!move_uploaded_file(
|
||||
$file['tmp_name'],
|
||||
sprintf(
|
||||
'/tmp/%s.%s',
|
||||
'ovpnclient',
|
||||
$ext
|
||||
)
|
||||
)
|
||||
) {
|
||||
throw new RuntimeException('Unable to move uploaded file');
|
||||
if (!empty($results['errors'])) {
|
||||
throw new RuntimeException($results['errors'][0]);
|
||||
}
|
||||
|
||||
// Good file upload, update auth credentials if present
|
||||
if (!empty($authUser) && !empty($authPassword)) {
|
||||
$auth_flag = 1;
|
||||
// Move tmp authdata to /etc/openvpn/login.conf
|
||||
$auth.= $authUser .PHP_EOL . $authPassword .PHP_EOL;
|
||||
$tmp_authdata = $tmp_destdir .'ovpn/authdata';
|
||||
$auth = $authUser .PHP_EOL . $authPassword .PHP_EOL;
|
||||
file_put_contents($tmp_authdata, $auth);
|
||||
chmod($tmp_authdata, 0644);
|
||||
$client_auth = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_login.conf';
|
||||
system("sudo cp $tmp_authdata $client_auth", $return);
|
||||
system("sudo mv $tmp_authdata $client_auth", $return);
|
||||
system("sudo rm ".RASPI_OPENVPN_CLIENT_LOGIN, $return);
|
||||
system("sudo ln -s $client_auth ".RASPI_OPENVPN_CLIENT_LOGIN, $return);
|
||||
if ($return !=0) {
|
||||
|
@ -178,14 +139,16 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword)
|
|||
}
|
||||
|
||||
// Set iptables rules and, optionally, auth-user-pass
|
||||
exec("sudo /etc/raspap/openvpn/configauth.sh $tmp_ovpnclient $auth_flag " .$_SESSION['ap_interface'], $return);
|
||||
$tmp_ovpn = $results['full_path'];
|
||||
exec("sudo /etc/raspap/openvpn/configauth.sh $tmp_ovpn $auth_flag " .$_SESSION['ap_interface'], $return);
|
||||
foreach ($return as $line) {
|
||||
$status->addMessage($line, 'info');
|
||||
}
|
||||
|
||||
// Move uploaded ovpn config from /tmp and create symlink
|
||||
$client_ovpn = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_client.conf';
|
||||
chmod($tmp_ovpnclient, 0644);
|
||||
system("sudo cp $tmp_ovpnclient $client_ovpn", $return);
|
||||
chmod($tmp_ovpn, 0644);
|
||||
system("sudo mv $tmp_ovpn $client_ovpn", $return);
|
||||
system("sudo rm ".RASPI_OPENVPN_CLIENT_CONFIG, $return);
|
||||
system("sudo ln -s $client_ovpn ".RASPI_OPENVPN_CLIENT_CONFIG, $return);
|
||||
|
||||
|
@ -201,3 +164,4 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword)
|
|||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,13 @@ function DisplayWireGuardConfig()
|
|||
{
|
||||
$status = new StatusMessages();
|
||||
if (!RASPI_MONITOR_ENABLED) {
|
||||
if (isset($_POST['savewgsettings'])) {
|
||||
$optRules = $_POST['wgRules'];
|
||||
$optConf = $_POST['wgCnfOpt'];
|
||||
$optSrvEnable = $_POST['wgSrvEnable'];
|
||||
if (isset($_POST['savewgsettings']) && $optConf == 'manual' && $optSrvEnable == 1 ) {
|
||||
SaveWireGuardConfig($status);
|
||||
} elseif (isset($_POST['savewgsettings']) && $optConf == 'upload' && is_uploaded_file($_FILES["wgFile"]["tmp_name"])) {
|
||||
SaveWireGuardUpload($status, $_FILES['wgFile'], $optRules);
|
||||
} elseif (isset($_POST['startwg'])) {
|
||||
$status->addMessage('Attempting to start WireGuard', 'info');
|
||||
exec('sudo /bin/systemctl start wg-quick@wg0', $return);
|
||||
|
@ -27,7 +32,7 @@ function DisplayWireGuardConfig()
|
|||
}
|
||||
}
|
||||
|
||||
// fetch wg config
|
||||
// fetch server config
|
||||
exec('sudo cat '. RASPI_WIREGUARD_CONFIG, $return);
|
||||
$conf = ParseConfig($return);
|
||||
$wg_srvpubkey = exec('sudo cat '. RASPI_WIREGUARD_PATH .'wg-server-public.key', $return);
|
||||
|
@ -39,7 +44,7 @@ function DisplayWireGuardConfig()
|
|||
$wg_senabled = true;
|
||||
}
|
||||
|
||||
// todo: iterate multiple peer configs
|
||||
// fetch client config
|
||||
exec('sudo cat '. RASPI_WIREGUARD_PATH.'client.conf', $preturn);
|
||||
$conf = ParseConfig($preturn);
|
||||
$wg_pipaddress = ($conf['Address'] == '') ? getDefaultNetValue('wireguard','peer','Address') : $conf['Address'];
|
||||
|
@ -55,12 +60,15 @@ function DisplayWireGuardConfig()
|
|||
exec('pidof wg-crypt-wg0 | wc -l', $wgstatus);
|
||||
$serviceStatus = $wgstatus[0] == 0 ? "down" : "up";
|
||||
$wg_state = ($wgstatus[0] > 0);
|
||||
$public_ip = get_public_ip();
|
||||
|
||||
echo renderTemplate(
|
||||
"wireguard", compact(
|
||||
"status",
|
||||
"wg_state",
|
||||
"serviceStatus",
|
||||
"public_ip",
|
||||
"optRules",
|
||||
"wg_log",
|
||||
"peer_id",
|
||||
"wg_srvpubkey",
|
||||
|
@ -79,6 +87,71 @@ function DisplayWireGuardConfig()
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates uploaded .conf file, adds iptables post-up and
|
||||
* post-down rules.
|
||||
*
|
||||
* @param object $status
|
||||
* @param object $file
|
||||
* @param boolean $optRules
|
||||
* @return object $status
|
||||
*/
|
||||
function SaveWireGuardUpload($status, $file, $optRules)
|
||||
{
|
||||
define('KB', 1024);
|
||||
$tmp_destdir = '/tmp/';
|
||||
$auth_flag = 0;
|
||||
|
||||
try {
|
||||
// If undefined or multiple files, treat as invalid
|
||||
if (!isset($file['error']) || is_array($file['error'])) {
|
||||
throw new RuntimeException('Invalid parameters');
|
||||
}
|
||||
|
||||
$upload = \RaspAP\Uploader\Upload::factory('wg',$tmp_destdir);
|
||||
$upload->set_max_file_size(64*KB);
|
||||
$upload->set_allowed_mime_types(array('text/plain'));
|
||||
$upload->file($file);
|
||||
|
||||
$validation = new validation;
|
||||
$upload->callbacks($validation, array('check_name_length'));
|
||||
$results = $upload->upload();
|
||||
|
||||
if (!empty($results['errors'])) {
|
||||
throw new RuntimeException($results['errors'][0]);
|
||||
}
|
||||
|
||||
// Valid upload, get file contents
|
||||
$tmp_wgconfig = $results['full_path'];
|
||||
$tmp_contents = file_get_contents($tmp_wgconfig);
|
||||
|
||||
// Set iptables rules
|
||||
if (isset($optRules) && !preg_match('/PostUp|PostDown/m',$tmp_contents)) {
|
||||
$rules[] = 'PostUp = '.getDefaultNetValue('wireguard','server','PostUp');
|
||||
$rules[] = 'PostDown = '.getDefaultNetValue('wireguard','server','PostDown');
|
||||
$rules[] = '';
|
||||
$rules = join(PHP_EOL, $rules);
|
||||
$rules = preg_replace('/wlan0/m', $_SESSION['ap_interface'], $rules);
|
||||
$tmp_contents = preg_replace('/^\s*$/ms', $rules, $tmp_contents, 1);
|
||||
file_put_contents($tmp_wgconfig, $tmp_contents);
|
||||
}
|
||||
|
||||
// Move processed file from tmp to destination
|
||||
system("sudo mv $tmp_wgconfig ". RASPI_WIREGUARD_CONFIG, $return);
|
||||
|
||||
if ($return ==0) {
|
||||
$status->addMessage('WireGuard configuration uploaded successfully', 'info');
|
||||
} else {
|
||||
$status->addMessage('Unable to save WireGuard configuration', 'danger');
|
||||
}
|
||||
return $status;
|
||||
|
||||
} catch (RuntimeException $e) {
|
||||
$status->addMessage($e->getMessage(), 'danger');
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user input, save wireguard configuration
|
||||
*
|
||||
|
|
|
@ -20,8 +20,7 @@ www-data ALL=(ALL) NOPASSWD:/bin/systemctl start openvpn-client@client
|
|||
www-data ALL=(ALL) NOPASSWD:/bin/systemctl enable openvpn-client@client
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/systemctl stop openvpn-client@client
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/systemctl disable openvpn-client@client
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/ovpnclient.ovpn /etc/openvpn/client/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/authdata /etc/openvpn/client/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/ovpn/* /etc/openvpn/client/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/usr/bin/ln -s /etc/openvpn/client/*.conf /etc/openvpn/client/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/openvpn/client/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasqdata /etc/dnsmasq.d/090_*.conf
|
||||
|
@ -49,6 +48,7 @@ www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasqdata /etc/dnsmasq.d/090_adblock.
|
|||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasq_custom /etc/raspap/adblock/custom.txt
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/wgdata /etc/wireguard/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/wg-*.key /etc/wireguard/wg-*.key
|
||||
www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/wg/* /etc/wireguard/*.conf
|
||||
www-data ALL=(ALL) NOPASSWD:/etc/raspap/adblock/update_blocklist.sh
|
||||
www-data ALL=(ALL) NOPASSWD:/usr/bin/socat - /dev/ttyUSB[0-9]
|
||||
www-data ALL=(ALL) NOPASSWD:/usr/local/sbin/onoff_huawei_hilink.sh *
|
||||
|
|
Binary file not shown.
|
@ -1026,14 +1026,44 @@ msgstr "Invalid custom host found on line "
|
|||
msgid "Tunnel settings"
|
||||
msgstr "Tunnel settings"
|
||||
|
||||
msgid "Configuration Method"
|
||||
msgstr "Configuration Method"
|
||||
|
||||
msgid "Upload file"
|
||||
msgstr "Upload file"
|
||||
|
||||
msgid "Create manually"
|
||||
msgstr "Create manually"
|
||||
|
||||
msgid "Upload a WireGuard config"
|
||||
msgstr "Upload a WireGuard config"
|
||||
|
||||
msgid "This option uploads and installs an existing WireGuard <code>.conf</code> file on this device."
|
||||
msgstr "This option uploads and installs an existing WireGuard <code>.conf</code> file on this device."
|
||||
|
||||
msgid "Apply iptables rules for AP interface"
|
||||
msgstr "Apply iptables rules for AP interface"
|
||||
|
||||
msgid "Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface."
|
||||
msgstr "Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface."
|
||||
|
||||
msgid "This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)."
|
||||
msgstr "This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)."
|
||||
|
||||
msgid "Select WireGuard configuration file (.conf)"
|
||||
msgstr "Select WireGuard configuration file (.conf)"
|
||||
|
||||
msgid "Create a local WireGuard config"
|
||||
msgstr "Create a local WireGuard config"
|
||||
|
||||
msgid "Enable server"
|
||||
msgstr "Enable server"
|
||||
|
||||
msgid "Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers."
|
||||
msgstr "Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers."
|
||||
msgid "Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers."
|
||||
msgstr "Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers."
|
||||
|
||||
msgid "This option adds <code>wg0.conf</code> to the WireGuard configuration."
|
||||
msgstr "This option adds <code>wg0.conf</code> to the WireGuard configuration."
|
||||
msgid "This setting generates a new WireGuard <code>.conf</code> file on this device."
|
||||
msgstr "This setting generates a new WireGuard <code>.conf</code> file on this device."
|
||||
|
||||
msgid "Local public key"
|
||||
msgstr "Local public key"
|
||||
|
|
|
@ -3,53 +3,106 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h4 class="mt-3"><?php echo _("Tunnel settings"); ?></h4>
|
||||
<div class="input-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input class="custom-control-input" id="server_enabled" type="checkbox" name="wg_senabled" value="1" <?php echo $wg_senabled ? ' checked="checked"' : "" ?> aria-describedby="server-description">
|
||||
<label class="custom-control-label" for="server_enabled"><?php echo _("Enable server") ?></label>
|
||||
</div>
|
||||
<p id="wg-description">
|
||||
<small><?php echo _("Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers.") ?></small>
|
||||
<small><?php echo _("This option adds <code>wg0.conf</code> to the WireGuard configuration.") ?></small>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-3 col-sm-6">
|
||||
<label for="code"><?php echo _("Local public key"); ?></label>
|
||||
</div>
|
||||
<div class="input-group col-md-12 mb-3">
|
||||
<input type="text" class="form-control" name="wg-server" id="wg-srvpubkey" value="<?php echo htmlspecialchars($wg_srvpubkey, ENT_QUOTES); ?>" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary rounded-right wg-keygen" type="button"><i class="fas fa-magic"></i></button>
|
||||
<span id="wg-server-pubkey-status" class="input-group-addon check-hidden ml-2 mt-1"><i class="fas fa-check"></i></span>
|
||||
</div>
|
||||
<div class="col-lg-12 mt-2">
|
||||
<div class="row mt-3 mb-2">
|
||||
<div class="info-item col-xs-3"><?php echo _("IPv4 Address"); ?></div>
|
||||
<div class="info-value col-xs-3"><?php echo htmlspecialchars($public_ip, ENT_QUOTES); ?><a class="text-gray-500" href="https://ipapi.co/<?php echo($public_ip); ?>" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt ml-2"></i></a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-xs-3 col-sm-3">
|
||||
<label for="code"><?php echo _("Local Port"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvport" value="<?php echo htmlspecialchars($wg_srvport, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
<h5><?php echo _("Configuration Method"); ?></h5>
|
||||
<div class="col-sm-12 mt-2 mb-2 form-check">
|
||||
<input class="form-check-input" id="wg-upload" name="wgCnfOpt" value="upload" data-toggle="" data-parent="#serversettings" data-target="#wgUpload" type="radio" checked>
|
||||
<label class="form-check-label"><?php echo _("Upload file"); ?></label>
|
||||
</div>
|
||||
<div class="col-sm-12 mt-2 mb-2 form-check">
|
||||
<input class="form-check-input" id="wg-manual" name="wgCnfOpt" value="manual" data-toggle="" data-parent="#serversettings" data-target="#wgManual" type="radio">
|
||||
<label class="form-check-label"><?php echo _("Create manually"); ?></label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="code"><?php echo _("IP Address"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvipaddress" value="<?php echo htmlspecialchars($wg_srvipaddress, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 ml-2">
|
||||
<div class="panel-group" id="serversettings">
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="code"><?php echo _("DNS"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvdns" value="<?php echo htmlspecialchars($wg_srvdns, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default panel-collapse" id="PanelUpload">
|
||||
<div class="panel-heading">
|
||||
<h5 class="panel-title"><?php echo _("Upload a WireGuard config"); ?></h5>
|
||||
<p id="wg-description">
|
||||
<small><?php echo _("This option uploads and installs an existing WireGuard <code>.conf</code> file on this device.") ?></small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="form-group col-sm-12">
|
||||
<div class="custom-control custom-switch">
|
||||
<?php $checked = $optRules == 1 ? 'checked="checked"' : '' ?>
|
||||
<input class="custom-control-input" id="chxwgrules" name="wgRules" type="checkbox" value="1" <?php echo $checked ?> />
|
||||
<label class="custom-control-label" for="chxwgrules"><?php echo _("Apply iptables rules for AP interface"); ?></label>
|
||||
<i class="fas fa-question-circle text-muted" data-toggle="tooltip" data-placement="auto" title="<?php echo _("Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface."); ?>"></i>
|
||||
<p id="wg-description">
|
||||
<small><?php printf(_("This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)."), $_SESSION['ap_interface']) ?></small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<h5 class="panel-title"><?php echo _("Configuration File"); ?></h4>
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" name="wgFile" id="wgFile">
|
||||
<label class="custom-file-label" for="wgFile"><?php echo _("Select WireGuard configuration file (.conf)"); ?></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2"></div>
|
||||
|
||||
</div><!-- /.panel-body -->
|
||||
</div><!-- /.panel -->
|
||||
|
||||
<div class="panel panel-default panel-collapse" id="PanelManual">
|
||||
<div class="panel-heading">
|
||||
<h5 class="panel-title"><?php echo _("Create a local WireGuard config"); ?></h5>
|
||||
<div class="input-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input class="custom-control-input" id="server_enabled" type="checkbox" name="wgSrvEnable" value="1" <?php echo $wg_senabled ? ' checked="checked"' : "" ?> aria-describedby="server-description">
|
||||
<label class="custom-control-label" for="server_enabled"><?php echo _("Enable server") ?></label>
|
||||
</div>
|
||||
<p id="wg-description">
|
||||
<small>
|
||||
<?php echo _("Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers.") ?>
|
||||
<?php echo _("This setting generates a new WireGuard <code>.conf</code> file on this device.") ?>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<label for="code"><?php echo _("Local public key"); ?></label>
|
||||
<div class="input-group col-md-12 mb-3">
|
||||
<input type="text" class="form-control" name="wg-server" id="wg-srvpubkey" value="<?php echo htmlspecialchars($wg_srvpubkey, ENT_QUOTES); ?>" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary rounded-right wg-keygen" type="button"><i class="fas fa-magic"></i></button>
|
||||
<span id="wg-server-pubkey-status" class="input-group-addon check-hidden ml-2 mt-1"><i class="fas fa-check"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-xs-3 col-sm-3">
|
||||
<label for="code"><?php echo _("Local Port"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvport" value="<?php echo htmlspecialchars($wg_srvport, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="code"><?php echo _("IP Address"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvipaddress" value="<?php echo htmlspecialchars($wg_srvipaddress, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="code"><?php echo _("DNS"); ?></label>
|
||||
<input type="text" class="form-control" name="wg_srvdns" value="<?php echo htmlspecialchars($wg_srvdns, ENT_QUOTES); ?>" />
|
||||
</div>
|
||||
<div class="row mb-3"></div>
|
||||
|
||||
</div><!-- /.panel-body -->
|
||||
</div><!-- /.panel -->
|
||||
|
||||
</div><!-- /.panel-group -->
|
||||
</div><!-- /.col -->
|
||||
</div><!-- /.row -->
|
||||
|
||||
</div>
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.tab-pane | settings tab -->
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue