1
0
mirror of https://github.com/billz/raspap-webgui.git synced 2023-10-10 13:37:24 +02:00

Merge pull request #1087 from RaspAP/billz/insiders-merge

Insiders 1st Edition
This commit is contained in:
Bill Zimmerman 2022-01-01 10:03:08 +01:00 committed by GitHub
commit 60d151b976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 7441 additions and 445 deletions

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,5 +1,5 @@
![](https://i.imgur.com/xeKD93p.png)
[![Release 2.7.1](https://img.shields.io/badge/release-v2.7.1-green)](https://github.com/raspap/raspap-webgui/releases) [![Awesome](https://awesome.re/badge.svg)](https://github.com/thibmaek/awesome-raspberry-pi) [![Join Insiders](https://img.shields.io/static/v1?label=Join%20Insiders&message=%E2%9D%A4&logo=GitHub&color=ff69b4)](https://github.com/sponsors/RaspAP) ![https://travis-ci.com/github/raspap/raspap-webgui/](https://api.travis-ci.org/RaspAP/raspap-webgui.svg) [![Crowdin](https://badges.crowdin.net/raspap/localized.svg)](https://crowdin.com/project/raspap) [![Twitter URL](https://img.shields.io/twitter/url?label=%40RaspAP&logoColor=%23d8224c&url=https%3A%2F%2Ftwitter.com%2Frasp_ap)](https://twitter.com/rasp_ap) [![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/RaspAP?style=social)](https://www.reddit.com/r/RaspAP/)
[![Release 2.8.0](https://img.shields.io/badge/release-v2.8.0-green)](https://github.com/raspap/raspap-webgui/releases) [![Awesome](https://awesome.re/badge.svg)](https://github.com/thibmaek/awesome-raspberry-pi) [![Join Insiders](https://img.shields.io/static/v1?label=Join%20Insiders&message=%E2%9D%A4&logo=GitHub&color=ff69b4)](https://github.com/sponsors/RaspAP) ![https://travis-ci.com/github/raspap/raspap-webgui/](https://api.travis-ci.org/RaspAP/raspap-webgui.svg) [![Crowdin](https://badges.crowdin.net/raspap/localized.svg)](https://crowdin.com/project/raspap) [![Twitter URL](https://img.shields.io/twitter/url?label=%40RaspAP&logoColor=%23d8224c&url=https%3A%2F%2Ftwitter.com%2Frasp_ap)](https://twitter.com/rasp_ap) [![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/RaspAP?style=social)](https://www.reddit.com/r/RaspAP/)
RaspAP is feature-rich wireless router software that _just works_ on many popular [Debian-based devices](#supported-operating-systems), including the Raspberry Pi. Our popular [Quick installer](#quick-installer) creates a known-good default configuration for all current Raspberry Pis with onboard wireless. A fully responsive, mobile-ready interface gives you control over the relevant services and networking options. Advanced DHCP settings, WireGuard and OpenVPN support, [SSL certificates](https://docs.raspap.com/ssl-quick/), security audits, [captive portal integration](https://docs.raspap.com/captive/), themes and [multilingual options](https://docs.raspap.com/translations/) are included.
@ -122,9 +122,9 @@ RaspAP was originally made for Raspbian, but now also installs on the following
| Distribution | Release | Architecture | Support |
|---|:---:|:---:|:---:|
| Raspberry Pi OS | (32-bit) Lite Buster | ARM | Official |
| Armbian | Buster | [ARM](https://docs.armbian.com/#supported-socs) | Official |
| Debian | Buster | ARM / x86_64 | Beta |
| Raspberry Pi OS | (32-bit) Lite Bullseye | ARM | Official |
| Armbian | Bullseye | [ARM](https://docs.armbian.com/#supported-socs) | Official |
| Debian | Bullseye | ARM / x86_64 | Beta |
| Ubuntu | 18.04 LTS / 19.10 | ARM / x86_64 | Beta |
![](https://i.imgur.com/luiyYNw.png)

View File

@ -0,0 +1,9 @@
<?php
require '../../includes/csrf.php';
require_once '../../includes/config.php';
// fetch wg client.conf
exec('sudo cat '. RASPI_WIREGUARD_PATH.'client.conf', $return);
echo implode(PHP_EOL,$return);

View File

@ -0,0 +1,22 @@
<?php
require '../../includes/csrf.php';
require_once '../../includes/config.php';
$entity = $_POST['entity'];
if (isset($entity)) {
// generate public/private key pairs for entity
$pubkey = RASPI_WIREGUARD_PATH.$entity.'-public.key';
$privkey = RASPI_WIREGUARD_PATH.$entity.'-private.key';
$pubkey_tmp = '/tmp/'.$entity.'-public.key';
$privkey_tmp = '/tmp/'.$entity.'-private.key';
exec("sudo wg genkey | tee $privkey_tmp | wg pubkey > $pubkey_tmp", $return);
$wgdata['pubkey'] = str_replace("\n",'',file_get_contents($pubkey_tmp));
exec("sudo mv $privkey_tmp $privkey", $return);
exec("sudo mv $pubkey_tmp $pubkey", $return);
echo json_encode($wgdata);
}

View File

@ -0,0 +1,93 @@
<?php
/*
Save settings of network devices (type, name, PW, APN ...)
Called by js saveNetDeviceSettings (App/js/custom.js)
*/
require '../../includes/csrf.php';
require_once '../../includes/config.php';
require_once '../../includes/functions.php';
if (isset($_POST['interface'])) {
$int = $_POST['interface'];
$cfg = [];
$file = $RASPI_MOBILEDATA_CONFIG;
$cfgfile="/etc/wvdial.conf";
if ( $int == "mobiledata") {
$cfg['pin'] = $_POST["pin-mobile"];
$cfg['apn'] = $_POST["apn-mobile"];
$cfg['apn_user'] = $_POST["apn-user-mobile"];
$cfg['apn_pw'] = $_POST["apn-pw-mobile"];
$cfg['router_user'] = $cfg['apn_user'] ;
$cfg['router_pw'] = $cfg['apn_pw'] ;
if (file_exists($cfgfile)) {
if($cfg["pin"] !== "") exec('sudo /bin/sed -i "s/CPIN=\".*\"/CPIN=\"'.$cfg["pin"].'\"/gi" '.$cfgfile);
if($cfg["apn"] !== "") exec('sudo /bin/sed -i "s/\"IP\"\,\".*\"/\"IP\"\,\"'.$cfg["apn"].'\"/gi" '.$cfgfile);
if($cfg["apn_user"] !== "") exec('sudo /bin/sed -i "s/^username = .*$/Username = '.$cfg["apn_user"].'/gi" '.$cfgfile);
if($cfg["apn_pw"] !== "") exec('sudo /bin/sed -i "s/^password = .*$/Password = '.$cfg["apn_pw"].'/gi" '.$cfgfile);
}
if (write_php_ini($cfg, RASPI_MOBILEDATA_CONFIG)) {
$jsonData = ['return'=>0,'output'=>['Successfully saved mobile data settings']];
} else {
$jsonData = ['return'=>1,'output'=>['Error saving mobile data settings']];
}
} else if ( preg_match("/netdevices/",$int)) {
if(!isset($_POST['opts']) ) {
$jsonData = ['return'=>0,'output'=>['No valid data to add/delete udev rule ']];
echo json_encode($jsonData);
return;
} else {
$opts=explode(" ",$_POST['opts'] );
$dev=$opts[0];
$vid=$_POST["int-vid-".$dev];
$pid=$_POST["int-pid-".$dev];
$mac=$_POST["int-mac-".$dev];
$name=trim($_POST["int-name-".$dev]);
// limit device name to letters and numbers. Total length max 20
$name=preg_replace("/[^a-z0-9]/", "", strtolower($name));
$name=substr($name, 0, min(strlen($name),20));
$type=$_POST["int-type-".$dev];
$newtype=$_POST["int-new-type-".$dev];
$udevfile=$_SESSION["udevrules"]["udev_rules_file"]; // default file /etc/udev/rules.d/80-net-devices.rules";
// find the rule prototype and prefix
$rule = "";
foreach($_SESSION["udevrules"]["network_devices"] as $devt) {
if($devt["type"]==$newtype) {
$rulenew = $devt["udev_rule"];
$prefix = $devt["name_prefix"];
}
}
// check for an existing rule and delete lines with same MAC or same VID/PID
if (!empty($vid) && !empty($pid)) {
$rule = '^.*ATTRS{idVendor}==\"' . $vid . '\".*ATTRS{idProduct}==\"' . $pid . '\".*$';
exec('sudo sed -i "/'.$rule.'/Id" '.$udevfile); // clear all entries with this VID/PID
$rule = '^.*ATTRS{idProduct}==\"' . $pid . '\".*ATTRS{idVendor}==\"' . $vid . '\".*$';
exec('sudo sed -i "/'.$rule.'/Id" '.$udevfile); // clear all entries with this VID/PID
}
if (!empty($mac)) {
exec('sudo sed -i "/^.*'.$mac.'.*$/d" '.$udevfile); // clear all entries with same MAC
}
// create new entry
if ( ($type != $newtype) || !empty($name) ) { // new device type or new name
if (empty($name)) $name = $prefix."%n";
if (!empty($mac)) $rule = preg_replace("/\\\$MAC\\\$/i", $mac, $rulenew);
if (!empty($vid)) $rule = preg_replace("/\\\$IDVENDOR\\\$/i", $vid, $rule);
if (!empty($pid)) $rule = preg_replace("/\\\$IDPRODUCT\\\$/i", $pid, $rule);
if (!empty($name)) $rule = preg_replace("/\\\$DEVNAME\\\$/i",$name,$rule);
if (!empty($rule)) exec('echo \''.$rule.'\' | sudo /usr/bin/tee -a '.$udevfile);
}
$jsonData = ['return'=>0,'output'=>['Settings changed for device '.$dev. '<br>Changes will only be in effect after reconnecting the device' ] ];
}
} else {
$jsonData = ['return'=>1,'output'=>['Unknown network configuration']];
}
} else {
$jsonData = ['return'=>2,'output'=>'Unable to detect interface'];
}
echo json_encode($jsonData);

View File

@ -0,0 +1,26 @@
<?php
require_once '../../includes/config.php';
require_once '../../includes/functions.php';
if (isset($_POST['cfg_id'])) {
$ovpncfg_id = $_POST['cfg_id'];
$ovpncfg_client = RASPI_OPENVPN_CLIENT_PATH.$ovpncfg_id.'_client.conf';
$ovpncfg_login = RASPI_OPENVPN_CLIENT_PATH.$ovpncfg_id.'_login.conf';
// remove existing client config +login and symbolically link the selected one
system("sudo rm ".RASPI_OPENVPN_CLIENT_CONFIG, $return);
system("sudo ln -s $ovpncfg_client ".RASPI_OPENVPN_CLIENT_CONFIG, $return);
system("sudo rm ".RASPI_OPENVPN_CLIENT_LOGIN, $return);
system("sudo ln -s $ovpncfg_login ".RASPI_OPENVPN_CLIENT_LOGIN, $return);
// restart service
exec("sudo /bin/systemctl stop openvpn-client@client", $return);
sleep(1);
exec("sudo /bin/systemctl enable openvpn-client@client", $return);
sleep(1);
exec("sudo /bin/systemctl start openvpn-client@client", $return);
echo json_encode($return);
}

View File

@ -0,0 +1,13 @@
<?php
require_once '../../includes/config.php';
require_once '../../includes/functions.php';
if (isset($_POST['cfg_id'])) {
$ovpncfg_id = $_POST['cfg_id'];
$ovpncfg_files = pathinfo(RASPI_OPENVPN_CLIENT_LOGIN, PATHINFO_DIRNAME).'/'.$ovpncfg_id.'_*.conf';
exec("sudo rm $ovpncfg_files", $return);
$jsonData = ['return'=>$return];
echo json_encode($jsonData);
}

View File

@ -79,6 +79,9 @@ h5.card-title {
font-family: Verdana, Geneva, sans-serif;
}
.sidebar-light hr.sidebar-divider {
padding-top: 0.5rem;
}
ul.nav-tabs, .nav-tabs .nav-link {
background-color: #f6f6ef;
@ -163,6 +166,7 @@ ul.nav-tabs, .nav-tabs .nav-link {
.info-item-xs {
font-size: 0.7rem;
margin-left: 0.3rem;
line-height: 1.5em;
}
.info-item-wifi {
@ -200,6 +204,10 @@ ul.nav-tabs, .nav-tabs .nav-link {
}
}
.fas.fa-circle {
font-size: 0.5rem;
}
.logoutput {
width:100%;
height:300px;

28
app/img/wg-qr-code.php Normal file
View File

@ -0,0 +1,28 @@
<?php
require_once '../../includes/config.php';
require_once '../../includes/defaults.php';
require_once '../../includes/functions.php';
// prevent direct file access
if (!isset($_SERVER['HTTP_REFERER'])) {
header('HTTP/1.0 403 Forbidden');
exit;
}
exec("sudo cat " .RASPI_WIREGUARD_PATH.'client.conf', $return);
$peer_conf = implode(PHP_EOL,$return);
$peer_conf.= PHP_EOL;
$command = "qrencode -t svg -m 0 -o - " . mb_escapeshellarg($peer_conf);
$svg = shell_exec($command);
$etag = hash('sha256', $peer_conf);
$content_length = strlen($svg);
$last_modified = date("Y-m-d H:i:s");
header("Content-Type: image/svg+xml");
header("Content-Length: $content_length");
header("Last-Modified: $last_modified");
header("ETag: \"$etag\"");
header("X-QR-Code-Content: $peer_conf");
echo shell_exec($command);

View File

@ -10,11 +10,6 @@ if (!isset($_SERVER['HTTP_REFERER'])) {
exit;
}
function qr_encode($str)
{
return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str);
}
$hostapd = parse_ini_file(RASPI_HOSTAPD_CONFIG, false, INI_SCANNER_RAW);
// assume wpa encryption and get the passphrase
@ -52,7 +47,8 @@ $content_length = strlen($svg);
header("Content-Type: image/svg+xml");
header("Content-Length: $content_length");
header("Last-Modified: $last_modified");
header("Content-Disposition: attachment; filename=\"qr.svg\"");
header("ETag: \"$etag\"");
header("X-QR-Code-Content: $data");
echo shell_exec($command);
echo $svg;

View File

@ -1,6 +1,5 @@
function msgShow(retcode,msg) {
if(retcode == 0) {
var alertType = 'success';
if(retcode == 0) { var alertType = 'success';
} else if(retcode == 2 || retcode == 1) {
var alertType = 'danger';
}
@ -123,6 +122,11 @@ $(document).on("click", "#gen_wpa_passphrase", function(e) {
$('#txtwpapassphrase').val(genPassword(63));
});
// Enable Bootstrap tooltips
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
function genPassword(pwdLen) {
var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var rndPass = Array(pwdLen).fill(pwdChars).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
@ -252,6 +256,69 @@ $('#hostapdModal').on('shown.bs.modal', function (e) {
$('#configureClientModal').on('shown.bs.modal', function (e) {
});
$('#ovpn-confirm-delete').on('click', '.btn-delete', function (e) {
var cfg_id = $(this).data('recordId');
$.post('ajax/openvpn/del_ovpncfg.php',{'cfg_id':cfg_id},function(data){
jsonData = JSON.parse(data);
$("#ovpn-confirm-delete").modal('hide');
var row = $(document.getElementById("openvpn-client-row-" + cfg_id));
row.fadeOut( "slow", function() {
row.remove();
});
});
});
$('#ovpn-confirm-delete').on('show.bs.modal', function (e) {
var data = $(e.relatedTarget).data();
$('.btn-delete', this).data('recordId', data.recordId);
});
$('#ovpn-confirm-activate').on('click', '.btn-activate', function (e) {
var cfg_id = $(this).data('record-id');
$.post('ajax/openvpn/activate_ovpncfg.php',{'cfg_id':cfg_id},function(data){
jsonData = JSON.parse(data);
$("#ovpn-confirm-activate").modal('hide');
setTimeout(function(){
window.location.reload();
},300);
});
});
$('#ovpn-confirm-activate').on('shown.bs.modal', function (e) {
var data = $(e.relatedTarget).data();
$('.btn-activate', this).data('recordId', data.recordId);
});
$('#ovpn-userpw,#ovpn-certs').on('click', function (e) {
if (this.id == 'ovpn-userpw') {
$('#PanelCerts').hide();
$('#PanelUserPW').show();
} else if (this.id == 'ovpn-certs') {
$('#PanelUserPW').hide();
$('#PanelCerts').show();
}
});
$(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();
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
});
/*
Sets the wirelss channel select options based on hw_mode and country_code.
@ -320,6 +387,55 @@ function updateBlocklist() {
function clearBlocklistStatus() {
$('#cbxblocklist-status').removeClass('check-updated').addClass('check-hidden');
}
// Handler for the wireguard generate key button
$('.wg-keygen').click(function(){
var entity_pub = $(this).parent('div').prev('input[type="text"]');
var entity_priv = $(this).parent('div').next('input[type="hidden"]');
var updated = entity_pub.attr('name')+"-pubkey-status";
$.post('ajax/networking/get_wgkey.php',{'entity':entity_pub.attr('name') },function(data){
var jsonData = JSON.parse(data);
entity_pub.val(jsonData.pubkey);
$('#' + updated).removeClass('check-hidden').addClass('check-updated').delay(500).animate({ opacity: 1 }, 700);
})
})
// Handler for wireguard client.conf download
$('.wg-client-dl').click(function(){
var req = new XMLHttpRequest();
var url = 'ajax/networking/get_wgcfg.php';
req.open('get', url, true);
req.responseType = 'blob';
req.setRequestHeader('Content-type', 'text/plain; charset=UTF-8');
req.onreadystatechange = function (event) {
if(req.readyState == 4 && req.status == 200) {
var blob = req.response;
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download = 'client.conf';
link.click();
}
}
req.send();
})
// Event listener for Bootstrap's form validation
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
//console.log(event.submitter);
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
// Static Array method
Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);
@ -356,6 +472,17 @@ function set_theme(theme) {
setCookie('theme',theme,90);
}
$(function() {
$('#night-mode').change(function() {
var state = $(this).is(':checked');
if (state == true && getCookie('theme') != 'lightsout.css') {
set_theme('lightsout.css');
} else {
set_theme('custom.php');
}
});
});
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));

505
app/lib/uploader.php Normal file
View 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);
}
}

View File

@ -0,0 +1,4 @@
# mobile data modem - ttyUSB0 device appears
SUBSYSTEM=="tty", KERNEL=="ttyUSB0", TAG+="systemd", ENV{SYSTEMD_WANTS}="start start_ppp0_device.service"

View File

@ -0,0 +1,3 @@
SUBSYSTEM=="net", ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="14db", NAME="hilink%n", TAG+="systemd", ENV{SYSTEMD_WANTS}="start start_huawei_hilink@hilink%n.service"

View File

@ -0,0 +1,505 @@
#!/bin/bash
#
# Huawei Hilink API
# =================
# - communication with Hilink devices via HTTP
# - send a standard http request with a xml formatted string to the device (default IP 192.169.8.1)
# - Howto:
# o "source" this script in your own script from the command line
# o if hilink_host ip/name differs, set "hilink_host=192.168.178.1" before calling any function
# o if the device is locked by a password, set hilink_user="admin"; hilink_password"1234secret"
# _login is called automatically
# only password type 4 is supported
# o if the SIM is requiring a PIN, set "hilink_pin=1234"
# o connect device to network: _switchMobileData ON ( or 1 )
# o disconnect device: _switchMobileData OFF ( or 0 )
# o get informations about the device: _getDeviceInformation and _getStatus and _getNetProvider
# all functions return XML formatted data in $response.
# o _getAllInformations: returns all available informations as key/value pairs (outputs text)
# o Check if device is connected: "if _isConnected; then .... fi"
# o $response can be parsed by calling _valueFromResponse
# e.g "_valueFromResponse msisdn" to get the phone number after a call to _getDeviceInformation
#
#
# Usage of functions
# - call the function with parameters (if required)
# - return code: 0 - success; 1 - failed
# - $status: status information (OK, ERROR)
# - $response: xml response to be parsed for the required information
#
#
# required software: curl, base64, sha256sum, sed
#
# ToDo: improve error handling
#
# zbchristian 2021
#
# Initialization procedure
# ========================
#
# hilink_host=192.168.8.1 # ip address of device
# hilink_user="admin" # user name if locked (default admin)
# hilink_password="1234Secret" # password if locked
# hilink_pin="1234" # PIN of SIM
# _initHilinkAPI # initialize the API
#
# Termination
# ===========
# cleanup the API before quitting the shell
# _closeHilinkAPI (optional: add parameter "save" to save the session/token data for subsequent calls. Valid for a few minutes.)
#
# BE AWARE, THAT THE API USES SOME GLOBAL VARIABLES : hilink_host, user, password, pin, response, status
# USE THESE ONLY TO COMMUNICATE WITH THE API.
# DO NOT USE THE VARIABLE PRE_FIX "hilink_" FOR YOUR OWN VARIABLES
#
hilink_host_default="192.168.8.1"
hilink_save_file="/tmp/hilink_api_saved.dat"
hilink_save_age=60
hilink_header_file="/tmp/hilink_login_hdr.txt"
# initialize
function _initHilinkAPI() {
local age
if [ -z "$hilink_host" ]; then hilink_host=$hilink_host_default; fi
if ! _hostReachable; then return 1; fi
if [ -f $hilink_save_file ]; then # found file with saved data
_getSavedData
age=$(( $(date +%s) - $(stat $hilink_save_file -c %Y) ))
if [[ $age -gt $hilink_save_age ]]; then
rm -f $hilink_save_file
_logout
_sessToken
fi
fi
if [ -z "$hilink_sessID" ] || [ -z "$hilink_token" ]; then _sessToken; fi
_login
return $?
}
function _getSavedData() {
local dat
if [ -f $hilink_save_file ]; then # restore saved session data
dat=$(cat $hilink_save_file)
hilink_sessID=$(echo "$dat" | sed -nr 's/sessionid: ([a-z0-9]*)/\1/ip')
hilink_token=$(echo "$dat" | sed -nr 's/token: ([a-z0-9]*)/\1/ip')
hilink_tokenlist=( $(echo "$dat" | sed -nr 's/tokenlist: ([a-z0-9 ]*)/\1/ip') )
fi
}
# Cleanup
# parameter: "save" - will store sessionid and tokens in file
function _closeHilinkAPI() {
local opt
if [ -z "$hilink_host" ]; then hilink_host=$hilink_host_default; fi
if ! _hostReachable; then return 1; fi
rm -f $hilink_save_file
[ ! -z "$1" ] && opt="${1,,}"
if [ ! -z "$opt" ] && [ "$opt" = "save" ]; then
echo "sessionid: $hilink_sessID" > $hilink_save_file
echo "token: $hilink_token" >> $hilink_save_file
echo "tokenlist: ${hilink_tokenlist[@]}" >> $hilink_save_file
fi
_logout
hilink_tokenlist=""
hilink_sessID=""
hilink_token=""
return 0
}
# get status (connection status, DNS, )
# parameter: none
function _getStatus() {
if _login; then
if _sendRequest "api/monitoring/status"; then
if [ ! -z "$1" ]; then _valueFromResponse "$1"; fi
fi
return $?
fi
return 1
}
function _isConnected() {
local conn
conn=$(_getStatus "connectionstatus")
status="NO"
if [ ! -z "$conn" ] && [ $conn -eq 901 ]; then
status="YES"
return 0
fi
return 1
}
# get device information (device name, imei, imsi, msisdn-phone number, MAC, WAN IP ...)
# parameter: name of parameter to return
function _getDeviceInformation() {
if _login; then
if _sendRequest "api/device/information"; then
if [ ! -z "$1" ]; then _valueFromResponse "$1"; fi
fi
return $?
fi
return 1
}
# get net provider information
# parameter: name of parameter to return
function _getNetProvider() {
if _login; then
if _sendRequest "api/net/current-plmn"; then
if [ ! -z "$1" ]; then _valueFromResponse "$1"; fi
fi
return $?
fi
return 1
}
# get signal level
# parameter: name of parameter to return
function _getSignal() {
if _login; then
if _sendRequest "api/device/signal"; then
if [ ! -z "$1" ]; then _valueFromResponse "$1"; fi
fi
return $?
fi
return 1
}
function _getAllInformations() {
if _getDeviceInformation; then _keyValuePairs; fi
if _getSignal; then _keyValuePairs; fi
if _getNetProvider; then _keyValuePairs; fi
}
# get status of mobile data connection
# parameter: none
function _getMobileDataStatus() {
if _login; then
if _sendRequest "api/dialup/mobile-dataswitch"; then
status=$(_valueFromResponse "dataswitch")
if [ $? -eq 0 ] && [ ! -z "$status" ]; then echo "$status"; fi
fi
return $?
fi
return 1
}
# PIN of SIM can be passed either as $hilink_pin, or as parameter
# parameter: PIN number of SIM card
function _enableSIM() {
#SimState:
#255 - no SIM,
#256 - error CPIN,
#257 - ready,
#258 - PIN disabled,
#259 - check PIN,
#260 - PIN required,
#261 - PUK required
local simstate
if [ ! -z "$1" ]; then hilink_pin="$1"; fi
if ! _login; then return 1; fi
if _sendRequest "api/pin/status"; then
simstate=$(echo $response | sed -rn 's/.*<simstate>([0-9]*)<\/simstate>.*/\1/pi')
if [[ $simstate -eq 257 ]]; then status="SIM ready"; return 0; fi
if [[ $simstate -eq 260 ]]; then
status="PIN required"
if [ ! -z "$hilink_pin" ]; then _setPIN "$hilink_pin"; fi
return $?
fi
if [[ $simstate -eq 255 ]]; then status="NO SIM"; return 1; fi
fi
return 1
}
# obtain session and verification token - stored in vars $hilink_sessID and $token
# parameter: none
function _sessToken() {
hilink_tokenlist=""
hilink_token=""
hilink_sessID=""
response=$(curl -s http://$hilink_host/api/webserver/SesTokInfo -m 5 2> /dev/null)
if [ -z "$response" ]; then echo "No access to device at $hilink_host"; return 1; fi
status=$(echo "$response" | sed -nr 's/.*<code>([0-9]*)<\/code>.*/\1/ip')
if [ -z "$status" ]; then
hilink_token=$(echo $response | sed -r 's/.*<TokInfo>(.*)<\/TokInfo>.*/\1/')
hilink_sessID=$(echo $response | sed -r 's/.*<SesInfo>(.*)<\/SesInfo>.*/\1/')
if [ ! -z "$hilink_sessID" ] && [ ! -z "$hilink_token" ]; then
hilink_sessID="SessionID=$hilink_sessID"
return 0
fi
fi
return 1
}
# unlock device (if locked) with user name and password
# requires stored hilink_user="admin"; hilink_password"1234secret";hilink_host=$hilink_host_default
# parameter: none
function _login() {
local ret encpw pwtype pwtype3 hashedpw pwtype4
if _loginState; then return 0; fi # login not required, or already done
_sessToken
# get password type
if ! _sendRequest "api/user/state-login"; then return 1; fi
pwtype=$(echo "$response" | sed -rn 's/.*<password_type>([0-9])<\/password_type>.*/\1/pi')
if [ -z "$pwtype" ];then pwtype=4; fi # fallback is type 4
ret=1
if [[ ! -z "$hilink_user" ]] && [[ ! -z "$hilink_password" ]]; then
# password encoding
# type 3 : base64(pw) encoded
# type 4 : base64(sha256sum(user + base64(sha256sum(pw)) + token))
pwtype3=$(echo -n "$hilink_password" | base64 --wrap=0)
hashedpw=$(echo -n "$hilink_password" | sha256sum -b | sed -nr 's/^([0-9a-z]*).*$/\1/ip' )
hashedpw=$(echo -n "$hashedpw" | base64 --wrap=0)
pwtype4=$(echo -n "$hilink_user$hashedpw$hilink_token" | sha256sum -b | sed -nr 's/^([0-9a-z]*).*$/\1/ip' )
encpw=$(echo -n "$pwtype4" | base64 --wrap=0)
if [ $pwtype -ne 4 ]; then encpw=$pwtype3; fi
hilink_xmldata="<?xml version='1.0' encoding='UTF-8'?><request><Username>$hilink_user</Username><Password>$encpw</Password><password_type>$pwtype</password_type></request>"
hilink_xtraopts="--dump-header $hilink_header_file"
rm -f $hilink_header_file
_sendRequest "api/user/login"
if [ ! -z "$status" ] && [ "$status" = "OK" ]; then
# store the list of 30 tokens. Each token is valid for a single request
hilink_tokenlist=( $(cat $hilink_header_file | sed -rn 's/^__RequestVerificationToken:\s*([0-9a-z#]*).*$/\1/pi' | sed 's/#/ /g') )
_getToken
hilink_sessID=$(cat $hilink_header_file | grep -ioP 'SessionID=([a-z0-9]*)')
if [ ! -z "$hilink_sessID" ] && [ ! -z "$hilink_token" ]; then ret=0; fi
fi
rm -f $hilink_header_file
fi
return $ret
}
# logout of hilink device
# parameter: none
function _logout() {
if _loginState; then
hilink_xmldata="<?xml version: '1.0' encoding='UTF-8'?><request><Logout>1</Logout></request>"
if _sendRequest "api/user/logout"; then
hilink_tokenlist=""
hilink_sessID=""
hilink_token=""
hilink_login_enabled=""
fi
return $?
fi
return 1
}
# parameter: none
function _loginState() {
local state
status="OK"
if [ -z "$hilink_login_enabled" ]; then _checkLoginEnabled; fi
if [ $hilink_login_enabled -eq 1 ]; then return 0; fi # login is disabled
_sendRequest "api/user/state-login"
state=`echo "$response" | sed -rn 's/.*<state>(.*)<\/state>.*/\1/pi'`
if [ ! -z "$state" ] && [ $state -eq 0 ]; then # already logged in
return 0
fi
return 1
}
function _checkLoginEnabled() {
local state
if _sendRequest "api/user/hilink_login"; then
hilink_login_enabled=0
state=$(echo $response | sed -rn 's/.*<hilink_login>(.*)<\/hilink_login>.*/\1/pi')
if [ ! -z "$state" ] && [ $state -eq 0 ]; then # no login enabled
hilink_login_enabled=1
fi
else
hilink_login_enabled=""
fi
}
# switch mobile data on/off 1/0
# if SIM is locked, $hilink_pin has to be set
# parameter: state - ON/OFF or 1/0
function _switchMobileData() {
local mode
if [ -z "$1" ]; then return 1; fi
_login
mode="${1,,}"
[ "$mode" = "on" ] && mode=1
[ "$mode" = "off" ] && mode=0
if [[ $mode -ge 0 ]]; then
if _enableSIM "$hilink_pin"; then
hilink_xmldata="<?xml version: '1.0' encoding='UTF-8'?><request><dataswitch>$mode</dataswitch></request>"
_sendRequest "api/dialup/mobile-dataswitch"
return $?
fi
fi
return 1
}
# parameter: PIN of SIM card
function _setPIN() {
local pin
if [ -z "$1" ]; then return 1; fi
pin="$1"
hilink_xmldata="<?xml version: '1.0' encoding='UTF-8'?><request><OperateType>0</OperateType><CurrentPin>$pin</CurrentPin><NewPin></NewPin><PukCode></PukCode></request>"
_sendRequest "api/pin/operate"
return $?
}
# Send request to host at http://$hilink_host/$apiurl
# data in $hilink_xmldata and options in $hilink_xtraopts
# parameter: apiurl (e.g. "api/user/login")
function _sendRequest() {
local ret apiurl
status="ERROR"
if [ -z "$1" ]; then return 1; fi
apiurl="$1"
ret=1
if [ -z "$hilink_sessID" ] || [ -z "$hilink_token" ]; then _sessToken; fi
if [ -z "$hilink_xmldata" ];then
response=$(curl -s http://$hilink_host/$apiurl -m 10 \
-H "Cookie: $hilink_sessID")
else
response=$(curl -s -X POST http://$hilink_host/$apiurl -m 10 \
-H "Content-Type: text/xml" \
-H "Cookie: $hilink_sessID" \
-H "__RequestVerificationToken: $hilink_token" \
-d "$hilink_xmldata" $hilink_xtraopts 2> /dev/null)
_getToken
fi
if [ ! -z "$response" ];then
response=$(echo $response | tr -d '\012\015') # delete newline chars
status=$(echo "$response" | sed -nr 's/.*<code>([0-9]*)<\/code>.*/\1/ip') # check for error code
if [ -z "$status" ]; then
status="OK"
response=$(echo "$response" | sed -nr 's/.*<response>(.*)<\/response>.*/\1/ip')
[ -z "$response" ] && response="none"
ret=0
else
status="ERROR $status"
fi
else
status="ERROR"
fi
if [[ "$status" =~ ERROR ]]; then _handleError; fi
hilink_xtraopts=""
hilink_xmldata=""
return $ret
}
# handle the list of tokens available after login
# parameter: none
function _getToken() {
if [ ! -z "$hilink_tokenlist" ] && [ ${#hilink_tokenlist[@]} -gt 0 ]; then
hilink_token=${hilink_tokenlist[0]} # get first token in list
hilink_tokenlist=("${hilink_tokenlist[@]:1}") # remove used token from list
if [ ${#hilink_tokenlist[@]} -eq 0 ]; then
_logout # use the last token to logout
fi
else
_sessToken # old token has been used - need new session
fi
}
# Analyse $status for error code
# return error text in $status
function _handleError() {
local ret txt
txt=$(_getErrorText)
if [ -z "$code" ]; then return 1; fi
ret=0
case "$code" in
101|108003|108007)
ret=1
status="$txt"
;;
108001|108002|108006)
ret=1
status="$txt"
;;
125001|125002|125003)
_sessToken
ret=0
;;
*)
;;
esac
return "$ret"
}
declare -A hilink_err_api
hilink_err_api[101]="Unable to get session ID/token"
hilink_err_api[108001]="Invalid username/password"
hilink_err_api[108002]=${hilink_err_api[108001]}
hilink_err_api[108006]=${hilink_err_api[108001]}
hilink_err_api[108003]="User already logged in - need to wait a bit"
hilink_err_api[108007]="Too many login attempts - need to wait a bit"
hilink_err_api[125001]="Invalid session/request token"
hilink_err_api[125002]=${hilink_err_api[125001]}
hilink_err_api[125003]=${hilink_err_api[125001]}
# check error and return error text
# status passsed in $status, or $1
function _getErrorText() {
local err code errortext
err="$status"
code="0"
if [ ! -z "$1" ]; then err="$1"; fi
if [ -z "$err" ]; then return 1; fi
errortext="$err"
if [[ "$err" =~ ERROR\ *([0-9]*) ]] && [ ! -z "${BASH_REMATCH[1]}" ]; then
code=${BASH_REMATCH[1]}
if [ ! -z "$code" ] && [ ! -z "${hilink_err_api[$code]}" ]; then
errortext="${hilink_err_api[$code]}"
fi
fi
echo $errortext
return 0
}
function _hostReachable() {
local avail
avail=$( timeout 0.5 ping -c 1 $hilink_host | sed -rn 's/.*time=.*/1/p' )
if [ -z "$avail" ]; then status="ERROR: Not reachable"; return 1; fi
status="OK"
return 0;
}
# helper function to parse $response (xml format) for a value
# call another function first!
# parameter: tag-name
function _valueFromResponse() {
local par value
if [ -z "$response" ] || [ -z "$1" ]; then return 1; fi
par="$1"
value=$(echo $response | sed -rn 's/.*<'$par'>(.*)<\/'$par'>.*/\1/pi')
if [ -z "$value" ]; then return 1; fi
echo "$value"
return 0
}
# list all keys of the current xml response
function _keysFromResponse() {
if [ -z "$response" ]; then return 1; fi
echo $response | grep -oiP "(?<=<)[a-z_-]*(?=>)"
return 0
}
# return all key=value pairs of the current xml response
function _keyValuePairs() {
if [ -z "$response" ]; then return 1; fi
echo $response | sed -n 's/<\([^>]*\)>\(.*\)<\/\1>[^<]*/\1=\"\2\"\n/gpi'
return 0
}
hilink_token=""
hilink_tokenlist=""
hilink_sessID=""
hilink_xmldata=""
hilink_xtraopts=""
hilink_host=$hilink_host_default
hilink_user="admin"
hilink_password=""
hilink_pin=""
response=""
status=""

View File

@ -0,0 +1,109 @@
#!/bin/bash
# get info about device and signal of Huawei mobile USB devices
# parm:
# $1 : requested information (manufacturer, device, imei, imsi, telnumber, ipaddress, mode, signal, operator)
# $2 : (optional) type - hilink or modem (default: hilink)
# $3 : (optional) for hilink: ip address of the device (default: 192.168.8.1)
# for modem: tty interface for communication (default: /dev/ttypUSB2)
# $4 : more options can be added for Hilink devices ('-u user -P password -p pin'). These are passed to the corresponding script
#
# requires: bc
# calls the scripts info_huawei_hilink.sh and info_huawei_modem.sh (same path as this script)
#
# zbchristian 2020
#
path=$(dirname "$0")
opt="device"
if [ ! -z "$1" ]; then opt=${1,,}; fi
type="hilink"
if [ ! -z "$2" ]; then type=${2,,}; fi
parms=""
if [ "$type" = "hilink" ]; then
connect="-h 192.168.8.1"
if [ ! -z "$3" ]; then connect="-h $3"; fi
if [ ! -z "$4" ]; then parms="$4"; fi
script="$path/info_huawei_hilink.sh"
else
connect="/dev/ttyUSB2"
if [ ! -z "$3" ]; then connect=$3; fi
script="$path/info_huawei_modem.sh"
fi
res=$($script $opt $connect $parms)
# some results require special treatment
case $opt in
# manufacturer)
# if [ "$res" = "none" ]; then res="Huawei"; fi
# ;;
# device)
# if [ ! "$res" = "none" ]; then res="Huawei $res";
# else res="Huawei"; fi
# ;;
mode)
if [ ! "$res" = "none" ]; then
if [ "$type" = "hilink" ]; then
if [ "$res" = "LTE" ]; then res="4G"
elif [ "$res" = "WCDMA" ]; then res="3G";
else res="2G"; fi
else
if [ $res -eq 7 ]; then res="4G"
elif [ $res -lt 7 ] && [ $res -gt 2 ] ; then res="3G";
else res="2G"; fi
fi
fi
;;
signal)
# return signal strength/quality in %
if [ "$type" = "hilink" ]; then
# signal request tries to get RSRQ value
# try to get RSRQ (4G), EC/IO (3G) or RSSI (2G) value
if [ "$res" = "none" ]; then res=$($script "ecio"); fi
if [ ! "$res" = "none" ]; then
# for rsrq and ecio assume: -3dB (100%) downto -20dB (0%)
qual=${res//dB/}
if [[ ! "$qual" =~ [-0-9\.]* ]]; then qual=-100; fi
qual=$(bc <<< "scale=0;res=$qual-0.5;res/1") # just round to next integer
if [ $qual -le -20 ]; then qual=0;
elif [ $qual -ge -3 ]; then qual=100;
else qual=$(bc <<< "scale=0;res=100.0/17.0*$qual+2000.0/17.0;res/1"); fi
else
# try rssi: >-70dBm (100%) downto -100dBm (0%)
res=$($script "rssi");
if [ ! "$res" = "none" ]; then
if [[ ! $res =~ [-0-9\.]* ]]; then res="-120 dBm"; fi
qual=${res//dBm/}
qual=$(bc <<< "scale=0;res=$qual+0.5;res/1") # just round to next integer
if [ $qual -le -110 ]; then qual=0;
elif [ $qual -ge -70 ]; then qual=100;
else qual=$(bc <<< "scale=0;res=2.5*$qual+275;res/1"); fi
fi
fi
else
# modem returns RSSI as number 0-31 - 0 = -113dB (0%), 1 = -111dB, 31 = >=51dB (100%)
qual=$(bc <<< "scale=0;res=$res*3.5+0.5;res/1")
if [ $qual -gt 100 ]; then res=100; fi
fi
if [ ! "$res" = "none" ]; then res="$res (${qual}%)"; fi
;;
operator)
# check if operator/network is just a 5 digit number -> extract network name from table
if [[ $res =~ ^[0-9]{5}$ ]]; then
mcc=${res:0:3}
mnc=${res:3:2}
op=$(cat $path/mcc-mnc-table.csv | sed -rn 's/^'$mcc'\,[0-9]*\,'$mnc'\,(.*\,){4}(.*)$/\2/p')
if [ ! -z "$op" ]; then res="$op ($res)"; fi
fi
;;
*)
;;
esac
echo $res

View File

@ -0,0 +1,95 @@
#!/bin/bash
# Information about HUAWEI hilink
# -------------------------------
# get info about the device and signal
# parameter: $1 - "connected", "device", "ipaddress", "mode", "signal" (see case statement below)
# -u,--user - username
# -P,--password - password
# -p,--pin - SIM pin
# -h,--host - host ip address for API calls (optional)
# returns the value of the parameter, or "none" if not found or empty
#
# All device informations are buffered for 5 secs to speed up subsequent calls
#
# zbchristian 2021
function _setAPIParams() {
if [ ! -z "$hostip" ]; then hilink_host="$hostip"; fi
if [ ! -z "$username" ]; then hilink_user="$username"; fi
if [ ! -z "$password" ]; then hilink_password="$password"; fi
if [ ! -z "$simpin" ]; then hilink_pin="$simpin"; fi
}
if [ -z "$1" ]; then echo "none"; exit; fi
property="${1,,}"
shift
hostip="192.168.8.1"
while [ -n "$1" ]; do
case "$1" in
-u|--user) username="$2"; shift ;;
-P|--password) password="$2"; shift ;;
-p|--pin) simpin="$2"; shift ;;
-h|--host) hostip="$2"; shift ;;
esac
shift
done
status="no valid option given"
result="none"
hostip="192.168.8.1"
if [ "$opt" = "connected" ]; then
source /usr/local/sbin/huawei_hilink_api.sh
_setAPIParams
if ! _initHilinkAPI; then echo "none"; exit; fi
result=$(_getMobileDataStatus)
_closeHilinkAPI
else
info_file="/tmp/huawei_infos_${hostip}_$(id -u).dat"
if [ -f "$info_file" ]; then
age=$(( $(date +%s) - $(stat $info_file -c %Y) ))
if [[ $age -gt 10 ]]; then rm -f $info_file; fi
fi
if [ -f "$info_file" ]; then
infos=$(cat $info_file)
else
source /usr/local/sbin/huawei_hilink_api.sh
_setAPIParams
if ! _initHilinkAPI; then echo "none"; exit; fi
infos=$(_getAllInformations)
_closeHilinkAPI
if [ ! -z "$infos" ]; then echo -n "$infos" > $info_file; fi
fi
case "$property" in
device|devicename)
key="devicename"
;;
ipaddress|wanipaddress)
key="wanipaddress"
;;
mode)
key="workmode"
;;
telnumber)
key="msisdn"
;;
imei|imsi|rssi|rsrq|rsrp|sinr|ecio)
key="$property"
;;
signal)
key="rsrq"
;;
operator|fullname)
key="fullname"
;;
*)
key="device"
;;
esac
if [ -z "$key" ]; then result="none"; fi
result=$(echo "$infos" | sed -rn 's/'$key'=\"([^ \s]*)\"/\1/ip')
if [ -z "$result" ]; then result="none"; fi
fi
echo -n "$result"

View File

@ -0,0 +1,52 @@
#!/bin/bash
# Information about HUAWEI modem - via AT commands
# ------------------------------------------------
# get info about the device and signal
# parameter: $1 - see opts list below
# $2 - tty device name for the communicaton (optional)
# returns the value of the parameter, or "none" if not found or empty
#
# requires: socat
#
# zbchristian 2020
opts=("manufacturer" "device" "imei" "imsi" "telnumber" "mode" "signal" "operator")
# at command to extract information
atcmds=("AT+CGMI" "AT+CGMM" "AT+CGSN" "AT+CIMI" "AT+CNUM" "AT+COPS?" "AT+CSQ" "AT+COPS?")
# regexp pattern to extract wanted information from result string
pats=( " " " " " " " " ".*\,\"([0-9\+]*)\".*" '.*\,([0-9])$' ".*: ([0-9]*).*" '.*\,\"([^ ]*)\".*$')
# tty device for communication - usually 3 tty devices are created and the 3rd ttyUSB2 is available, even, when the device is connected
dev="/dev/ttyUSB2"
atsilent="AT^CURC=0"
if [ ! -z $2 ]; then dev=$2; fi
idx=-1
opt=${opts[0]}
if [ ! -z $1 ]; then opt=$1; fi
for i in "${!opts[@]}"; do
if [[ ${opts[$i]} == $opt ]]; then idx=$i; fi
done
if [[ $idx == -1 ]];then echo "none"; exit; fi
atcmd=${atcmds[$idx]}
pat=${pats[$idx]}
result=`(echo $atsilent; echo $atcmd) | sudo /usr/bin/socat - $dev`
# escape the AT command to be used in the regexp
atesc=${atcmd//[\+]/\\+}
atesc=${atesc//[\?]/\\?}
result=`echo $result | sed -rn 's/.*'"$atesc"'\s([^ ]+|[^ ]+ [^ ]+)\sOK.*$/\1/pg'`
if [[ $pat != " " ]]; then
result=`echo $result | sed -rn 's/'"$pat"'/\1/pg'`
fi
if [ -z "$result" ]; then result="none"; fi
echo $result

View File

@ -0,0 +1,13 @@
# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto ppp0
iface ppp0 inet wvdial
provider connect
pre-up /usr/local/sbin/ppp0_setpin.sh
up /usr/local/sbin/ppp0_route.sh

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
#!/bin/bash
# connect/disconnect Huawei mobile data stick in Hilink mode (e.g. E3372h)
# ========================================================================
#
# options: -u, --user - user name (default "admin")
# -P, --password - password
# -h, --host - host ip address (default 192.168.8.1)
# -d, --devname - device name (IP is extracted using default route)
# -p, --pin - PIN of SIM card
# -c, --connect - connect 0/1 to set datamode off/on
#
# required software: curl, base64, sha256sum
#
# zbchristian 2021
# include the hilink API (defaults: hilink_user=admin, hilink_host=192.168.8.1)
source /usr/local/sbin/huawei_hilink_api.sh
# include the raspap helper functions
source /usr/local/sbin/raspap_helpers.sh
datamode=""
devname=""
while [ -n "$1" ]; do
case "$1" in
-u|--user) hilink_user="$2"; shift ;;
-P|--password) hilink_password="$2"; shift ;;
-p|--pin) if [[ $2 =~ ^[0-9]{4,8} ]]; then hilink_pin="$2"; fi; shift ;;
-h|--host) hilink_host="$2"; shift ;;
-d|--devname) devname="$2"; shift ;;
-c|--connect) if [ "$2" = "1" ]; then datamode=1; else datamode=0; fi; shift ;;
esac
shift
done
if [ ! -z "$devname" ]; then # get host IP for given device name
gw=$(ip route list | sed -rn "s/default via (([0-9]{1,3}\.){3}[0-9]{1,3}).*dev $devname.*/\1/p")
if [ -z "$gw" ]; then exit; fi # device name not found in routing list -> abort
hilink_host="$gw"
fi
if [ -z "$hilink_password" ] || [ -z "$hilink_pin" ]; then
_getAuthRouter
if [ ! -z "$raspap_user" ]; then hilink_user="$raspap_user"; fi
if [ ! -z "$raspap_password" ]; then hilink_password="$raspap_password"; fi
if [ ! -z "$raspap_pin" ]; then hilink_pin="$raspap_pin"; fi
fi
echo "Hilink: switch device at $hilink_host to mode $datamode" | systemd-cat
status="usage: -c 1/0 to disconnect/connect"
if [ -z "$datamode" ] || [ ! _initHilinkAPI ]; then echo "Hilink: failed - return status: $status"; exit; fi
if ! _switchMobileData "$datamode"; then echo -n "Hilink: could not switch the data mode on/off . Error: ";_getErrorText; fi
if ! _closeHilinkAPI; then echo -n "Hilink: failed - return status: $status . Error: ";_getErrorText; fi

View File

@ -0,0 +1,21 @@
#!/bin/bash
#
# get gateway and ip address of UTMS modem connected to ppp0
# add a default route
# called by /etc/network/interfaces.d/ppp0, when device is coming up
#
ppp0rt=""
let i=1
while [ -z "$ppp0rt" ] ; do
let i+=1
if [ $i -gt 20 ]; then
exit 1
fi
sleep 1
ppp0rt=`ip route list | grep -m 1 ppp0`
done
gate=`echo $ppp0rt | sed -rn 's/(([0-9]{1,3}\.){3}[0-9]{1,3}).*ppp0.*src (([0-9]{1,3}\.){3}[0-9]{1,3})/\1/p'`
src=`echo $ppp0rt | sed -rn 's/(([0-9]{1,3}\.){3}[0-9]{1,3}).*ppp0.*src (([0-9]{1,3}\.){3}[0-9]{1,3})/\3/p'`
ip route add default via $gate proto dhcp src $src metric 10
exit 0

View File

@ -0,0 +1,21 @@
#!/bin/bash
# in case /dev/ttyUSB0 does not exist, wait for it at most 30 seconds
let i=1
while ! test -c /dev/ttyUSB0; do
let i+=1
if [ $i -gt 2 ]; then
logger -s -t setpin "/dev/ttyUSB0 does not exist"
exit 3
fi
logger -s -t setpin "waiting 3 seconds for /dev/ttyUSB0"
sleep 3
done
# check for pin and set it if necessary
wvdial pinstatus 2>&1 | grep -q '^+CPIN: READY'
if [ $? -eq 0 ]; then
logger -s -t setpin "SIM card is ready to use :-)"
else
logger -s -t setpin "setting PIN"
wvdial pin 2>/dev/null
fi
exit 0

View File

@ -0,0 +1,51 @@
#!/bin/bash
#
# Helper functions to extract informations from RaspAP config/settings
#
# zbchristian 2021
#
# get the values of a RaspAP config variable
# call: _getRaspapConfig RASPAP_MOBILEDATA_CONFIG
raspap_webroot="/var/www/html"
function _getWebRoot() {
local path
path=$(cat /etc/lighttpd/lighttpd.conf | sed -rn "s/server.document-root \s*= \"([^ \s]*)\"/\1/p")
if [ ! -z "$path" ]; then raspap_webroot="$path"; fi
if [ -z "$path" ]; then return 1; else return 0; fi
}
# expand an RaspAP config variable utilizing PHP
function _getRaspapConfig() {
local conf var
raspap_config=""
var="$1"
if [ ! -z "$var" ]; then
if ! _getWebRoot; then return 1; fi
conf="$raspap_webroot/includes/config.php"
if [ -f "$conf" ]; then
conf=$(php -r 'include "'$conf'"; echo '$var';' 2> /dev/null)
if [ ! -z "$conf" ] && [ -d ${conf%/*} ]; then raspap_config="$conf"; fi
fi
fi
if [ -z "$raspap_config" ]; then return 1; else return 0; fi
}
# Username and password for mobile data devices is stored in a file (RASPAP_MOBILEDATA_CONFIG)
function _getAuthRouter() {
local mfile mdata pin user pw
if ! _getRaspapConfig "RASPI_MOBILEDATA_CONFIG"; then return 1; fi
mfile="$raspap_config"
if [ -f $mfile ]; then
mdata=$(cat "$mfile")
pin=$(echo "$mdata" | sed -rn 's/pin = ([^ \s]*)/\1/ip')
if [ ! -z "$pin" ]; then raspap_pin="$pin"; fi
user=$(echo "$mdata" | sed -rn 's/router_user = ([^ \s]*)/\1/ip')
if [ ! -z "$user" ]; then raspap_user="$user"; fi
pw=$(echo "$mdata" | sed -rn 's/router_pw = ([^ \s]*)/\1/ip')
if [ ! -z "$pw" ]; then raspap_password="$pw"; fi
return 0
fi
return 1
}

View File

@ -0,0 +1,13 @@
[Unit]
Description=Bring up HUAWEI mobile hilink device
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/bin/sleep 15
ExecStart=/usr/local/sbin/onoff_huawei_hilink.sh -c 1 -d %i
[Install]
Alias=start_ltemodem.service
WantedBy=multi-user.target

View File

@ -0,0 +1,16 @@
[Unit]
Description=Start ppp0 interface
BindsTo=dev-ttyUSB0.device
After=dev-ttyUSB0.device
[Service]
Type=forking
RemainAfterExit=yes
ExecStart=/sbin/ifup ppp0
ExecStop=/sbin/ifdown ppp0
[Install]
Alias=startppp0.service
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
[Dialer Defaults]
Modem Type = Analog Modem
ISDN = 0
Baud = 9600
Modem = /dev/ttyUSB0
[Dialer pin]
Init1 = AT+CPIN="XXXX"
[Dialer connect]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,"IP","web.vodafone.de"
New PPPD = yes
Phone = *99#
Password = me
Username = vodafone
Stupid Mode = 1
[Dialer pinstatus]
Init1 = AT+CPIN?

View File

@ -0,0 +1,64 @@
{
"info": "UDEV rules for different client types. $...$ expressions will be replaces automatically ($MAC$, $IDVENDOR$, $IDPRODUCT$, $DEVNAME$)",
"udev_rules_file": "/etc/udev/rules.d/80-raspap-net-devices.rules",
"script_path": "/usr/local/sbin",
"network_devices": [
{
"type": "eth",
"type_info": "ethernet port",
"clientid": 0,
"comment": "standard ethernet port",
"name_prefix": "eth",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"$MAC$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"eth\" "
},
{
"type": "usb",
"type_info": "usb network interface",
"clientid": 1,
"comment": "network interface - e.g. USB tethering of an Android phone ",
"name_prefix": "usb",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"eth\" "
},
{
"type": "wlan",
"type_info": "wireless adapter",
"clientid": 2,
"comment": "standard wireless interface",
"name_prefix": "wlan",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"$MAC$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"wlan\" "
},
{
"type": "ppp",
"type_info": "mobile data modem",
"clientid": 3,
"name_prefix": "ppp",
"comment": "recognized mobile data modems are automatically named as ppp0-9. Renaming is not possible. Dialin service relies on the name",
"udev_rule": "SUBSYSTEM==\"tty\", KERNEL==\"ttyUSB0\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"start start_ppp0_device.service\" "
},
{
"type": "hilink",
"type_info": "Huawei Hilink",
"clientid": 4,
"comment": "Huawei mobile data device in router mode. Control via HTTP. Device is connecting via service",
"name_prefix": "hilink",
"default_ip": "192.168.8.1",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"hilink\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"start start_huawei_hilink@hilink%n.service\" "
},
{
"type": "phone",
"type_info": "USB tethered phone",
"clientid": 5,
"comment": "ethernet access provided by tethering from phone via USB",
"name_prefix": "phone",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"phone\" "
},
{
"type": "tun",
"type_info": "tunnel device",
"clientid": -1,
"comment": "tunneling device used by OpenVPN",
"name_prefix": "tun"
}
]
}

View File

@ -19,9 +19,11 @@ define('RASPI_DHCPCD_LOG', '/var/log/dnsmasq.log');
define('RASPI_WPA_SUPPLICANT_CONFIG', '/etc/wpa_supplicant/wpa_supplicant.conf');
define('RASPI_HOSTAPD_CTRL_INTERFACE', '/var/run/hostapd');
define('RASPI_WPA_CTRL_INTERFACE', '/var/run/wpa_supplicant');
define('RASPI_OPENVPN_CLIENT_PATH', '/etc/openvpn/client/');
define('RASPI_OPENVPN_CLIENT_CONFIG', '/etc/openvpn/client/client.conf');
define('RASPI_OPENVPN_CLIENT_LOGIN', '/etc/openvpn/client/login.conf');
define('RASPI_OPENVPN_SERVER_CONFIG', '/etc/openvpn/server/server.conf');
define('RASPI_WIREGUARD_PATH', '/etc/wireguard/');
define('RASPI_WIREGUARD_CONFIG', RASPI_WIREGUARD_PATH.'wg0.conf');
define('RASPI_TORPROXY_CONFIG', '/etc/tor/torrc');
define('RASPI_LIGHTTPD_CONFIG', '/etc/lighttpd/lighttpd.conf');
define('RASPI_ACCESS_CHECK_IP', '1.1.1.1');

View File

@ -33,6 +33,25 @@
"uap0": {
"dhcp-range": [ "192.168.50.50,192.168.50.150,12h" ]
}
},
"wireguard": {
"server": {
"Address": [ "10.8.2.1/24" ],
"ListenPort": [ "51820" ],
"DNS": [ "9.9.9.9" ],
"PostUp": [ "iptables -A FORWARD -i wlan0 -o wg0 -j ACCEPT; iptables -A FORWARD -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE" ],
"PostDown": [ "iptables -D FORWARD -i wlan0 -o wg0 -j ACCEPT; iptables -D FORWARD -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE" ]
},
"peer": {
"Address": [ "10.8.1.2/24" ],
"Endpoint": [ "10.8.2.1:51820" ],
"ListenPort": [ "21841" ],
"AllowedIPs": ["10.8.2.0/24"],
"PersistentKeepalive": [ "15" ]
}
},
"txpower": {
"dbm": [ "auto", "30", "20", "17", "10", "6", "3", "1", "0" ]
}
}

205
config/iptables_rules.json Normal file
View File

@ -0,0 +1,205 @@
{
"info": "IPTABLES rules. $...$ expressions will be replaces automatically ($INTERFACE$, $PORT$, $IPADDRESS$)",
"rules_v4_file": "/etc/iptables/rules.v4",
"rules_v6_file": "/etc/iptables/rules.v6",
"order": [ "pre_rules", "restriction_rules", "main_rules", "exception_rules" ],
"pre_rules": [
{
"name": "firewall policies",
"fw-state": true,
"comment": "Policy rules (firewall)",
"rules": [
"-P INPUT DROP",
"-P FORWARD ACCEPT",
"-P OUTPUT ACCEPT",
"-t nat -P PREROUTING ACCEPT",
"-t nat -P POSTROUTING ACCEPT",
"-t nat -P INPUT ACCEPT",
"-t nat -P OUTPUT ACCEPT"
]
},
{
"name": "policies",
"fw-state": false,
"comment": "Policy rules",
"rules": [
"-P INPUT ACCEPT",
"-P FORWARD ACCEPT",
"-P OUTPUT ACCEPT",
"-t nat -P PREROUTING ACCEPT",
"-t nat -P POSTROUTING ACCEPT",
"-t nat -P INPUT ACCEPT",
"-t nat -P OUTPUT ACCEPT"
]
},
{
"name": "loopback",
"fw-state": true,
"comment": "allow loopback device",
"rules": [
"-A INPUT -i lo -j ACCEPT",
"-A OUTPUT -o lo -j ACCEPT"
]
},
{
"name": "ping",
"fw-state": true,
"ip-version": 4,
"comment": "allow ping request and echo",
"rules": [
"-A INPUT -p icmp --icmp-type 8/0 -j ACCEPT",
"-A INPUT -p icmp --icmp-type 0/0 -j ACCEPT"
]
},
{
"name": "ping IPv6",
"fw-state": true,
"ip-version": 6,
"comment": "allow ping request and echo for IPv6",
"rules": [
"-A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT",
"-A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT"
]
},
{
"name": "ntp",
"fw-state": true,
"comment": "allow ntp request via udp (tcp should work w/o rule)",
"rules": [
"-A INPUT -p udp --sport 123 -j ACCEPT"
]
},
{
"name": "dns",
"fw-state": true,
"comment": "allow dns request via tcp and udp",
"rules": [
"-A INPUT -p udp -m multiport --sport 53,853 -j ACCEPT",
"-A INPUT -p tcp -m multiport --sport 53,853 -j ACCEPT"
]
}
],
"main_rules": [
{
"name": "accesspoint",
"fw-state": true,
"comment": "Access point interface by default no restrictions",
"dependson": [
{ "var": "ap-device", "type": "string", "replace": "$INTERFACE$" }
],
"rules": [
"-A INPUT -i $INTERFACE$ -j ACCEPT",
"-A OUTPUT -o $INTERFACE$ -j ACCEPT"
]
},
{
"name": "NAT for access point",
"comment": "Masquerading needed for access point",
"rules": [
"-t nat -A POSTROUTING -j MASQUERADE"
]
},
{
"name": "clients",
"fw-state": true,
"comment": "Rules for client interfaces (includes tun device)",
"rules": [
"-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT"
]
},
{
"name": "openvpn",
"comment": "Rules for tunnel device (tun)",
"ip-version": 4,
"dependson": [
{ "var": "openvpn-enable", "type": "bool" },
{ "var": "openvpn-serverip", "type": "string", "replace": "$IPADDRESS$" },
{ "var": "ap-device", "type": "string", "replace": "$INTERFACE$" }
],
"rules": [
"-A INPUT -p udp -s $IPADDRESS$ -j ACCEPT",
"-A FORWARD -i tun+ -o $INTERFACE$ -m state --state RELATED,ESTABLISHED -j ACCEPT",
"-A FORWARD -i $INTERFACE$ -o tun+ -j ACCEPT",
"-t nat -A POSTROUTING -o tun+ -j MASQUERADE"
]
},
{
"name": "wireguard",
"comment": "Rules for wireguard device (wg)",
"ip-version": 4,
"dependson": [
{ "var": "wireguard-enable", "type": "bool" },
{ "var": "wireguard-serverip", "type": "string", "replace": "$IPADDRESS$" },
{ "var": "client-device", "type": "string", "replace": "$INTERFACE$" }
],
"rules": [
"-A INPUT -p udp -s $IPADDRESS$ -j ACCEPT",
"-A FORWARD -i wg+ -j ACCEPT",
"-t nat -A POSTROUTING -o $INTERFACE$ -j MASQUERADE"
]
}
],
"exception_rules": [
{
"name": "ssh",
"fw-state": true,
"comment": "Allow ssh access to RaspAP on port 22",
"dependson": [
{ "var": "ssh-enable", "type": "bool" }
],
"rules": [
"-A INPUT -p tcp --dport 22 -j ACCEPT"
]
},
{
"name": "http",
"fw-state": true,
"comment": "Allow access to RaspAP GUI (https)",
"dependson": [
{ "var": "http-enable", "type": "bool" }
],
"rules": [
"-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT"
]
},
{
"name": "interface",
"fw-state": true,
"comment": "Exclude interface from firewall",
"dependson": [
{ "var": "excl-devices", "type": "list", "replace": "$INTERFACE$" }
],
"rules": [
"-A INPUT -i $INTERFACE$ -j ACCEPT",
"-A OUTPUT -o $INTERFACE$ -j ACCEPT"
]
},
{
"name": "ipaddress",
"fw-state": true,
"ip-version": 4,
"comment": "allow access from/to IP",
"dependson": [
{ "var": "excluded-ips", "type": "list", "replace": "$IPADDRESS$" }
],
"rules": [
"-A INPUT -s $IPADDRESS$ -j ACCEPT",
"-A INPUT -d $IPADDRESS$ -j ACCEPT"
]
}
],
"restriction_rules": [
{
"name": "ipaddress",
"fw-state": true,
"ip-version": 4,
"dependson": [
{ "var": "restricted-ips", "type": "list", "replace": "$IPADDRESS$" }
],
"comment": "Block access from IP-address",
"rules": [
"-A INPUT -s $IPADDRESS$ -j DROP"
]
}
]
}

BIN
dist/raspap/css/fonts/RaspAP.eot vendored Executable file

Binary file not shown.

12
dist/raspap/css/fonts/RaspAP.svg vendored Executable file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="RaspAP" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="wireguard" d="M1023.147 463.147c0 0 23.595 496.853-522.453 496.853-482.859 0-497.963-476.587-497.963-476.587s-70.997-547.413 509.141-547.413c556.501 0 511.275 527.147 511.275 527.147zM347.947 636.757c102.4 62.72 233.344 24.363 282.368-69.888 9.301-17.877 10.496-45.355 4.608-64.128-20.352-64.683-68.309-100.949-134.187-116.395 19.413 16.64 34.859 35.499 39.808 61.525 1.195 5.504 1.88 11.827 1.88 18.31 0 20.027-6.533 38.528-17.584 53.488l0.174-0.246c-16.797 22.874-43.588 37.556-73.809 37.556-11.257 0-22.038-2.037-31.995-5.763l0.63 0.207c-40.533-15.36-62.72-52.395-58.752-97.877 3.712-42.24 35.797-69.632 95.787-80.043-8.96-4.736-15.872-8.235-22.613-11.989-27.988-15.524-51.374-35.995-69.74-60.451l-0.404-0.562c-6.101-8.192-10.24-8.875-19.541-3.2-120.619 73.771-128.384 258.859 3.371 339.456zM257.707 180.992c-19.413-4.949-38.187-12.203-57.984-18.688 9.685 65.365 86.229 125.568 150.997 118.699-18.043-24.598-29.583-54.982-31.551-87.945l-0.022-0.46c-21.504-3.968-41.813-6.613-61.44-11.605zM669.995 819.2c19.115-0.725 38.315-0.427 57.472-0.853 5.287-0.363 10.162-1.075 14.91-2.128l-0.659 0.123c-4.574-6.938-9.348-12.986-14.582-18.599l0.076 0.082c-6.827-6.4-14.549-12.629-24.448-2.944-2.347 2.347-7.979 1.792-12.075 1.877-19.072 0.213-38.144 0.853-57.173 0.128-17.856-0.589-34.82-2.396-51.386-5.353l2.149 0.318c-3.072-0.555-7.595-10.667-6.229-14.421 3.328-8.832 8.149-18.56 15.317-24.192 26.411-20.907 54.485-39.595 81.067-60.288 25.771-20.139 49.792-42.24 64.427-72.533 19.029-39.595 19.627-81.067 11.392-122.752-13.739-69.547-48.939-127.147-105.941-169.045-22.955-16.853-51.413-26.453-77.696-38.528-23.168-10.667-46.933-19.84-70.144-30.379-41.813-19.029-65.28-64.427-58.411-111.573 6.357-43.307 44.373-79.445 87.851-86.912 52.181-8.96 106.069 25.003 118.827 78.080 14.336 59.605-18.048 112.896-78.72 129.024l-10.923 2.816c16.213 7.253 30.208 12.416 43.179 19.541q33.835 18.645 66.475 39.467c6.4 4.096 9.856 4.096 15.36-0.597 41.685-36.096 66.56-80.981 73.557-135.979 11.52-91.093-31.573-174.763-112.896-217.643-125.781-66.347-279.765 9.173-307.541 148.651-23.808 119.467 60.501 227.84 162.005 248.747 43.648 9.003 83.541 27.179 114.56 60.8 20.053 21.675 29.739 40.277 33.067 48.683 5.86 14.568 9.259 31.458 9.259 49.142 0 0.094 0 0.187 0 0.281v-0.014c-0.72 15.473-4.371 29.921-10.408 43.044l0.296-0.719c-10.581 24.149-51.2 62.549-61.227 70.656l-95.573 74.837c-3.371 2.773-7.168 2.56-15.36 2.005-9.813-0.683-34.773-2.048-45.525 0.768 8.704 6.613 32.427 16.213 42.667 23.893-30.976 20.907-66.304 13.397-98.773 19.627 7.509 13.995 44.629 35.456 65.749 37.888-1.455 13.545-3.483 25.484-6.166 37.173l0.406-2.101c-1.28 4.736-6.571 9.387-11.221 12.075-11.179 6.571-23.083 11.989-35.968 18.517 10.935 7.156 24.244 11.558 38.555 11.945l0.101 0.002c1.66 0.068 3.608 0.107 5.566 0.107 11.77 0 23.21-1.408 34.163-4.064l-0.987 0.202c23.040-5.248 41.387-1.792 59.691 13.824-14.421 5.803-28.843 11.093-42.795 17.365-16.163 7.396-29.343 14.415-42.082 22.091l1.89-1.056c36.267-5.035 71.296-18.645 108.373-13.653l0.939 5.035-86.101 20.053c51.328 4.693 99.115 5.461 144.384-16.555 12.757-6.229 26.027-11.349 38.272-18.432 5.973-3.413 9.941-10.24 14.848-15.573 3.84-4.181 6.997-9.813 11.776-12.373 18.091-9.6 37.973-9.984 58.283-9.515l0.427 6.827c20.437-6.4 43.392-29.952 43.392-47.147-33.109 0-66.133 0.128-99.2-0.171-3.541 0-7.040-2.603-10.539-4.011 3.328-1.963 6.613-5.461 10.027-5.589zM627.328 868.139c-1.461-0.899-2.42-2.488-2.42-4.302 0-1.516 0.67-2.876 1.731-3.799l0.006-0.005c1.344-2.305 3.804-3.83 6.62-3.83 1.429 0 2.767 0.393 3.91 1.076l-0.035-0.019c3.2 1.621 6.315 3.328 10.155 5.333-3.072 2.645-5.547 4.864-8.107 6.955-4.523 3.712-8.235 1.365-11.861-1.408z" />
<glyph unicode="&#xe901;" glyph-name="raspap" horiz-adv-x="1031" d="M540.058 281.983c0-104.182-84.446-188.637-188.625-188.637-104.176 0-188.62 84.455-188.62 188.637 0 104.171 84.444 188.625 188.62 188.625 104.179 0 188.625-84.455 188.625-188.625zM351.437 550.062c-147.818 0-268.074-120.259-268.074-268.080 0-147.826 120.257-268.091 268.074-268.091s268.077 120.265 268.077 268.091c0 147.821-120.259 268.080-268.077 268.080zM351.437-58.985c-188 0-340.95 152.958-340.95 340.967 0 188.003 152.95 340.956 340.95 340.956 188.003 0 340.953-152.953 340.953-340.956 0-188.009-152.95-340.967-340.953-340.967zM404.82 698.222c185.52 0 339.484-137.497 365.479-315.929l79.208-5.253c-24.125 224.046-214.339 399.077-444.686 399.077-10.909 0-21.723-0.412-32.433-1.186l5.16-77.823c9.017 0.661 18.093 1.113 27.272 1.113zM404.989 874.303c285.73 0 520.41-222.659 539.731-503.584l78.375-5.205c-16.843 326.355-287.644 586.685-618.106 586.685-14.884 0-29.644-0.561-44.264-1.6l5.157-77.719c12.919 0.928 25.958 1.424 39.106 1.424z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
dist/raspap/css/fonts/RaspAP.ttf vendored Executable file

Binary file not shown.

BIN
dist/raspap/css/fonts/RaspAP.woff vendored Executable file

Binary file not shown.

54
dist/raspap/css/style.css vendored Normal file
View File

@ -0,0 +1,54 @@
/*!
* RaspAP-Brands Brand Icons - https://raspap.com
* License - https://github.com/billz/RaspAP-Brands-webgui/blob/master/LICENSE
*/
@font-face {
font-family: 'RaspAP';
src: url('fonts/RaspAP.eot?e76qs3');
src: url('fonts/RaspAP.eot?e76qs3#iefix') format('embedded-opentype'),
url('fonts/RaspAP.ttf?e76qs3') format('truetype'),
url('fonts/RaspAP.woff?e76qs3') format('woff'),
url('fonts/RaspAP.svg?e76qs3#RaspAP') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="ra-"], [class*=" ra-"] {
/* use !important to prevent issues with browser extensions that change ..webfonts */
font-family: 'RaspAP' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ra-wireguard:before {
font-size: 1.2rem;
content: "\e900";
color: #d1d3e2;
vertical-align: middle;
}
.card-header .ra-wireguard:before {
color: #fff;
}
.sidebar .nav-item.active .nav-link
span.ra-wireguard:before {
color: #6e707e;
}
.ra-raspap:before {
font-size: 4.35rem;
content: "\e901";
color: #d8224c;
margin-left: 0.1em;
}

View File

@ -6,7 +6,7 @@ if (!defined('RASPI_CONFIG')) {
$defaults = [
'RASPI_BRAND_TEXT' => 'RaspAP',
'RASPI_VERSION' => '2.7.1',
'RASPI_VERSION' => '2.8.0',
'RASPI_CONFIG_NETWORK' => RASPI_CONFIG.'/networking/defaults.json',
'RASPI_ADMIN_DETAILS' => RASPI_CONFIG.'/raspap.auth',
'RASPI_WIFI_AP_INTERFACE' => 'wlan0',
@ -24,9 +24,11 @@ $defaults = [
'RASPI_WPA_SUPPLICANT_CONFIG' => '/etc/wpa_supplicant/wpa_supplicant.conf',
'RASPI_HOSTAPD_CTRL_INTERFACE' => '/var/run/hostapd',
'RASPI_WPA_CTRL_INTERFACE' => '/var/run/wpa_supplicant',
'RASPI_OPENVPN_CLIENT_PATH' => '/etc/openvpn/client/',
'RASPI_OPENVPN_CLIENT_CONFIG' => '/etc/openvpn/client/client.conf',
'RASPI_OPENVPN_CLIENT_LOGIN' => '/etc/openvpn/client/login.conf',
'RASPI_OPENVPN_SERVER_CONFIG' => '/etc/openvpn/server/server.conf',
'RASPI_WIREGUARD_PATH' => '/etc/wireguard/',
'RASPI_WIREGUARD_CONFIG' => RASPI_WIREGUARD_PATH.'wg0.conf',
'RASPI_TORPROXY_CONFIG' => '/etc/tor/torrc',
'RASPI_LIGHTTPD_CONFIG' => '/etc/lighttpd/lighttpd.conf',
'RASPI_ACCESS_CHECK_IP' => '1.1.1.1',
@ -43,6 +45,7 @@ $defaults = [
'RASPI_DHCP_ENABLED' => true,
'RASPI_ADBLOCK_ENABLED' => false,
'RASPI_OPENVPN_ENABLED' => false,
'RASPI_WIREGUARD_ENABLED' => false,
'RASPI_TORPROXY_ENABLED' => false,
'RASPI_CONFAUTH_ENABLED' => true,
'RASPI_CHANGETHEME_ENABLED' => true,

368
includes/firewall.php Normal file
View File

@ -0,0 +1,368 @@
<?php
require_once 'includes/status_messages.php';
require_once 'includes/functions.php';
define('RASPAP_IPTABLES_SCRIPT', "/tmp/iptables_raspap.sh");
define('RASPAP_IP6TABLES_SCRIPT', "/tmp/ip6tables_raspap.sh");
/**
*
* @param array $rule
* @param array $conf
* @return array $don
*/
function getDependson(&$rule, &$conf)
{
if (isset($rule["dependson"][0]) ) {
$don = &$rule["dependson"];
if (!empty($don[0]) && isset($conf[$don[0]["var"]]) ) {
if (!isset($don[0]["type"]) ) { $don[0]["type"]="bool";
}
return $don;
}
}
return false;
}
/**
*
* @param array $sect
* @param array $conf
* @return boolean $active
*/
function isRuleEnabled(&$sect, &$conf)
{
$fw_on = isset($conf["firewall-enable"]) && $conf["firewall-enable"];
$active = isset($sect["fw-state"]) && $sect["fw-state"]==1;
$active = $fw_on ? $active : !$active;
$active = $active || !isset($sect["fw-state"]);
if (($don = getDependson($sect, $conf)) !== false
&& $don[0]["type"] == "bool" && !$conf[$don[0]["var"]]
) { $active = false;
}
return $active;
}
/**
*
* @param array $sect
* @param array $conf
* @return string $str
*/
function createRuleStr(&$sect, &$conf)
{
if (!is_array($sect["rules"]) ) { return "";
}
$rules = $sect["rules"];
$depon = getDependson($sect, $conf);
$rs = array();
foreach ( $rules as $rule ) {
if (preg_match('/\$[a-z0-9]*\$/i', $rule) ) {
$r = array($rule);
foreach ( $depon as $dep ) {
$rr = array();
$repl=$val="";
switch ( $dep["type"] ) {
case "list":
if (isset($dep["var"]) && !empty($conf[$dep["var"]]) ) { $val = explode(' ', $conf[$dep["var"]]);
}
if (!empty($val) && isset($dep["replace"]) ) { $repl=$dep["replace"];
}
break;
case "string":
if (isset($dep["var"]) ) { $val=$conf[$dep["var"]];
}
if (!empty($val) && isset($dep["replace"]) ) { $repl=$dep["replace"];
}
break;
default:
break;
}
if (!empty($repl) && !empty($val) ) {
if (is_array($val) ) {
foreach ( $val as $v ) { $rr = array_merge($rr, str_replace($repl, $v, $r));
}
}
else { $rr = array_merge($rr, str_replace($repl, $val, $r));
}
}
$r = !empty($rr) ? $rr : $r;
}
$rs = array_merge($rs, $rr);
} else {
$rs[] = $rule;
}
}
$str="";
foreach ( $rs as $r ) {
if (!preg_match('/\$[a-z0-9]*\$/i', $r) ) { $str .= '$IPT '.$r."\n";
}
}
return $str;
}
/**
*
* @param array $rule
* @return boolean
*/
function isIPv4(&$rule)
{
return !isset($rule["ip-version"]) || strstr($rule["ip-version"], "4") !== false;
}
/**
*
* @param array $rule
* @return boolean
*/
function isIPv6(&$rule)
{
return !isset($rule["ip-version"]) || strstr($rule["ip-version"], "6") !== false;
}
/**
*
* @return boolean
*/
function configureFirewall()
{
$json = file_get_contents(RASPI_IPTABLES_CONF);
$ipt = json_decode($json, true);
$conf = ReadFirewallConf();
$txt = "#!/bin/bash\n";
file_put_contents(RASPAP_IPTABLES_SCRIPT, $txt);
file_put_contents(RASPAP_IP6TABLES_SCRIPT, $txt);
file_put_contents(RASPAP_IPTABLES_SCRIPT, 'IPT="iptables"'."\n", FILE_APPEND);
file_put_contents(RASPAP_IP6TABLES_SCRIPT, 'IPT="ip6tables"'."\n", FILE_APPEND);
$txt = "\$IPT -F\n";
$txt .= "\$IPT -X\n";
$txt .= "\$IPT -t nat -F\n";
file_put_contents(RASPAP_IPTABLES_SCRIPT, $txt, FILE_APPEND);
file_put_contents(RASPAP_IP6TABLES_SCRIPT, $txt, FILE_APPEND);
if (empty($conf) || empty($ipt) ) { return false;
}
$count=0;
foreach ( $ipt["order"] as $idx ) {
if (isset($ipt[$idx]) ) {
foreach ( $ipt[$idx] as $i => $sect ) {
if (isRuleEnabled($sect, $conf) ) {
$str_rules= createRuleStr($sect, $conf);
if (!empty($str_rules) ) {
if (isIPv4($sect) ) { file_put_contents(RASPAP_IPTABLES_SCRIPT, $str_rules, FILE_APPEND);
}
if (isIPv6($sect) ) { file_put_contents(RASPAP_IP6TABLES_SCRIPT, $str_rules, FILE_APPEND);
}
++$count;
}
}
}
}
}
if ($count > 0 ) {
exec("chmod +x ".RASPAP_IPTABLES_SCRIPT);
exec("sudo ".RASPAP_IPTABLES_SCRIPT);
exec("sudo iptables-save | sudo tee /etc/iptables/rules.v4");
unlink(RASPAP_IPTABLES_SCRIPT);
exec("chmod +x ".RASPAP_IP6TABLES_SCRIPT);
exec("sudo ".RASPAP_IP6TABLES_SCRIPT);
exec("sudo ip6tables-save | sudo tee /etc/iptables/rules.v6");
unlink(RASPAP_IP6TABLES_SCRIPT);
}
return ($count > 0);
}
/**
*
* @param array $conf
* @return string $ret
*/
function WriteFirewallConf($conf)
{
$ret = false;
if (is_array($conf) ) { write_php_ini($conf, RASPI_FIREWALL_CONF);
}
return $ret;
}
/**
*
* @return array $conf
*/
function ReadFirewallConf()
{
$conf = array();
if (file_exists(RASPI_FIREWALL_CONF) ) {
$conf = parse_ini_file(RASPI_FIREWALL_CONF);
}
if ( !isset($conf["firewall-enable"]) ) {
$conf["firewall-enable"] = false;
$conf["ssh-enable"] = false;
$conf["http-enable"] = false;
$conf["excl-devices"] = "";
$conf["excluded-ips"] = "";
$conf["ap-device"] = "";
$conf["client-device"] = "";
$conf["restricted-ips"] = "";
}
exec('ifconfig | grep -E -i "^tun[0-9]"', $ret);
$conf["openvpn-enable"] = !empty($ret);
unset($ret);
exec('ifconfig | grep -E -i "^wg[0-9]"', $ret);
$conf["wireguard-enable"] = !empty($ret);
return $conf;
}
/**
*
* @return string $ips
*/
function getVPN_IPs()
{
$ips = "";
// get openvpn and wireguard server IPs
if (RASPI_OPENVPN_ENABLED && ($fconf = glob(RASPI_OPENVPN_CLIENT_PATH ."/*.conf")) !== false && !empty($fconf) ) {
foreach ( $fconf as $f ) {
unset($result);
exec('cat '.$f.' | sed -rn "s/^remote\s*([a-z0-9\.\-\_:]*)\s*([0-9]*)\s*$/\1 \2/ip" ', $result);
if (!empty($result) ) {
$result = explode(" ", $result[0]);
$ip = (isset($result[0])) ? $result[0] : "";
$port = (isset($result[1])) ? $result[1] : "";
if (!empty($ip) ) {
$ip = gethostbyname($ip);
if (filter_var($ip, FILTER_VALIDATE_IP) && strpos($ips, $ip) === false ) { $ips .= " $ip";
}
}
}
}
}
// get wireguard server IPs
if (RASPI_WIREGUARD_ENABLED && ($fconf = glob(RASPI_WIREGUARD_PATH ."/*.conf")) !== false && !empty($fconf) ) {
foreach ( $fconf as $f ) {
unset($result);
exec('sudo /bin/cat '.$f.' | sed -rn "s/^endpoint\s*=\s*\[?([a-z0-9\.\-\_:]*)\]?:([0-9]*)\s*$/\1 \2/ip" ', $result);
if (!empty($result) ) {
$result = explode(" ", $result[0]);
$ip = (isset($result[0])) ? $result[0] : "";
$port = (isset($result[1])) ? $result[1] : "";
if (!empty($ip) ) {
$ip = gethostbyname($ip);
if (filter_var($ip, FILTER_VALIDATE_IP) && strpos($ips, $ip) === false ) { $ips .= " $ip";
}
}
}
}
}
return trim($ips);
}
/**
*
* @return array $fw_conf
*/
function getFirewallConfiguration()
{
$fw_conf = ReadFirewallConf();
$json = file_get_contents(RASPI_IPTABLES_CONF);
getWifiInterface();
$ap_device = $_SESSION['ap_interface'];
$clients = getClients();
$str_clients = "";
foreach( $clients["device"] as $dev ) {
if (!$dev["isAP"] ) {
if (!empty($str_clients) ) { $str_clients .= ", ";
}
$str_clients .= $dev["name"];
}
}
$fw_conf["ap-device"] = $ap_device;
$fw_conf["client-list"] = $str_clients;
$id=findCurrentClientIndex($clients);
if ($id >= 0 ) { $fw_conf["client-device"] = $clients["device"][$id]["name"];
}
return $fw_conf;
}
/**
*
*/
function updateFirewall()
{
$fw_conf = getFirewallConfiguration();
if ( isset($fw_conf["firewall-enable"]) ) {
WriteFirewallConf($fw_conf);
configureFirewall();
}
return;
}
/**
*
*/
function DisplayFirewallConfig()
{
$status = new StatusMessages();
$fw_conf = getFirewallConfiguration();
$ap_device = $fw_conf["ap-device"];
$str_clients = $fw_conf["client-list"];
if (!empty($_POST)) {
$fw_conf["ssh-enable"] = isset($_POST['ssh-enable']);
$fw_conf["http-enable"] = isset($_POST['http-enable']);
$fw_conf["firewall-enable"] = isset($_POST['firewall-enable']) || isset($_POST['apply-firewall']);
if (isset($_POST['firewall-enable']) ) { $status->addMessage(_('Firewall is now enabled'), 'success');
}
if (isset($_POST['apply-firewall']) ) { $status->addMessage(_('Firewall settings changed'), 'success');
}
if (isset($_POST['firewall-disable']) ) { $status->addMessage(_('Firewall is now disabled'), 'warning');
}
if (isset($_POST['save-firewall']) ) { $status->addMessage(_('Firewall settings saved. Firewall is still disabled.'), 'success');
}
if (isset($_POST['excl-devices']) ) {
$excl = filter_var($_POST['excl-devices'], FILTER_SANITIZE_STRING);
$excl = str_replace(',', ' ', $excl);
$excl = trim(preg_replace('/\s+/', ' ', $excl));
if ($fw_conf["excl-devices"] != $excl ) {
$status->addMessage(_('Exclude devices '. $excl), 'success');
$fw_conf["excl-devices"] = $excl;
}
}
if (isset($_POST['excluded-ips']) ) {
$excl = filter_var($_POST['excluded-ips'], FILTER_SANITIZE_STRING);
$excl = str_replace(',', ' ', $excl);
$excl = trim(preg_replace('/\s+/', ' ', $excl));
if (!empty($excl) ) {
$excl = explode(' ', $excl);
$str_excl = "";
foreach ( $excl as $ip ) {
if (filter_var($ip, FILTER_VALIDATE_IP) ) { $str_excl .= "$ip ";
} else { $status->addMessage(_('Exclude IP address '. $ip . ' failed - not a valid IP address'), 'warning');
}
}
}
$str_excl = trim($str_excl);
if ($fw_conf["excluded-ips"] != $str_excl ) {
$status->addMessage(_('Exclude IP address(es) '. $str_excl), 'success');
$fw_conf["excluded-ips"] = $str_excl;
}
}
WriteFirewallConf($fw_conf);
configureFirewall();
}
$vpn_ips = getVPN_IPs();
echo renderTemplate(
"firewall", compact(
"status",
"ap_device",
"str_clients",
"fw_conf",
"vpn_ips"
)
);
}

View File

@ -152,15 +152,16 @@ function getDefaultNetValue($svc,$iface,$key)
* Returns default options for the specified service
*
* @param string $svc
* @param string $key
* @return object $json
*/
function getDefaultNetOpts($svc)
function getDefaultNetOpts($svc,$key)
{
$json = json_decode(file_get_contents(RASPI_CONFIG_NETWORK), true);
if ($json === null) {
return false;
} else {
return $json[$svc]['options'];
return $json[$svc][$key];
}
}
@ -224,6 +225,62 @@ function safefilerewrite($fileName, $dataToSave)
}
}
/**
* Prepends data to a file if not exists
*
* @param string $filename
* @param string $dataToSave
* @return boolean
*/
function file_prepend_data($filename, $dataToSave)
{
$context = stream_context_create();
$file = fopen($filename, 'r', 1, $context);
$file_data = readfile($file);
if (!preg_match('/^'.$dataToSave.'/', $file_data)) {
$tmp_file = tempnam(sys_get_temp_dir(), 'php_prepend_');
file_put_contents($tmp_file, $dataToSave);
file_put_contents($tmp_file, $file, FILE_APPEND);
fclose($file);
unlink($filename);
rename($tmp_file, $filename);
return true;
} else {
return false;
}
}
/**
* Fetches a meta value from a file
*
* @param string $filename
* @param string $pattern
* @return string
*/
function file_get_meta($filename, $pattern)
{
if(file_exists($filename)) {
$context = stream_context_create();
$file_data = file_get_contents($filename, false, $context);
preg_match('/^'.$pattern.'/', $file_data, $matched);
return $matched[1];
} else {
return false;
}
}
/**
* Callback function for array_filter
*
* @param string $var
* @return filtered value
*/
function filter_comments($var)
{
return $var[0] != '#';
}
/**
* Saves a CSRF token in the session
*/
@ -636,11 +693,70 @@ function getBridgedState()
return $arrHostapdConf['BridgedEnable'];
}
/**
* Validates the format of a CIDR notation string
*
* @param string $cidr
* @return bool
*/
function validateCidr($cidr)
{
$parts = explode('/', $cidr);
if(count($parts) != 2) {
return false;
}
$ip = $parts[0];
$netmask = intval($parts[1]);
if($netmask < 0) {
return false;
}
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return $netmask <= 32;
}
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
return $netmask <= 128;
}
return false;
}
// 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()
{
if ($_COOKIE['theme'] == 'lightsout.css') {
return true;
} else {
return false;
}
}
// search array for matching string and return only first matching group
function preg_only_match($pat,$haystack)
{
$match = "";
if(!empty($haystack) && !empty($pat)) {
if(!is_array($haystack)) $haystack = array($haystack);
$str = preg_grep($pat,$haystack);
if (!empty($str) && preg_match($pat,array_shift($str),$match) === 1 ) $match = $match[1];
}
return $match;
}
// Sanitizes a string for QR encoding
// @param string $str
// @return string
function qr_encode($str)
{
return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str);
}
function evalHexSequence($string) {
$evaluator = function ($input) {
return hex2bin($input[1]);

307
includes/get_clients.php Normal file
View File

@ -0,0 +1,307 @@
<?php
require_once 'includes/functions.php';
require_once 'includes/wifi_functions.php';
function getClients($simple=true)
{
exec('ifconfig -a | grep -oP "^(?!lo)(\w*)"', $rawdevs); // all devices except loopback
$path=RASPI_CLIENT_SCRIPT_PATH;
$cl=array();
if (!empty($rawdevs) && is_array($rawdevs)) {
$cl["clients"]=count($rawdevs);
// search for possibly not connected modem
exec("find /sys/bus/usb/devices/usb*/ -name dev ", $devtty); // search for ttyUSB
$devtty = preg_only_match("/(ttyUSB0)/", $devtty);
if (empty(preg_only_match("/(ppp)[0-9]/", $rawdevs))) {
if (!empty($devtty)) {
$rawdevs[]="ppp0";
exec("udevadm info --name='$devtty' 2> /dev/null");
}
}
foreach ($rawdevs as $i => $dev) {
$cl["device"][$i]["name"]=$dev;
$nam = (preg_match("/^(\w+)[0-9]$/",$dev,$nam) === 1) ? $nam=$nam[1] : "";
$cl["device"][$i]["type"]=$ty=getClientType($dev);
unset($udevinfo);
exec("udevadm info /sys/class/net/$dev 2> /dev/null", $udevinfo);
if ($nam == "ppp" && isset($devtty)) {
exec("udevadm info --name='$devtty' 2> /dev/null", $udevinfo);
}
if (!empty($udevinfo) && is_array($udevinfo)) {
$model = preg_only_match("/ID_MODEL_ENC=(.*)$/", $udevinfo);
if (empty($model) || preg_match("/^[0-9a-f]{4}$/", $model) === 1) {
$model = preg_only_match("/ID_MODEL_FROM_DATABASE=(.*)$/", $udevinfo);
}
if (empty($model)) {
$model = preg_only_match("/ID_OUI_FROM_DATABASE=(.*)$/", $udevinfo);
}
$vendor = preg_only_match("/ID_VENDOR_ENC=(.*)$/", $udevinfo);
if (empty($vendor) || preg_match("/^[0-9a-f]{4}$/", $vendor) === 1) {
$vendor = preg_only_match("/ID_VENDOR_FROM_DATABASE=(.*)$/", $udevinfo);
}
$driver = preg_only_match("/ID_NET_DRIVER=(.*)$/", $udevinfo);
$vendorid = preg_only_match("/ID_VENDOR_ID=(.*)$/", $udevinfo);
$productid = preg_only_match("/ID_MODEL_ID=(.*)$/", $udevinfo);
}
$cl["device"][$i]["model"] = preg_replace("/\\\\x20/", " ", $model);
$cl["device"][$i]["vendor"] = preg_replace("/\\\\x20/", " ", $vendor);
$cl["device"][$i]["vid"] = $vendorid;
$cl["device"][$i]["pid"] = $productid;
unset($mac);
exec("cat /sys/class/net/$dev/address 2> /dev/null", $mac);
$cl["device"][$i]["mac"] = empty($mac) ? "":$mac[0];
unset($ip);
exec("ifconfig $dev 2> /dev/null", $ip);
$cl["device"][$i]["ipaddress"] = preg_only_match("/.*inet ([0-9\.]+) .*/", $ip);
switch($ty) {
case "eth":
unset($res);
exec("ip link show $dev 2> /dev/null | grep -oP ' UP '", $res);
if (empty($res) && empty($ipadd)) {
$cl["device"][$i]["connected"] = "n";
} else {
$cl["device"][$i]["connected"] = "y";
}
break;
case "wlan":
unset($retiw);
exec("iwconfig $dev 2> /dev/null | sed -rn 's/.*(mode:master).*/1/ip'", $retiw);
$cl["device"][$i]["isAP"] = !empty($retiw);
unset($retiw);
exec("iw dev $dev link 2> /dev/null", $retiw);
if (!$simple && !empty($ssid=preg_only_match("/.*SSID:\s*([^\"]*).*/", $retiw)) ) {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["ssid"] = $ssid;
$cl["device"][$i]["ssidutf8"] = ssid2utf8($ssid);
$cl["device"][$i]["ap-mac"] = preg_only_match("/^Connected to ([0-9a-f\:]*).*$/", $retiw);
$sig = preg_only_match("/.*signal: (.*)$/", $retiw);
$val = preg_only_match("/^([0-9\.-]*).*$/", $sig);
if (!is_numeric($val)) {
$val = -100;
}
if ($val >= -50 ) {
$qual=100;
} else if ($val < -100) {
$qual=0;
} else {
$qual=round($val*2+200);
}
$cl["device"][$i]["signal"] = "$sig (".$qual."%)";
$cl["device"][$i]["bitrate"] = preg_only_match("/.*bitrate: ([0-9\.]* \w*\/s).*$/", $retiw);
$cl["device"][$i]["freq"] = preg_only_match("/.*freq: (.*)$/", $retiw);
$cl["device"][$i]["ap-mac"] = preg_only_match("/^Connected to ([0-9a-f\:]*).*$/", $retiw);
} else {
$cl["device"][$i]["connected"] = "n";
}
break;
case "ppp":
unset($res);
exec("ip link show $dev 2> /dev/null | grep -oP '( UP | UNKNOWN)'", $res);
if ($simple) {
if (empty($res)) {
$cl["device"][$i]["connected"] = "n";
$cl["device"][$i]["signal"] = "-100 dB (0%)";
} else {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["signal"] = "-0 dB (0%)";
}
break;
}
if (empty($res) && empty($ipadd)) {
$cl["device"][$i]["connected"] = "n";
} else {
$cl["device"][$i]["connected"] = "y";
}
unset($res);
exec("$path/info_huawei.sh mode modem", $res);
$cl["device"][$i]["mode"] = $res[0];
unset($res);
exec("$path/info_huawei.sh device modem", $res);
if ($res[0] != "none" ) {
$cl["device"][$i]["model"] = $res[0];
}
unset($res);
exec("$path/info_huawei.sh signal modem", $res);
$cl["device"][$i]["signal"] = $res[0];
unset($res);
exec("$path/info_huawei.sh operator modem", $res);
$cl["device"][$i]["operator"] = $res[0];
break;
case "hilink":
$pin=$user=$pw="";
getMobileLogin($pin,$pw,$user);
$opts=$pin.' '.$user.' '.$pw;
unset($res);
// exec("ip link show $dev 2> /dev/null | grep -oP ' UP '",$res);
exec("ifconfig -a | grep -i $dev -A 1 | grep -oP '(?<=inet )([0-9]{1,3}\.){3}'", $apiadd);
$apiadd = !empty($apiadd) ? $apiadd[0]."1" : "";
unset($res);
exec("$path/info_huawei.sh mode hilink $apiadd \"$opts\" ", $res);
$cl["device"][$i]["mode"] = $res[0];
unset($res);
exec("$path/info_huawei.sh device hilink $apiadd \"$opts\" ", $res);
if ($res[0] != "none" ) {
$cl["device"][$i]["model"] = $res[0];
}
unset($res);
exec("$path/info_huawei.sh signal hilink $apiadd \"$opts\" ", $res);
$cl["device"][$i]["signal"] = $res[0];
unset($ipadd);
exec("$path/info_huawei.sh ipaddress hilink $apiadd \"$opts\" ", $ipadd);
if (!empty($ipadd) && $ipadd[0] !== "none" ) {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["wan_ip"] = $ipadd[0];
} else {
$cl["device"][$i]["connected"] = "n";
$cl["device"][$i]["wan_ip"] = "-";
}
unset($res);
exec("$path/info_huawei.sh operator hilink $apiadd \"$opts\" ", $res);
$cl["device"][$i]["operator"] = $res[0];
break;
case "phone":
case "usb":
$cl["device"][$i]["connected"] = "y";
break;
default:
}
if (!isset($cl["device"][$i]["signal"])) {
$cl["device"][$i]["signal"]= $cl["device"][$i]["connected"] == "n" ? "-100 dB (0%)": "0 dB (100%)";;
}
if (!isset($cl["device"][$i]["isAP"])) {
$cl["device"][$i]["isAP"]=false;
}
}
}
return $cl;
}
function getClientType($dev) {
loadClientConfig();
// check if device type stored in DEVTYPE or raspapType (from UDEV rule) protperty of the device
exec("udevadm info /sys/class/net/$dev 2> /dev/null", $udevadm);
$type="none";
if (!empty($udevadm)) {
$type=preg_only_match("/raspapType=(\w*)/i",$udevadm);
if (empty($type)) {
$type=preg_only_match("/DEVTYPE=(\w*)/i",$udevadm);
}
}
if (empty($type) || $type == "none" || array_search($type, $_SESSION["net-device-name-prefix"]) === false) {
// no device type yet -> get device type from device name
if (preg_match("/^(\w+)[0-9]$/",$dev,$nam) === 1) $nam=$nam[1];
else $nam="none";
if (($n = array_search($nam, $_SESSION["net-device-name-prefix"])) === false) $n = count($_SESSION["net-device-types"])-1;
$type = $_SESSION["net-device-types"][$n];
}
return $type;
}
function getMobileLogin(&$pin,&$pw,&$user) {
if (file_exists(($f = RASPI_MOBILEDATA_CONFIG))) {
$dat = parse_ini_file($f);
$pin = (isset($dat["pin"]) && preg_match("/^[0-9]*$/", $dat["pin"])) ? "-p ".$dat["pin"] : "";
$user = (isset($dat["router_user"]) && !empty($dat["router_user"]) ) ? "-u ".$dat["router_user"] : "";
$pw = (isset($dat["router_pw"]) && !empty($dat["router_pw"]) ) ? "-P ".$dat["router_pw"] : "";
}
}
function loadClientConfig()
{
// load network device config file for UDEV rules into $_SESSION
if (!isset($_SESSION["udevrules"])) {
$_SESSION["net-device-types"]=array();
$_SESSION["net-device-name-prefix"]=array();
try {
$udevrules = file_get_contents(RASPI_CLIENT_CONFIG_PATH);
$_SESSION["udevrules"] = json_decode($udevrules, true);
// get device types
foreach ($_SESSION["udevrules"]["network_devices"] as $dev) {
$_SESSION["net-device-name-prefix"][]=$dev["name_prefix"];
$_SESSION["net-device-types"][]=$dev["type"];
$_SESSION["net-device-types-info"][]=$dev["type_info"];
}
} catch (Exception $e) {
$_SESSION["udevrules"]= null;
}
$_SESSION["net-device-types"][]="none";
$_SESSION["net-device-types-info"][]="unknown";
$_SESSION["net-device-name-prefix"][]="none";
}
}
function findCurrentClientIndex($clients)
{
$devid = -1;
if (!empty($clients)) {
$ncl=$clients["clients"];
if ($ncl > 0) {
$ty=-1;
foreach ($clients["device"] as $i => $dev) {
$id=array_search($dev["type"], $_SESSION["net-device-types"]);
if ($id >=0 && $_SESSION["udevrules"]["network_devices"][$id]["clientid"] > $ty && !$dev["isAP"]) {
$ty=$id;
$devid=$i;
}
}
}
}
return $devid;
}
function waitClientConnected($dev, $timeout=10)
{
do {
exec('ifconfig -a | grep -i '.$dev.' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $res);
$connected= !empty($res);
if (!$connected) {
sleep(1);
}
} while (!$connected && --$timeout > 0);
return $connected;
}
function setClientState($state)
{
$clients=getClients();
if (($idx = findCurrentClientIndex($clients)) >= 0) {
$dev = $clients["device"][$idx];
exec('ifconfig -a | grep -i '.$dev["name"].' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $res);
if (!empty($res)) {
$connected=$res[0];
}
switch($dev["type"]) {
case "wlan":
if ($state =="up") {
exec('sudo ip link set '.$dev["name"].' up');
}
if (!empty($connected) && $state =="down") {
exec('sudo ip link set '.$dev["name"].' down');
}
break;
case "hilink":
preg_match("/^([0-9]{1,3}\.){3}/", $connected, $ipadd);
$ipadd = $ipadd[0].'1'; // ip address of the Hilink api
$mode = ($state == "up") ? 1 : 0;
$pin=$user=$pw="";
getMobileLogin($pin,$pw,$user);
exec('sudo '.RASPI_CLIENT_SCRIPT_PATH.'/onoff_huawei_hilink.sh -c '.$mode.' -h '.$ipadd.' '.$pin.' '.$user.' '.$pw);
break;
case "ppp":
if ($state == "up") {
exec('sudo ifup '.$dev["name"]);
}
if (!empty($connected) && $state == "down") {
exec('sudo ifdown '.$dev["name"]);
}
break;
default:
break;
}
if ($state=="up") {
waitClientConnected($dev["name"], 15);
}
}
}

View File

@ -25,12 +25,17 @@ function DisplayHostAPDConfig()
];
$arrSecurity = array(1 => 'WPA', 2 => 'WPA2', 3 => 'WPA+WPA2', 'none' => _("None"));
$arrEncType = array('TKIP' => 'TKIP', 'CCMP' => 'CCMP', 'TKIP CCMP' => 'TKIP+CCMP');
$arrTxPower = getDefaultNetOpts('txpower','dbm');
$managedModeEnabled = false;
exec("ip -o link show | awk -F': ' '{print $2}'", $interfaces);
sort($interfaces);
exec("iw reg get | awk '/country / { sub(/:/,\"\",$2); print $2 }'", $country_code);
$cmd = "iw dev ".$_SESSION['ap_interface']." info | awk '$1==\"txpower\" {print $2}'";
exec($cmd, $txpower);
$txpower = intval($txpower[0]);
if (!RASPI_MONITOR_ENABLED) {
if (isset($_POST['SaveHostAPDSettings'])) {
SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $status);
@ -88,6 +93,17 @@ function DisplayHostAPDConfig()
if (!isset($arrConfig['country_code']) && isset($country_code[0])) {
$arrConfig['country_code'] = $country_code[0];
}
// set txpower with iw if value is non-default ('auto')
if (isset($_POST['txpower']) && ($_POST['txpower'] != 'auto')) {
$sdBm = $_POST['txpower'] * 100;
exec('sudo /sbin/iw dev '.$_POST['interface'].' set txpower fixed '.$sdBm, $return);
$status->addMessage('Setting transmit power to '.$_POST['txpower'].' dBm.', 'success');
$txpower = $_POST['txpower'];
} elseif ($_POST['txpower'] == 'auto') {
exec('sudo /sbin/iw dev '.$_POST['interface'].' set txpower auto', $return);
$status->addMessage('Setting transmit power to '.$_POST['txpower'].'.', 'success');
$txpower = $_POST['txpower'];
}
echo renderTemplate(
"hostapd", compact(
@ -101,6 +117,8 @@ function DisplayHostAPDConfig()
"selectedHwMode",
"arrSecurity",
"arrEncType",
"arrTxPower",
"txpower",
"arrHostapdConf"
)
);
@ -308,13 +326,13 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $status)
$ip_address.= (!preg_match('/.*\/\d+/', $ip_address)) ? '/'.mask2cidr($netmask) : null;
if ($bridgedEnable == 1) {
$config = array_keys(getDefaultNetOpts('dhcp'));
$config = array_keys(getDefaultNetOpts('dhcp','options'));
$config[] = PHP_EOL.'# RaspAP br0 configuration';
$config[] = 'denyinterfaces eth0 wlan0';
$config[] = 'interface br0';
$config[] = PHP_EOL;
} elseif ($wifiAPEnable == 1) {
$config = array_keys(getDefaultNetOpts('dhcp'));
$config = array_keys(getDefaultNetOpts('dhcp','options'));
$config[] = PHP_EOL.'# RaspAP uap0 configuration';
$config[] = 'interface uap0';
$config[] = 'static ip_address='.$ip_address;

View File

@ -11,10 +11,23 @@ function getRouteInfo($checkAccess)
$rInfo = array();
// get all default routes
exec('ip route list | sed -rn "s/default via (([0-9]{1,3}\.){3}[0-9]{1,3}).*dev (\w*).*src (([0-9]{1,3}\.){3}[0-9]{1,3}).*/\3 \4 \1/p"', $routes);
exec('ip route list | sed -rn "s/default dev (\w*) scope link/\1/p"', $devs);
$devpat = array("tun", "ppp"); // routing in case of VPN and PPP connection are different
foreach ($devpat as $pat) {
exec('ip route list | grep -oP "'.$pat.'[0-9]" | sort -u', $devs);
}
if (!empty($devs)) {
foreach ($devs as $dev)
exec('ip route list | sed -rn "s/(([0-9]{1,3}\.){3}[0-9]{1,3}).*dev.*("' . $dev . '").*scope link src (([0-9]{1,3}\.){3}[0-9]{1,3}).*/\3 \4 \1/p"', $routes);
foreach ($devs as $dev) {
unset($gateway);
unset($ipadd);
exec('ip route list | sed -rn "s/^.*via (([0-9]{1,3}\.){3}[0-9]{1,3}) dev "' . $dev . '".*$/\1/p" | head -n 1', $gateway);
if (empty($gateway)) {
exec('ip route list | sed -rn "s/(([0-9]{1,3}\.){3}[0-9]{1,3}).*dev.*"' . $dev . '".*scope link src.*/\1/p"', $gateway);
}
exec('ifconfig -a | grep -i ' . $dev . ' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $ipadd);
if (!empty($gateway) && !empty($ipadd)) {
$routes[]="$dev $ipadd[0] $gateway[0]";
}
}
}
if (!empty($routes)) {
foreach ($routes as $i => $route) {
@ -41,5 +54,4 @@ function getRouteInfo($checkAccess)
}
return $rInfo;
}
?>

View File

@ -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();
@ -20,7 +21,9 @@ function DisplayOpenVPNConfig()
if (isset($_POST['authPassword'])) {
$authPassword = strip_tags(trim($_POST['authPassword']));
}
$return = SaveOpenVPNConfig($status, $_FILES['customFile'], $authUser, $authPassword);
if (is_uploaded_file( $_FILES["customFile"]["tmp_name"])) {
$return = SaveOpenVPNConfig($status, $_FILES['customFile'], $authUser, $authPassword);
}
} elseif (isset($_POST['StartOpenVPN'])) {
$status->addMessage('Attempting to start OpenVPN', 'info');
exec('sudo /bin/systemctl start openvpn-client@client', $return);
@ -39,16 +42,32 @@ 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)) {
$authUser = $auth[0];
$authPassword = $auth[1];
$auth = array_filter($auth, 'filter_comments');
$authUser = current($auth);
$authPassword = next($auth);
}
$clients = preg_grep('/_client.(conf)$/', scandir(pathinfo(RASPI_OPENVPN_CLIENT_CONFIG, PATHINFO_DIRNAME)));
exec("readlink ".RASPI_OPENVPN_CLIENT_CONFIG." | xargs basename", $ret);
$conf_default = empty($ret) ? "none" : $ret[0];
$logEnable = 0;
if (!empty($_POST) && !isset($_POST['log-openvpn'])) {
$logOutput = "";
$f = @fopen("/tmp/openvpn.log", "r+");
if ($f !== false) {
ftruncate($f, 0);
fclose($f);
}
} elseif (isset($_POST['log-openvpn']) || filesize('/tmp/openvpn.log') >0) {
$logEnable = 1;
exec("sudo /etc/raspap/openvpn/openvpnlog.sh", $logOutput);
$logOutput = file_get_contents('/tmp/openvpn.log');
}
echo renderTemplate(
@ -56,9 +75,13 @@ function DisplayOpenVPNConfig()
"status",
"serviceStatus",
"openvpnstatus",
"logEnable",
"logOutput",
"public_ip",
"authUser",
"authPassword"
"authPassword",
"clients",
"conf_default"
)
);
}
@ -76,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 {
@ -86,76 +109,49 @@ 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);
$validation = new validation;
$upload->callbacks($validation, array('check_name_length'));
$results = $upload->upload();
if (!empty($results['errors'])) {
throw new RuntimeException($results['errors'][0]);
}
// Validate extension
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
if ($ext != 'ovpn') {
throw new RuntimeException('Invalid file extension');
}
// 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');
}
// Good file upload, update auth credentials if present
if (!empty($authUser) && !empty($authPassword)) {
$auth_flag = 1;
// Move tmp authdata to /etc/openvpn/login.conf
$tmp_authdata = $tmp_destdir .'ovpn/authdata';
$auth = $authUser .PHP_EOL . $authPassword .PHP_EOL;
file_put_contents($tmp_authdata, $auth);
system("sudo cp $tmp_authdata " . RASPI_OPENVPN_CLIENT_LOGIN, $return);
chmod($tmp_authdata, 0644);
$client_auth = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_login.conf';
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) {
$status->addMessage('Unable to save client auth credentials', 'danger');
}
}
// 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');
}
// Copy tmp client config to /etc/openvpn/client
system("sudo cp $tmp_ovpnclient " . RASPI_OPENVPN_CLIENT_CONFIG, $return);
// Move uploaded ovpn config from /tmp and create symlink
$client_ovpn = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_client.conf';
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);
if ($return ==0) {
$status->addMessage('OpenVPN client.conf uploaded successfully', 'info');
} else {
@ -168,3 +164,4 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword)
return $status;
}
}

View File

@ -147,6 +147,7 @@ function DisplaySystem()
'pl_PL.UTF-8' => 'Polskie',
'pt_BR.UTF-8' => 'Português',
'ru_RU.UTF-8' => 'Русский',
'ro_RO.UTF-8' => 'Română',
'sv_SE.UTF-8' => 'Svenska',
'tr_TR.UTF-8' => 'Türkçe',
'vi_VN.UTF-8' => 'Tiếng Việt (Vietnamese)'

View File

@ -7,13 +7,11 @@ function DisplayThemeConfig(&$extraFooterScripts)
{
$themes = [
"default" => "RaspAP (default)",
"hackernews" => "HackerNews",
"lightsout" => "Lights Out"
"hackernews" => "HackerNews"
];
$themeFiles = [
"default" => "custom.php",
"hackernews" => "hackernews.css",
"lightsout" => "lightsout.css"
"hackernews" => "hackernews.css"
];
$selectedTheme = array_search($_COOKIE['theme'], $themeFiles);

310
includes/wireguard.php Normal file
View File

@ -0,0 +1,310 @@
<?php
require_once 'includes/status_messages.php';
require_once 'config.php';
/**
* Displays wireguard server & peer configuration
*/
function DisplayWireGuardConfig()
{
$status = new StatusMessages();
if (!RASPI_MONITOR_ENABLED) {
$optRules = $_POST['wgRules'];
$optConf = $_POST['wgCnfOpt'];
$optSrvEnable = $_POST['wgSrvEnable'];
$optLogEnable = $_POST['wgLogEnable'];
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);
foreach ($return as $line) {
$status->addMessage($line, 'info');
}
} elseif (isset($_POST['stopwg'])) {
$status->addMessage('Attempting to stop WireGuard', 'info');
exec('sudo /bin/systemctl stop wg-quick@wg0', $return);
foreach ($return as $line) {
$status->addMessage($line, 'info');
}
}
CheckWireGuardLog( $optLogEnable, $status );
}
// 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);
$wg_srvport = ($conf['ListenPort'] == '') ? getDefaultNetValue('wireguard','server','ListenPort') : $conf['ListenPort'];
$wg_srvipaddress = ($conf['Address'] == '') ? getDefaultNetValue('wireguard','server','Address') : $conf['Address'];
$wg_srvdns = ($conf['DNS'] == '') ? getDefaultNetValue('wireguard','server','DNS') : $conf['DNS'];
$wg_peerpubkey = exec('sudo cat '. RASPI_WIREGUARD_PATH .'wg-peer-public.key', $return);
if (sizeof($conf) >0) {
$wg_senabled = true;
}
// 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'];
$wg_plistenport = ($conf['ListenPort'] == '') ? getDefaultNetValue('wireguard','peer','ListenPort') : $conf['ListenPort'];
$wg_pendpoint = ($conf['Endpoint'] == '') ? getDefaultNetValue('wireguard','peer','Endpoint') : $conf['Endpoint'];
$wg_pallowedips = ($conf['AllowedIPs'] == '') ? getDefaultNetValue('wireguard','peer','AllowedIPs') : $conf['AllowedIPs'];
$wg_pkeepalive = ($conf['PersistentKeepalive'] == '') ? getDefaultNetValue('wireguard','peer','PersistentKeepalive') : $conf['PersistentKeepalive'];
if (sizeof($conf) >0) {
$wg_penabled = true;
}
// fetch service status
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",
"optLogEnable",
"peer_id",
"wg_srvpubkey",
"wg_srvport",
"wg_srvipaddress",
"wg_srvdns",
"wg_senabled",
"wg_penabled",
"wg_pipaddress",
"wg_plistenport",
"wg_peerpubkey",
"wg_pendpoint",
"wg_pallowedips",
"wg_pkeepalive"
)
);
}
/**
* 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
*
* @param object $status
* @return boolean
*/
function SaveWireGuardConfig($status)
{
// Set defaults
$good_input = true;
$peer_id = 1;
// Validate server input
if ($_POST['wg_senabled'] == 1) {
if (isset($_POST['wg_srvport'])) {
if (strlen($_POST['wg_srvport']) > 5 || !is_numeric($_POST['wg_srvport'])) {
$status->addMessage('Invalid value for server local port', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_plistenport'])) {
if (strlen($_POST['wg_plistenport']) > 5 || !is_numeric($_POST['wg_plistenport'])) {
$status->addMessage('Invalid value for peer local port', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_srvipaddress'])) {
if (!validateCidr($_POST['wg_srvipaddress'])) {
$status->addMessage('Invalid value for server IP address', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_srvdns'])) {
if (!filter_var($_POST['wg_srvdns'],FILTER_VALIDATE_IP)) {
$status->addMessage('Invalid value for DNS', 'danger');
$good_input = false;
}
}
}
// Validate peer input
if ($_POST['wg_penabled'] == 1) {
if (isset($_POST['wg_pipaddress'])) {
if (!validateCidr($_POST['wg_pipaddress'])) {
$status->addMessage('Invalid value for peer IP address', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_pendpoint']) && strlen(trim($_POST['wg_pendpoint']) >0 )) {
$wg_pendpoint_seg = substr($_POST['wg_pendpoint'],0,strpos($_POST['wg_pendpoint'],':'));
if (!filter_var($wg_pendpoint_seg,FILTER_VALIDATE_IP)) {
$status->addMessage('Invalid value for endpoint address', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_pallowedips']) && strlen(trim($_POST['wg_pallowedips']) >0)) {
if (!validateCidr($_POST['wg_pallowedips'])) {
$status->addMessage('Invalid value for allowed IPs', 'danger');
$good_input = false;
}
}
if (isset($_POST['wg_pkeepalive']) && strlen(trim($_POST['wg_pkeepalive']) >0 )) {
if (strlen($_POST['wg_pkeepalive']) > 4 || !is_numeric($_POST['wg_pkeepalive'])) {
$status->addMessage('Invalid value for persistent keepalive', 'danger');
$good_input = false;
}
}
}
// Save settings
if ($good_input) {
var_dump($_POST);
// server (wg0.conf)
if ($_POST['wg_senabled'] == 1) {
// fetch server private key from filesytem
$wg_srvprivkey = exec('sudo cat '. RASPI_WIREGUARD_PATH .'wg-server-private.key', $return);
$config[] = '[Interface]';
$config[] = 'Address = '.$_POST['wg_srvipaddress'];
$config[] = 'ListenPort = '.$_POST['wg_srvport'];
$config[] = 'DNS = '.$_POST['wg_srvdns'];
$config[] = 'PrivateKey = '.$wg_srvprivkey;
$config[] = 'PostUp = '.getDefaultNetValue('wireguard','server','PostUp');
$config[] = 'PostDown = '.getDefaultNetValue('wireguard','server','PostDown');
$config[] = '';
$config[] = '[Peer]';
$config[] = 'PublicKey = '.$_POST['wg-peer'];
$config[] = 'AllowedIPs = '.$_POST['wg_pallowedips'];
if ($_POST['wg_pkeepalive'] !== '') {
$config[] = 'PersistentKeepalive = '.trim($_POST['wg_pkeepalive']);
}
$config[] = '';
$config = join(PHP_EOL, $config);
file_put_contents("/tmp/wgdata", $config);
system('sudo cp /tmp/wgdata '.RASPI_WIREGUARD_CONFIG, $return);
} else {
# remove selected conf + keys
system('sudo rm '. RASPI_WIREGUARD_PATH .'wg-server-private.key', $return);
system('sudo rm '. RASPI_WIREGUARD_PATH .'wg-server-public.key', $return);
system('sudo rm '. RASPI_WIREGUARD_CONFIG, $return);
}
// client1 (client.conf)
if ($_POST['wg_penabled'] == 1) {
// fetch peer private key from filesystem
$wg_peerprivkey = exec('sudo cat '. RASPI_WIREGUARD_PATH .'wg-peer-private.key', $return);
$config = [];
$config[] = '[Interface]';
$config[] = 'Address = '.trim($_POST['wg_pipaddress']);
$config[] = 'PrivateKey = '.$wg_peerprivkey;
$config[] = 'ListenPort = '.$_POST['wg_plistenport'];
$config[] = '';
$config[] = '[Peer]';
$config[] = 'PublicKey = '.$_POST['wg-server'];
$config[] = 'AllowedIPs = '.$_POST['wg_pallowedips'];
$config[] = 'Endpoint = '.$_POST['wg_pendpoint'];
if ($_POST['wg_pkeepalive'] !== '') {
$config[] = 'PersistentKeepalive = '.trim($_POST['wg_pkeepalive']);
}
$config[] = '';
$config = join(PHP_EOL, $config);
file_put_contents("/tmp/wgdata", $config);
system('sudo cp /tmp/wgdata '.RASPI_WIREGUARD_PATH.'client.conf', $return);
} else {
# remove selected conf + keys
system('sudo rm '. RASPI_WIREGUARD_PATH .'wg-peer-private.key', $return);
system('sudo rm '. RASPI_WIREGUARD_PATH .'wg-peer-public.key', $return);
system('sudo rm '. RASPI_WIREGUARD_PATH.'client.conf', $return);
}
foreach ($return as $line) {
$status->addMessage($line, 'info');
}
if ($return == 0) {
$status->addMessage('WireGuard configuration updated successfully', 'success');
} else {
$status->addMessage('WireGuard configuration failed to be updated', 'danger');
}
}
}
/**
*
* @return object $status
*/
function CheckWireGuardLog( $opt, $status )
{
// handle log option
if ( $opt == "1") {
exec("sudo journalctl --identifier wg-quick > /tmp/wireguard.log");
$status->addMessage('WireGuard debug log updated', 'success');
}
return $status;
}

View File

@ -7,15 +7,15 @@
* Enables use of simple web interface rather than SSH to control WiFi and related services on the Raspberry Pi.
* Recommended distribution is Raspberry Pi OS (32-bit) Lite. Specific instructions to install the supported software are
* in the README and original post by @SirLagz. For a quick run through, the packages required for the WebGUI are:
* lighttpd (version 1.4.53 installed via apt)
* php-cgi (version 7.3.19-1 installed via apt)
* lighttpd (version 1.4.59 installed via apt)
* php-cgi (version 7.4.25 installed via apt)
* along with their supporting packages, php7.3 will also need to be enabled.
*
* @author Lawrence Yau <sirlagz@gmail.com>
* @author Bill Zimmerman <billzimmerman@gmail.com>
* @license GNU General Public License, version 3 (GPL-3.0)
* @version 2.7.1
* @link https://github.com/raspap/raspap-webgui/
* @version 2.8.0
* @link https://github.com/RaspAP/raspap-webgui/
* @link https://raspap.com/
* @see http://sirlagz.net/2013/02/08/raspap-webgui/
*
@ -45,6 +45,7 @@ require_once 'includes/themes.php';
require_once 'includes/data_usage.php';
require_once 'includes/about.php';
require_once 'includes/openvpn.php';
require_once 'includes/wireguard.php';
require_once 'includes/torproxy.php';
$config = getConfig();
@ -82,6 +83,9 @@ $bridgedEnabled = getBridgedState();
<!-- Custom Fonts -->
<link href="dist/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<!-- RaspAP Fonts -->
<link href="dist/raspap/css/style.css" rel="stylesheet" type="text/css">
<!-- Custom CSS -->
<link href="<?php echo $theme_url; ?>" title="main" rel="stylesheet">
@ -161,6 +165,11 @@ $bridgedEnabled = getBridgedState();
<?php if (RASPI_OPENVPN_ENABLED) : ?>
<li class="nav-item">
<a class="nav-link" href="openvpn_conf"><i class="fas fa-key fa-fw mr-2"></i><span class="nav-label"><?php echo _("OpenVPN"); ?></a>
</li>
<?php endif; ?>
<?php if (RASPI_WIREGUARD_ENABLED) : ?>
<li class="nav-item">
<a class="nav-link" href="wg_conf"><span class="ra-wireguard mr-2"></span><span class="nav-label"><?php echo _("WireGuard"); ?></a>
</li>
<?php endif; ?>
<?php if (RASPI_TORPROXY_ENABLED) : ?>
@ -214,8 +223,13 @@ $bridgedEnabled = getBridgedState();
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Navbar -->
<p class="text-left brand-title mt-3 ml-2"><?php //echo _("WiFi Configuration Portal"); ?></p>
<p class="text-left brand-title mt-3 ml-2"></p>
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Night mode -->
<div class="custom-control custom-switch mt-4">
<input type="checkbox" class="custom-control-input" id="night-mode" <?php echo getNightmode() ? 'checked' : null ; ?> >
<label class="custom-control-label" for="night-mode"><i class="far fa-moon mr-1 text-muted"></i></label>
</div>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User -->
<li class="nav-item dropdown no-arrow">
@ -254,6 +268,12 @@ $bridgedEnabled = getBridgedState();
case "/openvpn_conf":
DisplayOpenVPNConfig();
break;
case "/wg_conf":
DisplayWireGuardConfig();
break;
case "/torproxy_conf":
DisplayTorProxyConfig();
break;
case "/torproxy_conf":
DisplayTorProxyConfig();
break;

View File

@ -35,7 +35,7 @@ echo "Checking iptables rules"
rules=(
"-A POSTROUTING -o tun0 -j MASQUERADE"
"-A FORWARD -i tun0 -o ${interface} -m state --state RELATED,ESTABLISHED -j ACCEPT"
"-A FORWARD -i wlan0 -o tun0 -j ACCEPT"
"-A FORWARD -i ${interface} -o tun0 -j ACCEPT"
)
for rule in "${rules[@]}"; do

View File

@ -0,0 +1,40 @@
#!/bin/bash
#
# RaspAP feature installation: handling of mobile data clients and client configuration
# to be sources by the RaspAP installer script
# Author: @zbchristian <christian@zeitnitz.eu>
# Author URI: https://github.com/zbchristian/
# License: GNU General Public License v3.0
# License URI: https://github.com/raspap/raspap-webgui/blob/master/LICENSE
# path for mobile modem scripts
readonly raspap_clients_scripts="/usr/local/sbin"
#
# table of mobile network operators - links the 5 digit operator code (from the modem) with a clear text operator name
readonly raspap_clients_operator_table="https://raw.githubusercontent.com/musalbas/mcc-mnc-table/master/mcc-mnc-table.csv"
function _install_feature_clients() {
name="feature clients"
_install_log "Install $name"
_install_log " - required packages for mobile data clients"
sudo apt-get -y install wvdial socat bc || _install_status 1 "Unable to install dependencies for $name"
_install_log " - copy configuration files and scripts"
# Move scripts
sudo cp "$webroot_dir/config/client_config/"*.sh "$raspap_clients_scripts/" || _install_status 1 "Unable to move client scripts ($name)"
sudo chmod a+rx "$raspap_clients_scripts/"*.sh || _install_status 1 "Unable to chmod client scripts ($name)"
# wget $raspap_clients_operator_table -o "$raspap_clients_scripts/"mcc-mnc-table.csv || _install_status 1 "Unable to wget operator table ($name)"
sudo cp "$webroot_dir/config/client_config/mcc-mnc-table.csv" "$raspap_clients_scripts/" || _install_status 1 "Unable to move client data ($name)"
# wvdial settings
sudo cp "$webroot_dir/config/client_config/wvdial.conf" "/etc/" || _install_status 1 "Unable to install client configuration ($name)"
sudo cp "$webroot_dir/config/client_config/interfaces" "/etc/network/interfaces" || _install_status 1 "Unable to install interface settings ($name)"
# udev rules/services to auto start mobile data services
sudo cp "$webroot_dir/config/client_config/70-mobile-data-sticks.rules" "/etc/udev/rules.d/" || _install_status 1 "Unable to install client udev rules ($name)"
sudo cp "$webroot_dir/config/client_config/80-raspap-net-devices.rules" "/etc/udev/rules.d/" || _install_status 1 "Unable to install client udev rules ($name)"
sudo cp "$webroot_dir/config/client_config/"*.service "/etc/systemd/system/" || _install_status 1 "Unable to install client startup services ($name)"
# client configuration and udev rule templates
sudo cp "$webroot_dir/config/client_udev_prototypes.json" "/etc/raspap/networking/" || _install_status 1 "Unable to install client configuration ($name)"
_install_status 0
}

View File

@ -0,0 +1,20 @@
#!/bin/bash
#
# RaspAP feature installation: Firewall
# to be sources by the RaspAP installer script
# Author: @zbchristian <christian@zeitnitz.eu>
# Author URI: https://github.com/zbchristian/
# License: GNU General Public License v3.0
# License URI: https://github.com/raspap/raspap-webgui/blob/master/LICENSE
function _install_feature_firewall() {
name="feature firewall"
_install_log "Install $name"
# create config dir
sudo mkdir "$raspap_network/firewall" || _install_status 1 "Unable to create firewall config directory"
# copy firewall configuration
sudo cp "$webroot_dir/config/iptables_rules.json" "$raspap_network/firewall/" || _install_status 1 "Unable to copy iptables templates"
sudo chown $raspap_user:$raspap_user -R "$raspap_network/firewall" || _install_status 1 "Unable to change ownership of firewall directory and files "
_install_status 0
}

View File

@ -1,3 +1,3 @@
#!/bin/bash
touch /tmp/openvpn.log
grep -m 100 openvpn /var/log/syslog | sudo tee /tmp/openvpn.log
journalctl |grep -m 200 openvpn | sudo tee /tmp/openvpn.log

View File

@ -20,8 +20,9 @@ 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/client.conf
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/authdata /etc/openvpn/client/login.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
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/dnsmasq.d/090_*.conf
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dhcpddata /etc/dhcpcd.conf
@ -30,15 +31,35 @@ www-data ALL=(ALL) NOPASSWD:/sbin/reboot
www-data ALL=(ALL) NOPASSWD:/sbin/ip link set wlan[0-9] down
www-data ALL=(ALL) NOPASSWD:/sbin/ip link set wlan[0-9] up
www-data ALL=(ALL) NOPASSWD:/sbin/ip -s a f label wlan[0-9]
www-data ALL=(ALL) NOPASSWD:/sbin/ifup *
www-data ALL=(ALL) NOPASSWD:/sbin/ifdown *
www-data ALL=(ALL) NOPASSWD:/sbin/iw
www-data ALL=(ALL) NOPASSWD:/bin/cp /etc/raspap/networking/dhcpcd.conf /etc/dhcpcd.conf
www-data ALL=(ALL) NOPASSWD:/etc/raspap/hostapd/enablelog.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/hostapd/disablelog.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/hostapd/servicestart.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/lighttpd/configport.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/openvpn/configauth.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/openvpn/openvpnlog.sh
www-data ALL=(ALL) NOPASSWD:/bin/chmod o+r /tmp/hostapd.log
www-data ALL=(ALL) NOPASSWD:/bin/chmod o+r /var/log/dnsmasq.log
www-data ALL=(ALL) NOPASSWD:/bin/chmod o+r /tmp/dnsmasq.log
www-data ALL=(ALL) NOPASSWD:/bin/chmod o+r /tmp/wireguard.log
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasqdata /etc/dnsmasq.d/090_adblock.conf
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 *
www-data ALL=(ALL) NOPASSWD:/bin/sed -i * /etc/wvdial.conf
www-data ALL=(ALL) NOPASSWD:/bin/sed -i * /etc/udev/rules.d/80-raspap-net-devices.rules
www-data ALL=(ALL) NOPASSWD:/usr/bin/tee -a /etc/udev/rules.d/80-raspap-net-devices.rules
www-data ALL=(ALL) NOPASSWD:/usr/bin/journalctl --identifier wg-quick
www-data ALL=(ALL) NOPASSWD:/bin/systemctl * wg-quick@wg0
www-data ALL=(ALL) NOPASSWD:/usr/bin/wg
www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wireguard/*.conf
www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wireguard/wg-*.key
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/wireguard/*.conf
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/wireguard/wg-*.key

View File

@ -0,0 +1,29 @@
#!/bin/bash
# include the raspap helper functions
source /usr/local/sbin/raspap_helpers.sh
_getWebRoot
echo -n "Update firewall ... "
cat << EOF > /tmp/updateFirewall.php
<?php
//set_include_path('/var/www/html/');
\$_SESSION['locale']="en_GB.UTF-8";
require_once 'includes/config.php';
require_once 'includes/defaults.php';
require_once RASPI_CONFIG.'/raspap.php';
require_once 'includes/locale.php';
require_once 'includes/wifi_functions.php';
require_once 'includes/get_clients.php';
require_once 'includes/firewall.php';
updateFirewall();
?>
EOF
sudo php -d include_path=$raspap_webroot /tmp/updateFirewall.php
rm /tmp/updateFirewall.php
echo "done."

Binary file not shown.

View File

@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: raspap\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2021-01-13 08:19\n"
"Last-Translator: Svend Skipper Andersen\n"
"PO-Revision-Date: 2020-04-14 08:51\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: Danish\n"
"Language: da_DK\n"
"MIME-Version: 1.0\n"
@ -12,10 +12,8 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: raspap\n"
"X-Crowdin-Project-ID: 395801\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/en_US/LC_MESSAGES/messages.po\n"
"X-Crowdin-File-ID: 10\n"
#: index.php
msgid "RaspAP Wifi Configuration Portal"
@ -253,12 +251,6 @@ msgstr "Klientliste"
msgid "Interface"
msgstr "Interface"
msgid "Enable DHCP for this interface"
msgstr "Aktivér DHCP for denne grænseflade"
msgid "Enable this option if you want RaspAP to assign IP addresses on the selected interface."
msgstr "Aktivér denne indstilling hvis du ønsker at RaspAP skal tildele IP-adresser på den valgte grænseflade."
msgid "DNS Server"
msgstr "DNS-server"
@ -352,9 +344,6 @@ msgstr "Format"
msgid "Choose a hosted server"
msgstr "Vælg en hostet server"
msgid "Enable these options to log DHCP server activity."
msgstr "Aktivér disse indstillinger for at logge DHCP-serveraktivitet."
msgid "Log DHCP requests"
msgstr "Log DHCP anmodninger"
@ -455,31 +444,10 @@ msgstr "Maksimal klientantal"
msgid "Configures the max_num_sta option of hostapd. The default and maximum is 2007. If empty or 0, the default applies."
msgstr "Konfigurerer max_num_sta i hostapd. Standard og maksimum er 2007. Hvis tom eller 0, bruges standard."
msgid "Beacon interval"
msgstr "Beaconinterval"
msgid "Disable <code>disassoc_low_ack</code>"
msgstr "Deaktivér <code>disassoc_low_ack</code>"
msgid "Do not disassociate stations based on excessive transmission failures."
msgstr "Undlad at frakoble stationer baseret på overdrevne transmissionsfejl."
msgid "Executing RaspAP service start"
msgstr "Udfører RaspAP servicestart"
msgid "Close"
msgstr "Luk"
msgid "Enable this option to log <code>hostapd</code> activity."
msgstr "Aktivér denne indstilling for at logge <code>hostapd</code> aktivitet."
#: includes/networking.php
msgid "Summary"
msgstr "Oversigt"
msgid "Internet connection"
msgstr "Internetforbindelse"
msgid "Current settings"
msgstr "Nuværende indstillinger"
@ -507,9 +475,6 @@ msgstr "Deaktiveret"
msgid "Static IP Options"
msgstr "Statiske IP-indstillinger"
msgid "Metric"
msgstr "Metrisk"
msgid "Apply settings"
msgstr "Anvend indstillinger"
@ -562,12 +527,6 @@ msgstr "Systemet genstarter nu!"
msgid "System Shutting Down Now!"
msgstr "Systemet lukker ned nu!"
msgid "Web server port"
msgstr "Webserverport"
msgid "Web server bind address"
msgstr "Webserver bind-adresse"
#: includes/themes.php
msgid "Theme settings"
msgstr "Temaindstillinger"
@ -575,9 +534,6 @@ msgstr "Temaindstillinger"
msgid "Select a theme"
msgstr "Vælg et tema"
msgid "Color"
msgstr "Farve"
#: includes/data_usage.php
msgid "Data usage"
msgstr "Dataforbrug"
@ -778,24 +734,3 @@ msgstr "Statistikker"
msgid "Information provided by adblock"
msgstr "Information leveret af adblock"
msgid "Enable custom blocklist"
msgstr "Aktiver brugerdefineret blokliste"
msgid "Define custom hosts to be blocked by entering an IPv4 or IPv6 address followed by any whitespace (spaces or tabs) and the host name."
msgstr "Definer brugerdefinerede værter, der skal blokeres ved at indtaste en IPv4- eller IPv6-adresse efterfulgt af blanke tegn (mellemrum eller faneblade) og værtsnavnet."
msgid "<b>IPv4 example:</b> 0.0.0.0 badhost.com"
msgstr "<b>IPv4 eksempel:</b> 0.0.0.0 badhost.com"
msgid "This option adds an <code>addn-hosts</code> directive to the dnsmasq configuration."
msgstr "Denne indstilling tilføjer et <code>addn-værts</code> direktiv til dnsmasq-konfigurationen."
msgid "Custom blocklist not defined"
msgstr "Brugerdefineret blokliste ikke defineret"
msgid "Invalid custom IP address found on line "
msgstr "Ugyldig brugerdefineret IP-adresse fundet på linje "
msgid "Invalid custom host found on line "
msgstr "Ugyldig brugerdefineret vært fundet på linje "

Binary file not shown.

View File

@ -1104,11 +1104,11 @@ msgstr "Allowed IPs"
msgid "Persistent keepalive"
msgstr "Persistent keepalive"
msgid "Display WireGuard status"
msgstr "Display WireGuard status"
msgid "Enable this option to display an updated <code>wg-quick</code> debug log."
msgstr "Enable this option to display an updated <code>wg-quick</code> debug log."
msgid "Enable this option to display an updated WireGuard status."
msgstr "Enable this option to display an updated WireGuard status."
msgid "WireGuard debug log updated"
msgstr "WireGuard debug log updated"
msgid "Scan this QR code with your client to connect to this tunnel"
msgstr "Scan this QR code with your client to connect to this tunnel"
@ -1140,3 +1140,73 @@ msgstr "WireGuard configuration updated successfully"
msgid "WireGuard configuration failed to be updated"
msgstr "WireGuard configuration failed to be updated"
#: templates/firewall.php
msgid "Client Firewall"
msgstr "Client Firewall"
msgid "Firewall is ENABLED"
msgstr "Firewall is ENABLED"
msgid "Firewall is OFF"
msgstr "Firewall is OFF"
msgid "The default firewall will only allow outgoing and already established traffic."
msgstr "The default firewall will only allow outgoing and already established traffic."
msgid "No incoming UDP traffic is allowed."
msgstr "No incoming UDP traffic is allowed."
msgid "There are no restrictions for the access point <code>%s</code>."
msgstr "There are no restrictions for the access point <code>%s</code>."
msgid "Exception: Service"
msgstr "Exception: Service"
msgid "allow SSH access on port 22"
msgstr "allow SSH access on port 22"
msgid "allow access to the RaspAP GUI on port 80 or 443"
msgstr "allow access to the RaspAP GUI on port 80 or 443"
msgid "Allow incoming connections for some services from the internet side."
msgstr "Allow incoming connections for some services from the internet side."
msgid "Exception: network device"
msgstr "Exception: network device"
msgid "Exclude device(s)"
msgstr "Exclude device(s)"
msgid "Exclude the given network device(s) (separated by a blank or comma) from firewall rules."
msgstr "Exclude the given network device(s) (separated by a blank or comma) from firewall rules."
msgid "Current client devices: <code>%s</code>"
msgstr "Current client devices: <code>%s</code>"
msgid "The access point <code>%s</code> is per default excluded."
msgstr "The access point <code>%s</code> is per default excluded."
msgid "Exception: IP-Address"
msgstr "Exception: IP-Address"
msgid "Allow incoming connections from"
msgstr "Allow incoming connections from"
msgid "For the given IP-addresses (separated by a blank or comma) the incoming connection (via TCP and UDP) is accepted."
msgstr "For the given IP-addresses (separated by a blank or comma) the incoming connection (via TCP and UDP) is accepted."
msgid "This is required for an OpenVPN via UDP or Wireguard connection."
msgstr "This is required for an OpenVPN via UDP or Wireguard connection."
msgid "The list of configured VPN server IP addresses: <code><b>%s</b></code>"
msgstr "The list of configured VPN server IP addresses: <code><b>%s</b></code>"
msgid "Disable Firewall"
msgstr "Disable Firewall"
msgid "Enable Firewall"
msgstr "Enable Firewall"
msgid "Apply changes"
msgstr "Apply changes"

Binary file not shown.

View File

@ -1,22 +1,19 @@
# RaspAP Portable Object file
# Project home: https://github.com/billz/raspap-webgui
# Licensed under the GNU General Public License v3.0
# This file is distributed under the same license as the RaspAP package
# FIRST AUTHOR billzimmerman@gmail.com, 2017
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: 1.2.1\n"
"Project-Id-Version: raspap\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2019-10-21 23:15+0000\n"
"Last-Translator: Luis Franco <luis_franco1990@hotmail.com>\n"
"Language-Team: \n"
"Language: es_MX\n"
"PO-Revision-Date: 2020-04-14 08:51\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: raspap\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/en_US/LC_MESSAGES/messages.po\n"
#: index.php
msgid "RaspAP Wifi Configuration Portal"
@ -35,7 +32,13 @@ msgid "WiFi client"
msgstr "Cliente wiFi"
msgid "Hotspot"
msgstr "Hotspot"
msgstr ""
msgid "Memory Use"
msgstr ""
msgid "CPU Temp"
msgstr ""
msgid "Networking"
msgstr "Red de trabajo"
@ -44,10 +47,10 @@ msgid "DHCP Server"
msgstr "Servidor DHCP"
msgid "OpenVPN"
msgstr "OpenVPN"
msgstr ""
msgid "TOR proxy"
msgstr "TOR proxy"
msgstr ""
msgid "Authentication"
msgstr "Autentificacion"
@ -97,7 +100,7 @@ msgid "Client settings"
msgstr "Configuracion de Cliente"
msgid "SSID"
msgstr "SSID"
msgstr ""
msgid "Channel"
msgstr "Canal"
@ -178,8 +181,8 @@ msgstr "Paquetes Trasnferidos"
msgid "Transferred Bytes"
msgstr "Bytes Trasnferidos"
msgid "Wireless Information"
msgstr "Informacion Inalambrica"
msgid "Wireless Client"
msgstr ""
msgid "Connected To"
msgstr "Conectado a"
@ -248,6 +251,9 @@ msgstr "Lista de Clientes"
msgid "Interface"
msgstr "Interfaz"
msgid "DNS Server"
msgstr "Servidor DNS"
msgid "Starting IP Address"
msgstr "Dirección IP de incio"
@ -318,31 +324,31 @@ msgid "Dnsmasq is not running"
msgstr "Dnsmasq no esta iniciado"
msgid "Upstream DNS servers"
msgstr "Upstream DNS servers"
msgstr ""
msgid "Only ever query DNS servers configured below"
msgstr "Only ever query DNS servers configured below"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr ""
msgid "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr ""
msgid "Add upstream DNS server"
msgstr "Add upstream DNS server"
msgstr ""
msgid "Format"
msgstr "Format"
msgstr ""
msgid "Choose a hosted server"
msgstr "Choose a hosted server"
msgstr ""
msgid "Log DHCP requests"
msgstr "Log DHCP requests"
msgstr ""
msgid "Log DNS queries"
msgstr "Log DNS queries"
msgstr ""
#: includes/hostapd.php
msgid "Basic"
@ -367,7 +373,7 @@ msgid "Encryption Type"
msgstr "Tipo de Encriptacion"
msgid "PSK"
msgstr "PSK"
msgstr ""
msgid "Advanced settings"
msgstr "Configuracion Avanzada"
@ -426,6 +432,9 @@ msgstr "Salida del archivo de registro"
msgid "WiFi client AP mode"
msgstr "Modo AP de WiFi de cliente"
msgid "Bridged AP mode"
msgstr ""
msgid "Hide SSID in broadcast"
msgstr "Ocultar SSID en la transmisión"
@ -445,9 +454,6 @@ msgstr "Configuracion Actual"
msgid "Default Gateway"
msgstr "Puerta de Enlace predeterminada"
msgid "DNS Server"
msgstr "Servidor DNS"
msgid "Alternate DNS Server"
msgstr "Servidor DNS Alterno"
@ -606,7 +612,7 @@ msgid "Diffie Hellman parameters"
msgstr "Parámetros Diffie Hellman"
msgid "KeepAlive"
msgstr "KeepAlive"
msgstr ""
msgid "Server log"
msgstr "Registro del servidor"
@ -660,6 +666,10 @@ msgstr "Intentando iniciar TOR"
msgid "Attempting to stop TOR"
msgstr "Intentando detener TOR"
#: template/dashboard.php
msgid "Bridged AP mode is enabled. For Hostname and IP, see your router's admin page."
msgstr ""
#: common form controls
msgid "Save settings"
msgstr "Guardar Configuraciones"
@ -682,3 +692,45 @@ msgstr "arriba"
msgid "down"
msgstr "abajo"
msgid "adblock"
msgstr ""
msgid "Ad Blocking"
msgstr ""
msgid "Start Ad Blocking"
msgstr ""
msgid "Restart Ad Blocking"
msgstr ""
msgid "Blocklist settings"
msgstr ""
msgid "Enable blocklists"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>block DNS requests for ads, tracking and other virtual garbage</b>. Blocklists are gathered from multiple, actively maintained sources and automatically updated, cleaned, optimized and moderated on a daily basis."
msgstr ""
msgid "This option adds <code>conf-file</code> and <code>addn-hosts</code> to the dnsmasq configuration."
msgstr ""
msgid "Choose a blocklist provider"
msgstr ""
msgid "Hostnames blocklist last updated"
msgstr ""
msgid "Domains blocklist last updated"
msgstr ""
msgid "Update now"
msgstr ""
msgid "Statistics"
msgstr ""
msgid "Information provided by adblock"
msgstr ""

Binary file not shown.

View File

@ -1,26 +1,19 @@
# RaspAP Portable Object file
# Project home: https://github.com/billz/raspap-webgui
# Licensed under the GNU General Public License v3.0
# This file is distributed under the same license as the RaspAP package
# FIRST AUTHOR billzimmerman@gmail.com, 2017
#
# Translators:
# William Zimmerman <billzimmerman@gmail.com>, 2019
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: 1.2.1\n"
"Project-Id-Version: raspap\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2019-10-25 17:42+0000\n"
"Last-Translator: William Zimmerman <billzimmerman@gmail.com>, 2019\n"
"Language-Team: Japanese (https://www.transifex.com/na-360/teams/104285/ja/)\n"
"PO-Revision-Date: 2020-04-17 06:37\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: Japanese\n"
"Language: ja_JP\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: raspap\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/en_US/LC_MESSAGES/messages.po\n"
#: index.php
msgid "RaspAP Wifi Configuration Portal"
@ -41,6 +34,12 @@ msgstr "WiFiクライアント"
msgid "Hotspot"
msgstr "ホットスポット"
msgid "Memory Use"
msgstr "メモリ使用率"
msgid "CPU Temp"
msgstr "CPU温度"
msgid "Networking"
msgstr "ネットワーク"
@ -115,9 +114,7 @@ msgstr "パスフレーズ"
msgid "Wifi settings updated successfully"
msgstr "Wifi設定が正常に更新されました"
msgid ""
"Wifi settings updated but cannot restart (cannot execute 'wpa_cli "
"reconfigure')"
msgid "Wifi settings updated but cannot restart (cannot execute 'wpa_cli reconfigure')"
msgstr "Wifi設定は更新されましたが、再起動できません「wpa_cli reconfigure」を実行できません"
msgid "Wifi settings failed to be updated"
@ -147,11 +144,8 @@ msgstr "隠す"
msgid "Not configured"
msgstr "設定されていません"
msgid ""
"<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not "
"currently support connecting to WEP"
msgstr ""
"<strong>注:</strong> WEPアクセスポイントは「オープン」と表示されます。RaspAPは現在、WEPへの接続をサポートしていません"
msgid "<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not currently support connecting to WEP"
msgstr "<strong>注:</strong> WEPアクセスポイントは「オープン」と表示されます。RaspAPは現在、WEPへの接続をサポートしていません"
#: includes/dashboard.php
msgid "Interface Information"
@ -187,8 +181,8 @@ msgstr "転送されたパケット"
msgid "Transferred Bytes"
msgstr "転送されたバイト"
msgid "Wireless Information"
msgstr "ワイヤレスの情報"
msgid "Wireless Client"
msgstr "無線クライアント"
msgid "Connected To"
msgstr "接続"
@ -330,31 +324,31 @@ msgid "Dnsmasq is not running"
msgstr "Dnsmasqが実行されていません"
msgid "Upstream DNS servers"
msgstr "Upstream DNS servers"
msgstr "アップストリームDNSサーバー"
msgid "Only ever query DNS servers configured below"
msgstr "Only ever query DNS servers configured below"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr ""
msgid "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr ""
msgid "Add upstream DNS server"
msgstr "Add upstream DNS server"
msgstr "アップストリームDNSサーバーを追加"
msgid "Format"
msgstr "Format"
msgstr ""
msgid "Choose a hosted server"
msgstr "Choose a hosted server"
msgstr ""
msgid "Log DHCP requests"
msgstr "Log DHCP requests"
msgstr ""
msgid "Log DNS queries"
msgstr "Log DNS queries"
msgstr ""
#: includes/hostapd.php
msgid "Basic"
@ -438,17 +432,17 @@ msgstr "ログファイル出力"
msgid "WiFi client AP mode"
msgstr "WiFiクライアントAPモード"
msgid "Bridged AP mode"
msgstr ""
msgid "Hide SSID in broadcast"
msgstr "ブロードキャストでSSIDを非表示"
msgid "Maximum number of clients"
msgstr "クライアントの最大数"
msgid ""
"Configures the max_num_sta option of hostapd. The default and maximum is "
"2007. If empty or 0, the default applies."
msgstr ""
"hostapdのmax_num_staオプションを構成します。 デフォルトおよび最大値は2007です。空欄または0の場合、デフォルトが適用されます。"
msgid "Configures the max_num_sta option of hostapd. The default and maximum is 2007. If empty or 0, the default applies."
msgstr "hostapdのmax_num_staオプションを構成します。 デフォルトおよび最大値は2007です。空欄または0の場合、デフォルトが適用されます。"
#: includes/networking.php
msgid "Summary"
@ -672,6 +666,10 @@ msgstr "TORを実行しようとしています"
msgid "Attempting to stop TOR"
msgstr "TORを停止しようとしています"
#: template/dashboard.php
msgid "Bridged AP mode is enabled. For Hostname and IP, see your router's admin page."
msgstr ""
#: common form controls
msgid "Save settings"
msgstr "設定を保存"
@ -693,3 +691,46 @@ msgstr "上"
msgid "down"
msgstr "下"
msgid "adblock"
msgstr "adblock"
msgid "Ad Blocking"
msgstr "広告ブロック"
msgid "Start Ad Blocking"
msgstr "広告ブロックを開始する"
msgid "Restart Ad Blocking"
msgstr "広告ブロックを再開する"
msgid "Blocklist settings"
msgstr ""
msgid "Enable blocklists"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>block DNS requests for ads, tracking and other virtual garbage</b>. Blocklists are gathered from multiple, actively maintained sources and automatically updated, cleaned, optimized and moderated on a daily basis."
msgstr ""
msgid "This option adds <code>conf-file</code> and <code>addn-hosts</code> to the dnsmasq configuration."
msgstr ""
msgid "Choose a blocklist provider"
msgstr ""
msgid "Hostnames blocklist last updated"
msgstr ""
msgid "Domains blocklist last updated"
msgstr ""
msgid "Update now"
msgstr "今すぐ更新する"
msgid "Statistics"
msgstr "統計"
msgid "Information provided by adblock"
msgstr ""

Binary file not shown.

View File

@ -1,26 +1,19 @@
# RaspAP Portable Object file
# Project home: https://github.com/billz/raspap-webgui
# Licensed under the GNU General Public License v3.0
# This file is distributed under the same license as the RaspAP package
# FIRST AUTHOR billzimmerman@gmail.com, 2017
#
# Translators:
# William Zimmerman <billzimmerman@gmail.com>, 2019
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: 1.2.1\n"
"Project-Id-Version: raspap\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2019-10-25 17:42+0000\n"
"Last-Translator: William Zimmerman <billzimmerman@gmail.com>, 2019\n"
"Language-Team: Korean (https://www.transifex.com/na-360/teams/104285/ko/)\n"
"PO-Revision-Date: 2020-04-14 08:51\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: Korean\n"
"Language: ko_KR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ko\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: raspap\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/en_US/LC_MESSAGES/messages.po\n"
#: index.php
msgid "RaspAP Wifi Configuration Portal"
@ -41,6 +34,12 @@ msgstr "WiFi 클라이언트"
msgid "Hotspot"
msgstr "핫스팟"
msgid "Memory Use"
msgstr ""
msgid "CPU Temp"
msgstr ""
msgid "Networking"
msgstr "네트워킹"
@ -101,7 +100,7 @@ msgid "Client settings"
msgstr "클라이언트 설정 "
msgid "SSID"
msgstr "SSID"
msgstr ""
msgid "Channel"
msgstr "채널 "
@ -115,9 +114,7 @@ msgstr "암호 "
msgid "Wifi settings updated successfully"
msgstr "Wifi 설정이 성공적으로 업데이트되었습니다"
msgid ""
"Wifi settings updated but cannot restart (cannot execute 'wpa_cli "
"reconfigure')"
msgid "Wifi settings updated but cannot restart (cannot execute 'wpa_cli reconfigure')"
msgstr "Wifi 설정이 업데이트되었지만 재시작할 수 없습니다('wpa_cli reconfigure'를 실행할 수 없습니다)"
msgid "Wifi settings failed to be updated"
@ -147,11 +144,8 @@ msgstr "숨기기 "
msgid "Not configured"
msgstr "환결설정 안됨"
msgid ""
"<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not "
"currently support connecting to WEP"
msgstr ""
"<strong>주의:</strong> WEP 접근점은 'Open'으로 표시됩니다. RaspAP은 현재 WEP 연결을 지원하지 않습니다"
msgid "<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not currently support connecting to WEP"
msgstr "<strong>주의:</strong> WEP 접근점은 'Open'으로 표시됩니다. RaspAP은 현재 WEP 연결을 지원하지 않습니다"
#: includes/dashboard.php
msgid "Interface Information"
@ -187,8 +181,8 @@ msgstr "전송된 패킷"
msgid "Transferred Bytes"
msgstr "전송된 바이트량"
msgid "Wireless Information"
msgstr "무선 정보"
msgid "Wireless Client"
msgstr ""
msgid "Connected To"
msgstr "연결"
@ -330,31 +324,31 @@ msgid "Dnsmasq is not running"
msgstr "Dnsmasq가 실행 중이 아닙니다 "
msgid "Upstream DNS servers"
msgstr "Upstream DNS servers"
msgstr ""
msgid "Only ever query DNS servers configured below"
msgstr "Only ever query DNS servers configured below"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr ""
msgid "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr ""
msgid "Add upstream DNS server"
msgstr "Add upstream DNS server"
msgstr ""
msgid "Format"
msgstr "Format"
msgstr ""
msgid "Choose a hosted server"
msgstr "Choose a hosted server"
msgstr ""
msgid "Log DHCP requests"
msgstr "Log DHCP requests"
msgstr ""
msgid "Log DNS queries"
msgstr "Log DNS queries"
msgstr ""
#: includes/hostapd.php
msgid "Basic"
@ -379,7 +373,7 @@ msgid "Encryption Type"
msgstr "암호화 유형"
msgid "PSK"
msgstr "PSK"
msgstr ""
msgid "Advanced settings"
msgstr "고급 설정 "
@ -438,18 +432,17 @@ msgstr "로그파일 출력"
msgid "WiFi client AP mode"
msgstr "WiFi 클라이언트 AP 모드 "
msgid "Bridged AP mode"
msgstr ""
msgid "Hide SSID in broadcast"
msgstr "방송 중에 SSID 숨기기 "
msgid "Maximum number of clients"
msgstr "클라이언트 최대 개수"
msgid ""
"Configures the max_num_sta option of hostapd. The default and maximum is "
"2007. If empty or 0, the default applies."
msgstr ""
"hostapd의 max_num_sta option을 구성합니다. 기본값 및 최대값은 2007입니다. 비었거나 0인 경우 기본값이 "
"적용됩니다."
msgid "Configures the max_num_sta option of hostapd. The default and maximum is 2007. If empty or 0, the default applies."
msgstr "hostapd의 max_num_sta option을 구성합니다. 기본값 및 최대값은 2007입니다. 비었거나 0인 경우 기본값이 적용됩니다."
#: includes/networking.php
msgid "Summary"
@ -673,6 +666,10 @@ msgstr "TOR 시작 시도 중입니다 "
msgid "Attempting to stop TOR"
msgstr "TOR 중지 시도 중입니다 "
#: template/dashboard.php
msgid "Bridged AP mode is enabled. For Hostname and IP, see your router's admin page."
msgstr ""
#: common form controls
msgid "Save settings"
msgstr "설정 저장"
@ -694,3 +691,46 @@ msgstr "작동"
msgid "down"
msgstr "다운"
msgid "adblock"
msgstr ""
msgid "Ad Blocking"
msgstr ""
msgid "Start Ad Blocking"
msgstr ""
msgid "Restart Ad Blocking"
msgstr ""
msgid "Blocklist settings"
msgstr ""
msgid "Enable blocklists"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>block DNS requests for ads, tracking and other virtual garbage</b>. Blocklists are gathered from multiple, actively maintained sources and automatically updated, cleaned, optimized and moderated on a daily basis."
msgstr ""
msgid "This option adds <code>conf-file</code> and <code>addn-hosts</code> to the dnsmasq configuration."
msgstr ""
msgid "Choose a blocklist provider"
msgstr ""
msgid "Hostnames blocklist last updated"
msgstr ""
msgid "Domains blocklist last updated"
msgstr ""
msgid "Update now"
msgstr ""
msgid "Statistics"
msgstr ""
msgid "Information provided by adblock"
msgstr ""

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: raspap\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2020-05-19 15:29\n"
"Last-Translator: Denis Trifiniuc\n"
"PO-Revision-Date: 2020-04-14 08:51\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: Russian\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
@ -35,10 +35,10 @@ msgid "Hotspot"
msgstr "Точка доступа"
msgid "Memory Use"
msgstr "Использование RAM"
msgstr ""
msgid "CPU Temp"
msgstr "Температура ЦП"
msgstr ""
msgid "Networking"
msgstr "Сетевые"
@ -47,10 +47,10 @@ msgid "DHCP Server"
msgstr "DHCP сервер"
msgid "OpenVPN"
msgstr "OpenVPN"
msgstr ""
msgid "TOR proxy"
msgstr "TOR proxy"
msgstr ""
msgid "Authentication"
msgstr "авторизации"
@ -100,7 +100,7 @@ msgid "Client settings"
msgstr "Настройки клиента"
msgid "SSID"
msgstr "SSID"
msgstr ""
msgid "Channel"
msgstr "Канал"
@ -182,7 +182,7 @@ msgid "Transferred Bytes"
msgstr "Передано Байт"
msgid "Wireless Client"
msgstr "WiFi клиент"
msgstr ""
msgid "Connected To"
msgstr "Подключено к"
@ -324,31 +324,31 @@ msgid "Dnsmasq is not running"
msgstr "Dnsmasq не запущена"
msgid "Upstream DNS servers"
msgstr "Пользовательские DNS-серверы"
msgstr ""
msgid "Only ever query DNS servers configured below"
msgstr "Использовать только DNS-серверы, настроенные ниже"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>send DNS queries to the servers configured below exclusively</b>. By default RaspAP also uses its upstream DHCP server's name servers."
msgstr "Включите эту опцию, если вы хотите, чтобы RaspAP <b>отправлял DNS-запросы только на серверы, настроенные ниже</b>. По умолчанию RaspAP также использует восходящие DNS-серверы, назначенные через DHCP."
msgstr ""
msgid "This option adds <code>no-resolv</code> to the dnsmasq configuration."
msgstr "Этот параметр добавляет <code>no-resolv</code> в конфигурацию dnsmasq."
msgstr ""
msgid "Add upstream DNS server"
msgstr "Добавить сервер DNS"
msgstr ""
msgid "Format"
msgstr "Формат"
msgstr ""
msgid "Choose a hosted server"
msgstr "Общедоступный DNS-сервер"
msgstr ""
msgid "Log DHCP requests"
msgstr "Журнал DHCP-запросов"
msgstr ""
msgid "Log DNS queries"
msgstr "Журнал DNS-запросов"
msgstr ""
#: includes/hostapd.php
msgid "Basic"
@ -373,7 +373,7 @@ msgid "Encryption Type"
msgstr "Тип шифрования"
msgid "PSK"
msgstr "PSK"
msgstr ""
msgid "Advanced settings"
msgstr "Расширенные настройки"
@ -433,7 +433,7 @@ msgid "WiFi client AP mode"
msgstr "Режим AP WiFi-клиента"
msgid "Bridged AP mode"
msgstr "Режим моста ТОЧКИ ДОСТУПА"
msgstr ""
msgid "Hide SSID in broadcast"
msgstr "Скрыть SSID при трансляции"
@ -668,7 +668,7 @@ msgstr "Попытка остановить TOR"
#: template/dashboard.php
msgid "Bridged AP mode is enabled. For Hostname and IP, see your router's admin page."
msgstr "Мостовой режим ТОЧКИ ДОСТУПА включен. Для хоста и IP-адреса см. страницу администрирования маршрутизатора."
msgstr ""
#: common form controls
msgid "Save settings"
@ -693,44 +693,44 @@ msgid "down"
msgstr "вниз"
msgid "adblock"
msgstr "Adblock"
msgstr ""
msgid "Ad Blocking"
msgstr "Ad Blocking"
msgstr ""
msgid "Start Ad Blocking"
msgstr "Запустить Ad Blocking"
msgstr ""
msgid "Restart Ad Blocking"
msgstr "Перезапустить Ad Blocking"
msgstr ""
msgid "Blocklist settings"
msgstr "Настройки блокировки"
msgstr ""
msgid "Enable blocklists"
msgstr "Включить блокировку"
msgstr ""
msgid "Enable this option if you want RaspAP to <b>block DNS requests for ads, tracking and other virtual garbage</b>. Blocklists are gathered from multiple, actively maintained sources and automatically updated, cleaned, optimized and moderated on a daily basis."
msgstr "Включите эту опцию, если вы хотите, чтобы RaspAP <b>блокировал DNS запросы для рекламы, отслеживания и другого виртуального мусора</b>. Блокирующие списки собираются из множества активно поддерживаемых источников и автоматически обновляются, очищаются, оптимизируются и модерируются ежедневно."
msgstr ""
msgid "This option adds <code>conf-file</code> and <code>addn-hosts</code> to the dnsmasq configuration."
msgstr "Эта опция добавляет в конфигурацию dnsmasq <code>conf-file</code> и <code>addn-hosts</code>."
msgstr ""
msgid "Choose a blocklist provider"
msgstr "Выберите поставщика черного списка"
msgstr ""
msgid "Hostnames blocklist last updated"
msgstr "Имена черного списка последнее обновление"
msgstr ""
msgid "Domains blocklist last updated"
msgstr "Последнее обновление списка блокировки доменов"
msgstr ""
msgid "Update now"
msgstr "Обновить сейчас"
msgstr ""
msgid "Statistics"
msgstr "Статистика"
msgstr ""
msgid "Information provided by adblock"
msgstr "Информация получена от Adblock"
msgstr ""

View File

@ -1,58 +1,79 @@
<!-- static leases tab -->
<div class="tab-pane fade" id="static-leases">
<h4 class="mt-3 mb-3"><?php echo _("Static leases") ?></h4>
<div class="row">
<div class="col-md-12">
<h4 class="mt-3 mb-3"><?php echo _("Static leases") ?></h4>
<p id="static-lease-description">
<small><?php echo _("Clients with a particular hardware MAC address can always be allocated the same IP address.") ?></small>
<small class="text-muted"><?php echo _("This option adds <code>dhcp-host</code> entries to the dnsmasq configuration.") ?></small>
</p>
<div class="dhcp-static-leases js-dhcp-static-lease-container">
<?php foreach ($hosts as $host) : ?>
<?php list($host, $comment) = array_map("trim", explode("#", $host)); ?>
<?php list($mac, $ip) = array_map("trim", explode(",", $host)); ?>
<div class="row dhcp-static-lease-row js-dhcp-static-lease-row">
<div class="col-md-4 col-xs-3">
<input type="text" name="static_leases[mac][]" value="<?php echo htmlspecialchars($mac, ENT_QUOTES) ?>" placeholder="<?php echo _("MAC address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[ip][]" value="<?php echo htmlspecialchars($ip, ENT_QUOTES) ?>" placeholder="<?php echo _("IP address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[comment][]" value="<?php echo htmlspecialchars($comment, ENT_QUOTES) ?>" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
</div>
<div class="col-md-2 col-xs-3">
<button type="button" class="btn btn-outline-danger js-remove-dhcp-static-lease"><i class="far fa-trash-alt"></i></button>
</div>
</div>
<?php endforeach ?>
</div>
<div class="dhcp-static-leases js-dhcp-static-lease-container">
<?php foreach ($hosts as $host) : ?>
<?php list($host, $comment) = array_map("trim", explode("#", $host)); ?>
<?php list($mac, $ip) = array_map("trim", explode(",", $host)); ?>
<div class="row dhcp-static-lease-row js-dhcp-static-lease-row">
<div class="row dhcp-static-lease-row js-new-dhcp-static-lease">
<div class="col-md-4 col-xs-3">
<input type="text" name="static_leases[mac][]" value="<?php echo htmlspecialchars($mac, ENT_QUOTES) ?>" placeholder="<?php echo _("MAC address") ?>" class="form-control">
<input type="text" name="mac" value="" placeholder="<?php echo _("MAC address") ?>" class="form-control" autofocus="autofocus">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[ip][]" value="<?php echo htmlspecialchars($ip, ENT_QUOTES) ?>" placeholder="<?php echo _("IP address") ?>" class="form-control">
<input type="text" name="ip" value="" placeholder="<?php echo _("IP address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[comment][]" value="<?php echo htmlspecialchars($comment, ENT_QUOTES) ?>" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
<input type="text" name="comment" value="" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
</div>
<div class="col-md-2 col-xs-3">
<button type="button" class="btn btn-danger js-remove-dhcp-static-lease"><?php echo _("Remove") ?></button>
<button type="button" class="btn btn-outline-success js-add-dhcp-static-lease"><i class="far fa-plus-square"></i></button>
</div>
</div>
<?php endforeach ?>
</div>
<h5 class="mt-3 mb-3"><?php echo _("Add static DHCP lease") ?></h5>
<div class="row dhcp-static-lease-row js-new-dhcp-static-lease">
<div class="col-md-4 col-xs-3">
<input type="text" name="mac" value="" placeholder="<?php echo _("MAC address") ?>" class="form-control" autofocus="autofocus">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="ip" value="" placeholder="<?php echo _("IP address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="comment" value="" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
</div>
<div class="col-md-2 col-xs-3">
<button type="button" class="btn btn-success js-add-dhcp-static-lease"><?php echo _("Add") ?></button>
</div>
</div>
<h5 class="mt-3 mb-3"><?php echo _("Restrict access") ?></h5>
<div class="input-group">
<input type="hidden" name="dhcp-ignore" value="0">
<div class="custom-control custom-switch">
<input class="custom-control-input" id="dhcp-ignore" type="checkbox" name="dhcp-ignore" value="1" <?php echo $conf['dhcp-ignore'] ? ' checked="checked"' : "" ?> aria-describedby="dhcp-ignore-description">
<label class="custom-control-label" for="dhcp-ignore"><?php echo _("Limit network access to static clients") ?></label>
</div>
<p id="dhcp-ignore-description">
<small><?php echo _("Enable this option if you want RaspAP to <b>ignore any clients</b> which are not specified in the static leases list.") ?></small>
<small class="text-muted"><?php echo _("This option adds <code>dhcp-ignore</code> to the dnsmasq configuration.") ?></small>
</p>
</div>
</div>
</div>
<template id="js-dhcp-static-lease-row">
<div class="row dhcp-static-lease-row js-dhcp-static-lease-row">
<div class="col-md-4 col-xs-3">
<input type="text" name="static_leases[mac][]" value="{{ mac }}" placeholder="<?php echo _("MAC address") ?>" class="form-control">
<template id="js-dhcp-static-lease-row">
<div class="row dhcp-static-lease-row js-dhcp-static-lease-row">
<div class="col-md-4 col-xs-3">
<input type="text" name="static_leases[mac][]" value="{{ mac }}" placeholder="<?php echo _("MAC address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[ip][]" value="{{ ip }}" placeholder="<?php echo _("IP address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[comment][]" value="{{ comment }}" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
</div>
<div class="col-md-2 col-xs-3">
<button type="button" class="btn btn-outline-danger js-remove-dhcp-static-lease"><i class="far fa-trash-alt"></i></button>
</div>
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[ip][]" value="{{ ip }}" placeholder="<?php echo _("IP address") ?>" class="form-control">
</div>
<div class="col-md-3 col-xs-3">
<input type="text" name="static_leases[comment][]" value="{{ comment }}" placeholder="<?php echo _("Optional comment") ?>" class="form-control">
</div>
<div class="col-md-2 col-xs-3">
<button type="button" class="btn btn-warning js-remove-dhcp-static-lease"><?php echo _("Remove") ?></button>
</div>
</div>
</template>
</template>
</div><!-- /.tab-pane -->

110
templates/firewall.php Executable file
View File

@ -0,0 +1,110 @@
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<i class="fas fa-shield-alt mr-2"></i><?php echo _("Firewall"); ?>
</div>
</div><!-- /.row -->
</div><!-- /.card-header -->
<div class="card-body">
<?php $status->showMessages(); ?>
<h4><?php echo _("Client Firewall"); ?></h4>
<?php if ( $fw_conf["firewall-enable"]) : ?>
<i class="fas fa-circle mr-2 service-status-up"></i><?php echo _("Firewall is ENABLED"); ?>
<?php else : ?>
<i class="fas fa-circle mr-2 service-status-down"></i><?php echo _("Firewall is OFF"); ?>
<?php endif ?>
<div class="row">
<div class="col-md-6">
<p class="mr-2">
<small>
<?php echo _("The default firewall will only allow outgoing and already established traffic."); ?><br />
<?php echo _("No incoming UDP traffic is allowed."); ?><br />
<?php printf(_("There are no restrictions for the access point <code>%s</code>."), $ap_device); ?>
</small>
</p>
</div>
</div>
<form id="frm-firewall" action="firewall_conf" method="POST" >
<?php echo CSRFTokenFieldTag(); ?>
<h5><?php echo _("Exception: Service"); ?></h4>
<div class="row">
<div class="form-group col-md-6">
<div class="custom-control custom-switch">
<input class="custom-control-input" id="ssh-enable" type="checkbox" name="ssh-enable" value="1" aria-describedby="exception-description" <?php if ($fw_conf["ssh-enable"]) echo "checked"; ?> >
<label class="custom-control-label" for="ssh-enable"><?php echo _("allow SSH access on port 22") ?></label>
</div>
<div class="custom-control custom-switch">
<input class="custom-control-input" id="http-enable" type="checkbox" name="http-enable" value="1" aria-describedby="exceptions-description" <?php if ($fw_conf["http-enable"]) echo "checked"; ?> >
<label class="custom-control-label" for="http-enable"><?php echo _("allow access to the RaspAP GUI on port 80 or 443") ?></label>
</div>
<p class="mb-0" id="exceptions-description">
<small><?php echo _("Allow incoming connections for some services from the internet side.") ?></small>
</p>
</div>
</div>
<h5><?php echo _("Exception: network device"); ?></h4>
<div class="row">
<div class="form-group col-md-6">
<label for="excl-device"><?php echo _("Exclude device(s)") ?></label>
<input class="form-control" id="excl-devices" type="text" name="excl-devices" value="<?php echo $fw_conf["excl-devices"] ?>" aria-describedby="exclusion-description" >
<p class="mb-0" id="exclusion-description">
<small>
<?php echo _("Exclude the given network device(s) (separated by a blank or comma) from firewall rules."); ?><br />
<?php printf(_("Current client devices: <code>%s</code>"), $str_clients); ?><br />
<?php printf(_("The access point <code>%s</code> is per default excluded."), $ap_device); ?>
</small>
</p>
</div>
</div>
<h5><?php echo _("Exception: IP-Address"); ?></h4>
<div class="row">
<div class="form-group col-md-6">
<label for="excluded-ips"><?php echo _("Allow incoming connections from") ?></label>
<input class="form-control" id="excluded-ips" type="text" name="excluded-ips" value="<?php echo $fw_conf["excluded-ips"] ?>" aria-describedby="excl-ips-description" >
<p class="mb-0" id="excl-ips-description">
<small>
<?php echo _("For the given IP-addresses (separated by a blank or comma) the incoming connection (via TCP and UDP) is accepted."); ?><br />
<?php echo _("This is required for an OpenVPN via UDP or Wireguard connection."); ?><br />
<?php if ( !empty($vpn_ips) ) printf (_("The list of configured VPN server IP addresses: <code><b>%s</b></code>"), $vpn_ips); ?>
</small>
</p>
</div>
</div>
<?php if ($fw_conf["firewall-enable"]) : ?>
<input type="submit" class="btn btn-outline btn-primary" value="<?php echo _("Apply changes"); ?>" name="apply-firewall" />
<input type="submit" class="btn btn-warning firewall-apply" value="<?php echo _("Disable Firewall") ?>" name="firewall-disable" data-toggle="modal" data-target="#firewallModal"/>
<?php else : ?>
<input type="submit" class="btn btn-outline btn-primary" value="<?php echo _("Save settings"); ?>" name="save-firewall" />
<input type="submit" class="btn btn-success firewall-apply" value="<?php echo _("Enable Firewall") ?>" name="firewall-enable" data-toggle="modal" data-target="#firewallModal"/>
<?php endif ?>
</form>
</div><!-- /.card-body -->
<div class="card-footer"></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->
<!-- Modal -->
<div class="modal fade" id="firewallModal" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="ModalLabel">
<i class="fas fa-sync-alt mr-2"></i><?php echo _("Executing firewall option") ?>
</div>
</div>
<div class="modal-body">
<div class="col-md-12 mb-3 mt-1">
<?php if($fw_conf["firewall-enable"]) echo _("Disabling firewall").'...'; else echo _("Enabling firewall").'...'; ?>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline btn-primary" data-dismiss="modal"><?php echo _("Close"); ?></button>
</div>
</div>
</div>
</div>

View File

@ -52,11 +52,22 @@
</p>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="cbxtxpower"><?php echo _("Transmit power (dBm)") ?></label>
<i class="fas fa-question-circle text-muted" data-toggle="tooltip" data-placement="auto" title="<?php echo _("dBm is a unit of level used to indicate that a power ratio is expressed in decibels (dB) with reference to one milliwatt (mW). 30 dBm is equal to 1000 mW, while 0 dBm equals 1.25 mW."); ?>"></i>
<?php
SelectorOptions('txpower', $arrTxPower, $txpower, 'cbxtxpower');
?>
<small id="txpower_help" class="text-muted"><?php echo _("Sets the <code>txpower</code> option for the AP interface and the configured country."); ?></small>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="max_num_sta"><?php echo _("Maximum number of clients") ?></label>
<input type="text" id="max_num_sta" class="form-control" name="max_num_sta" placeholder="2007" value="<?php echo $arrConfig["max_num_sta"] ?>" aria-describedby="max_num_sta_help">
<small id="max_num_sta_help" class="text-muted"><?php echo _("Configures the max_num_sta option of hostapd. The default and maximum is 2007. If empty or 0, the default applies.") ?></small>
<small id="max_num_sta_help" class="text-muted"><?php echo _("Configures the <code>max_num_sta</code> option of hostapd. The default and maximum is 2007. If empty or 0, the default applies.") ?></small>
</div>
</div>
<div class="row">

View File

@ -1,3 +1,15 @@
<?php ob_start() ?>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<input type="submit" class="btn btn-outline btn-primary" name="SaveOpenVPNSettings" value="Save settings" />
<?php if ($openvpnstatus[0] == 0) {
echo '<input type="submit" class="btn btn-success" name="StartOpenVPN" value="Start OpenVPN" />' , PHP_EOL;
} else {
echo '<input type="submit" class="btn btn-warning" name="StopOpenVPN" value="Stop OpenVPN" />' , PHP_EOL;
}
?>
<?php endif ?>
<?php $buttons = ob_get_clean(); ob_end_clean() ?>
<div class="row">
<div class="col-lg-12">
<div class="card">
@ -21,72 +33,58 @@
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li class="nav-item"><a class="nav-link active" id="clienttab" href="#openvpnclient" data-toggle="tab"><?php echo _("Client settings"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="logoutputtab" href="#openvpnlogoutput" data-toggle="tab"><?php echo _("Logfile output"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="configstab" href="#openvpnconfigs" data-toggle="tab"><?php echo _("Configurations"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="loggingtab" href="#openvpnlogging" data-toggle="tab"><?php echo _("Logging"); ?></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="openvpnclient">
<h4 class="mt-3"><?php echo _("Client settings"); ?></h4>
<div class="row">
<div class="col">
<div class="row mb-2">
<div class="col-lg-12 mt-2 mb-2">
<div class="row ml-1">
<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>
<div class="row">
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Username"); ?></label>
<input type="text" class="form-control" name="authUser" value="<?php echo htmlspecialchars($authUser, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Password"); ?></label>
<input type="password" class="form-control" name="authPassword" value="<?php echo htmlspecialchars($authPassword, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12">
<div class="custom-file">
<input type="file" class="custom-file-input" name="customFile" id="customFile">
<label class="custom-file-label" for="customFile"><?php echo _("Select OpenVPN configuration file (.ovpn)"); ?></label>
</div>
</div>
</div>
</div><!-- col-->
<div class="col-sm">
<a href="https://go.nordvpn.net/aff_c?offer_id=15&aff_id=36402&url_id=902"><img src="app/img/no-trace-200x200.png" class="float-left mb-3 mt-3"></a>
</div>
</div><!-- main row -->
</div>
<div class="tab-pane fade" id="openvpnlogoutput">
<h4 class="mt-3"><?php echo _("Client log"); ?></h4>
<div class="row">
<div class="form-group col-md-8">
<?php
echo '<textarea class="logoutput"></textarea>';
?>
</div>
</div>
</div>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<input type="submit" class="btn btn-outline btn-primary" name="SaveOpenVPNSettings" value="Save settings" />
<?php if ($openvpnstatus[0] == 0) {
echo '<input type="submit" class="btn btn-success" name="StartOpenVPN" value="Start OpenVPN" />' , PHP_EOL;
} else {
echo '<input type="submit" class="btn btn-warning" name="StopOpenVPN" value="Stop OpenVPN" />' , PHP_EOL;
}
?>
<?php endif ?>
</form>
</div>
<?php echo renderTemplate("openvpn/general", $__template_data) ?>
<?php echo renderTemplate("openvpn/configs", $__template_data) ?>
<?php echo renderTemplate("openvpn/logging", $__template_data) ?>
</div><!-- /.tab-content -->
<?php echo $buttons ?>
</form>
</div><!-- /.card-body -->
<div class="card-footer"> Information provided by openvpn</div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
<div class="card-footer"><?php echo _("Information provided by openvpn"); ?></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->
<!-- modal confirm-delete-->
<div class="modal fade" id="ovpn-confirm-delete" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="ModalLabel"><i class="far fa-trash-alt mr-2"></i><?php echo _("Delete OpenVPN client"); ?></div>
</div>
<div class="modal-body">
<div class="col-md-12 mb-3 mt-1"><?php echo _("Delete client configuration? This cannot be undone."); ?></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal"><?php echo _("Cancel"); ?></button>
<button type="button" class="btn btn-outline-danger btn-delete"><?php echo _("Delete"); ?></button>
</div>
</div>
</div>
</div>
<!-- modal confirm-enable -->
<div class="modal fade" id="ovpn-confirm-activate" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="ModalLabel"><i class="far fa-check-circle mr-2"></i><?php echo _("Activate OpenVPN client"); ?></div>
</div>
<div class="modal-body">
<div class="col-md-12 mb-3 mt-1"><?php echo _("Activate client configuration? This will restart the openvpn-client service."); ?></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal"><?php echo _("Cancel"); ?></button>
<button type="button" class="btn btn-outline-success btn-activate"><?php echo _("Activate"); ?></button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,35 @@
<div class="tab-pane fade" id="openvpnconfigs">
<div class="row">
<div class="col-md">
<h4 class="mt-3 mb-3"><?php echo _("Configurations"); ?></h4>
<p id="openvpnconfigs-description" class="mb-3">
<small><?php echo _("Currently available OpenVPN client configurations are displayed below.") ?></small>
<br><small class="text-muted"><?php echo _("Activating a configuraton will restart the <code>openvpn-client</code> service.") ?></small>
</p>
<div class="openvpn-configs js-openvpn-configs-container">
<?php foreach ($clients as $client) :
if ($client == $conf_default) {
$btn_class = "active";
} else {
$btn_class = "disabled";
}
$label = preg_replace('/_client$/','',pathinfo($client, PATHINFO_FILENAME));
$client = $label;
?>
<div class="row mt-2" id="openvpn-client-row-<?php echo htmlspecialchars($client, ENT_QUOTES); ?>" >
<div class="col-md-6 col-xs-4">
<label><?php echo htmlspecialchars($label, ENT_QUOTES); ?></label>
</div>
<div class="col-md-auto px-lg-3 col-xs-2">
<button type="button" class="btn btn-outline-success <?php echo $btn_class; ?> js-activate-openvpn-client" data-record-id="<?php echo htmlspecialchars($client, ENT_QUOTES); ?>" data-toggle="modal" data-target="#ovpn-confirm-activate" /><i class="far fa-check-circle"></i></button>
</div>
<div class="col-md-auto col-xs-2">
<button type="button" class="btn btn-outline-danger js-remove-openvpn-client" data-record-id="<?php echo htmlspecialchars($client, ENT_QUOTES); ?>" data-toggle="modal" data-target="#ovpn-confirm-delete" /><i class="far fa-trash-alt"></i></button>
</div>
</div><!-- ./row openvpn-client -->
<?php endforeach ?>
</div><!-- /.openvpn-configs -->
<div class="mb-3"></div>
</div><!-- /.tab-pane | manage configs tab -->
</div>
</div>

View File

@ -0,0 +1,70 @@
<div class="tab-pane active" id="openvpnclient">
<h4 class="mt-3"><?php echo _("Client settings"); ?></h4>
<div class="row">
<div class="col-lg-8">
<div class="row mb-2">
<div class="col-lg-12 mt-2 mb-2">
<div class="row ml-1">
<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>
<h5><?php echo _("Authentification Method"); ?></h5>
<div class="col-sm-12 mt-2 mb-2 form-check">
<input class="form-check-input" id="ovpn-userpw" name="sel1" value="userpw" data-toggle="" data-parent="#clientsettings" data-target="#UserPW" type="radio" checked>
<label class="form-check-label"><?php echo _("Username and password"); ?></label>
</div>
<div class="col-sm-12 mt-2 mb-2 form-check">
<input class="form-check-input" id="ovpn-certs" name="sel1" value="certs" data-toggle="" data-parent="#clientsettings" data-target="#Certs" type="radio">
<label class="form-check-label"><?php echo _("Certificates"); ?></label>
</div>
<div class="col-sm-12 ml-2">
<div class="panel-group" id="clientsettings">
<div class="panel panel-default panel-collapse" id="PanelUserPW" >
<div class="panel-heading">
<h5 class="panel-title"><?php echo _("Enter username and password"); ?></h5>
</div>
<div class="panel-body">
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Username"); ?></label>
<input type="text" class="form-control" name="authUser" value="<?php echo htmlspecialchars($authUser, ENT_QUOTES); ?>" />
</div>
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Password"); ?></label>
<input type="password" class="form-control" name="authPassword" value="<?php echo htmlspecialchars($authPassword, ENT_QUOTES); ?>" />
</div>
</div>
</div><!-- panel -->
<div class="panel panel-default panel-collapse collapse in" id="PanelCerts">
<div class="panel-body">
<div class="panel-heading">
<h5 class="panel-title"><?php echo _("Certificates in the configuration file"); ?></h5>
</div>
<p><?php echo _("RaspAP supports certificates by including them in the configuration file."); ?>
<ul>
<small>
<li><?php echo _("Signing certification authority (CA) certificate (e.g. <code>ca.crt</code>): enclosed in <code>&lt;ca> ... &lt;/ca></code> tags."); ?></li>
<li><?php echo _("Client certificate (public key) (e.g. <code>client.crt</code>): enclosed in <code>&lt;cert> ... &lt;/cert></code> tags."); ?></li>
<li><?php echo _("Private key of the client certificate (e.g. <code>client.key</code>): enclosed in <code>&lt;key> ... &lt;/key></code> tags."); ?></li>
</small>
</ul>
</p>
</div>
</div> <!-- panel -->
</div> <!-- panel-group -->
</div> <!-- col -->
<div class="col-sm-12 ">
<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="customFile" id="customFile">
<label class="custom-file-label" for="customFile"><?php echo _("Select OpenVPN configuration file (.ovpn)"); ?></label>
</div>
</div>
</div> <!-- col -->
</div><!-- col-8 -->
<div class="col-sm-auto"></div>
</div><!-- /.row -->
</div><!-- /.tab-pane | general tab -->

View File

@ -0,0 +1,16 @@
<!-- logging tab -->
<div class="tab-pane fade" id="openvpnlogging">
<h4 class="mt-3 mb-3"><?php echo _("Logging") ?></h4>
<p><?php echo _("Enable this option to log <code>openvpn</code> activity.") ?></p>
<div class="custom-control custom-switch">
<input class="custom-control-input" id="log-openvpn" type="checkbox" name="log-openvpn" value="1" <?php echo $logEnable ? ' checked="checked"' : "" ?> aria-describedby="log-openvpn">
<label class="custom-control-label" for="log-openvpn"><?php echo _("Enable logging") ?></label>
</div>
<div class="row">
<div class="form-group col-md-8 mt-2">
<textarea class="logoutput"><?php echo htmlspecialchars($logOutput, ENT_QUOTES); ?></textarea>
</div>
</div>
</div><!-- /.tab-pane -->

View File

@ -17,7 +17,7 @@
</div>
<div class="col-xs-3 col-sm-3">
<label for="code"><?php echo _("Color"); ?></label>
<input class="form-control color-input" value="#d8224c" aria-label="color" />
<input class="form-control color-input" value="#2b8080" aria-label="color" />
</div>
</div>
<form action="system_info" method="POST">

0
templates/torproxy.php Normal file → Executable file
View File

108
templates/wg/general.php Normal file
View File

@ -0,0 +1,108 @@
<!-- wireguard settings tab -->
<div class="tab-pane active" id="wgsettings">
<div class="row">
<div class="col-lg-8">
<h4 class="mt-3"><?php echo _("Tunnel settings"); ?></h4>
<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>
<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="col-sm-12 ml-2">
<div class="panel-group" id="serversettings">
<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">
<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><!-- /.tab-pane | settings tab -->

19
templates/wg/logging.php Normal file
View File

@ -0,0 +1,19 @@
<!-- wireguard logging tab -->
<div class="tab-pane fade" id="wglogging">
<div class="row">
<div class="col-md-12">
<h4 class="mt-3"><?php echo _("Logging"); ?></h4>
<p><?php echo _("Enable this option to display an updated <code>wg-quick</code> debug log.") ?></p>
<div class="custom-control custom-switch">
<input class="custom-control-input" id="wgLogEnable" type="checkbox" name="wgLogEnable" value="1" <?php echo $optLogEnable ? ' checked="checked"' : "" ?> aria-describedby="wgLogEnable">
<label class="custom-control-label" for="wgLogEnable"><?php echo _("Logfile output") ?></label>
</div>
<?php
exec('sudo chmod o+r /tmp/wireguard.log');
$log = file_get_contents('/tmp/wireguard.log');
echo '<textarea class="logoutput my-3">'.htmlspecialchars($log, ENT_QUOTES).'</textarea>';
?>
</div>
</div><!-- /.row -->
</div><!-- /.tab-pane | logging tab -->

82
templates/wg/peers.php Normal file
View File

@ -0,0 +1,82 @@
<!-- wireguard peers tab -->
<div class="tab-pane fade" id="wgpeers">
<div class="row">
<div class="col-md-6">
<h4 class="mt-3"><?php echo _("Peer"); ?></h4>
<div class="input-group">
<input type="hidden" name="peer_id" value="1">
<div class="custom-control custom-switch">
<input class="custom-control-input" id="peer_enabled" type="checkbox" name="wg_penabled" value="1" <?php echo $wg_penabled ? ' checked="checked"' : "" ?> aria-describedby="endpoint-description">
<label class="custom-control-label" for="peer_enabled"><?php echo _("Enable peer") ?></label>
</div>
<p id="wg-description">
<small><?php echo _("Enable this option to encrypt traffic by creating a tunnel between RaspAP and this peer.") ?></small>
<small><?php echo _("This option adds <code>client.conf</code> to the WireGuard configuration.") ?></small>
</p>
</div>
<div class="row">
<div class="col-xs-3 col-sm-6 mt-3">
<label for="code"><?php echo _("Peer public key"); ?></label>
</div>
<div class="input-group col-md-12">
<input type="text" class="form-control" name="wg-peer" id="wg-peerpubkey" value="<?php echo htmlspecialchars($wg_peerpubkey, 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-peer-pubkey-status" class="input-group-addon check-hidden ml-2 mt-1"><i class="fas fa-check"></i></span>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-xs-3 col-sm-3 mt-3">
<label for="code"><?php echo _("Local Port"); ?></label>
<input type="text" class="form-control" name="wg_plistenport" value="<?php echo htmlspecialchars($wg_plistenport, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-xs-3 col-sm-6">
<label for="code"><?php echo _("IP Address"); ?></label>
<input type="text" class="form-control" name="wg_pipaddress" value="<?php echo htmlspecialchars($wg_pipaddress, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-xs-3 col-sm-6">
<label for="code"><?php echo _("Endpoint address"); ?></label>
<input type="text" class="form-control" name="wg_pendpoint" value="<?php echo htmlspecialchars($wg_pendpoint, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="col-xs-3 col-sm-6">
<label for="code"><?php echo _("Allowed IPs"); ?></label>
<input type="text" class="form-control mb-3" name="wg_pallowedips" value="<?php echo htmlspecialchars($wg_pallowedips, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="col-xs-3 col-sm-6">
<label for="code"><?php echo _("Persistent keepalive"); ?></label>
<input type="text" class="form-control col-sm-3 mb-3" name="wg_pkeepalive" value="<?php echo htmlspecialchars($wg_pkeepalive, ENT_QUOTES); ?>" />
</div>
</div>
</div>
<div class="col-md-6 mt-5">
<figure class="figure w-75 ml-3">
<?php if ($wg_penabled == true ) : ?>
<img src="app/img/wg-qr-code.php" class="figure-img img-fluid" alt="RaspAP Wifi QR code" style="width:100%;">
<figcaption class="figure-caption">
<?php echo _("Scan this QR code with your client to connect to this tunnel"); ?>
<?php echo _("or download the <code>client.conf</code> file to your device."); ?>
</figcaption>
<button class="btn btn-outline-secondary rounded-right wg-client-dl mt-2" type="button"><?php echo _("Download"); ?> <i class="fas fa-download ml-1"></i></button>
<?php endif; ?>
</figure>
</div>
</div><!-- /.row -->
</div><!-- /.tab-pane | peers tab -->

View File

@ -14,13 +14,11 @@
</div>
<?php endif ?>
<?php $index = 0; ?>
<?php if (!empty($connected)): ?>
<h4 class="h-underlined my-3"><?php echo _("Connected") ?></h4>
<div class="card-grid">
<?php foreach ($connected as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php foreach ($connected as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>
@ -30,8 +28,8 @@
<?php if (!empty($known)): ?>
<h4 class="h-underlined my-3"><?php echo _("Known") ?></h4>
<div class="card-grid">
<?php foreach ($known as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php foreach ($known as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>
@ -41,8 +39,8 @@
<?php if (!empty($nearby)): ?>
<h4 class="h-underlined my-3"><?php echo _("Nearby") ?></h4>
<div class="card-grid">
<?php foreach ($nearby as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php foreach ($nearby as $network) : ?>
<?php $index = isset($network['index']) ? $network['index'] : -1; ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>

53
templates/wireguard.php Executable file
View File

@ -0,0 +1,53 @@
<?php ob_start() ?>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<input type="submit" class="btn btn-outline btn-primary" name="savewgsettings" value="<?php echo _("Save settings"); ?>">
<?php if ($wg_state) : ?>
<input type="submit" class="btn btn-warning" name="stopwg" value="<?php echo _("Stop WireGuard"); ?>">
<?php else : ?>
<input type="submit" class="btn btn-success" name="startwg" value="<?php echo _("Start WireGuard"); ?>">
<?php endif ?>
<?php endif ?>
<?php $buttons = ob_get_clean(); ob_end_clean() ?>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<span class="ra-wireguard mr-2"></span><?php echo _("WireGuard"); ?>
</div>
<div class="col">
<button class="btn btn-light btn-icon-split btn-sm service-status float-right">
<span class="icon text-gray-600"><i class="fas fa-circle service-status-<?php echo $serviceStatus ?>"></i></span>
<span class="text service-status">wg <?php echo _($serviceStatus) ?></span>
</button>
</div>
</div><!-- /.row -->
</div><!-- /.card-header -->
<div class="card-body">
<?php $status->showMessages(); ?>
<form role="form" action="/wg_conf" enctype="multipart/form-data" method="POST">
<?php echo CSRFTokenFieldTag() ?>
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li class="nav-item"><a class="nav-link active" id="settingstab" href="#wgsettings" data-toggle="tab"><?php echo _("Settings"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="peertab" href="#wgpeers" data-toggle="tab"><?php echo _("Peer"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="loggingtab" href="#wglogging" data-toggle="tab"><?php echo _("Logging"); ?></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<?php echo renderTemplate("wg/general", $__template_data) ?>
<?php echo renderTemplate("wg/peers", $__template_data) ?>
<?php echo renderTemplate("wg/logging", $__template_data) ?>
</div><!-- /.tab-content -->
<?php echo $buttons ?>
</form>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo _("Information provided by wireguard"); ?></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->

View File

@ -645,9 +645,9 @@ camelcase@^5.0.0:
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
caniuse-lite@^1.0.30000998, caniuse-lite@^1.0.30001219:
version "1.0.30001228"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa"
integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==
version "1.0.30001230"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==
caseless@~0.12.0:
version "0.12.0"
@ -1179,9 +1179,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.723:
version "1.3.738"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz#aec24b091c82acbfabbdcce08076a703941d17ca"
integrity sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==
version "1.3.739"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9"
integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==
emoji-regex@^7.0.1:
version "7.0.3"
@ -2756,16 +2756,11 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2:
dependencies:
brace-expansion "^1.1.7"
minimist@^1.1.3, minimist@^1.2.5:
minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"