Merge pull request #1416 from RaspAP/feat/vpn-providers

Custom VPN provider support
This commit is contained in:
Bill Zimmerman 2023-10-27 13:38:54 +02:00 committed by GitHub
commit 4f3e00fe56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 673 additions and 4 deletions

View File

@ -75,8 +75,8 @@ License: GNU General Public License v3.0
.service-status-down { .service-status-down {
color: #f80107 !important; color: #f80107 !important;
animation: flash 1s linear infinite;
} }
@keyframes flash { @keyframes flash {
50% { 50% {
opacity: 0; opacity: 0;
@ -88,6 +88,8 @@ License: GNU General Public License v3.0
height: 20rem; height: 20rem;
border: 1px solid #d1d3e2; border: 1px solid #d1d3e2;
border-radius: .35rem; border-radius: .35rem;
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace;
font-size: 0.8rem;
} }
.dhcp-static-leases { .dhcp-static-leases {

View File

@ -42,6 +42,12 @@ body {
background-color: #fff; background-color: #fff;
} }
.btn-primary.disabled {
color: <?php echo $color; ?> !important;
border-color: <?php echo $color; ?> !important;
background-color: #fff !important;
}
.card-footer, .modal-footer { .card-footer, .modal-footer {
background-color: #f2f1f0; background-color: #f2f1f0;
} }

View File

@ -3,6 +3,7 @@
define('RASPI_BRAND_TEXT', 'RaspAP'); define('RASPI_BRAND_TEXT', 'RaspAP');
define('RASPI_CONFIG', '/etc/raspap'); define('RASPI_CONFIG', '/etc/raspap');
define('RASPI_CONFIG_NETWORK', RASPI_CONFIG.'/networking/defaults.json'); define('RASPI_CONFIG_NETWORK', RASPI_CONFIG.'/networking/defaults.json');
define('RASPI_CONFIG_PROVIDERS', 'config/vpn-providers.json');
define('RASPI_ADMIN_DETAILS', RASPI_CONFIG.'/raspap.auth'); define('RASPI_ADMIN_DETAILS', RASPI_CONFIG.'/raspap.auth');
define('RASPI_WIFI_AP_INTERFACE', 'wlan0'); define('RASPI_WIFI_AP_INTERFACE', 'wlan0');
define('RASPI_CACHE_PATH', sys_get_temp_dir() . '/raspap'); define('RASPI_CACHE_PATH', sys_get_temp_dir() . '/raspap');
@ -43,6 +44,7 @@ define('RASPI_NETWORK_ENABLED', true);
define('RASPI_DHCP_ENABLED', true); define('RASPI_DHCP_ENABLED', true);
define('RASPI_ADBLOCK_ENABLED', false); define('RASPI_ADBLOCK_ENABLED', false);
define('RASPI_OPENVPN_ENABLED', false); define('RASPI_OPENVPN_ENABLED', false);
define('RASPI_VPN_PROVIDER_ENABLED', false);
define('RASPI_WIREGUARD_ENABLED', false); define('RASPI_WIREGUARD_ENABLED', false);
define('RASPI_TORPROXY_ENABLED', false); define('RASPI_TORPROXY_ENABLED', false);
define('RASPI_CONFAUTH_ENABLED', true); define('RASPI_CONFAUTH_ENABLED', true);

55
config/vpn-providers.json Normal file
View File

@ -0,0 +1,55 @@
{
"providers": [
{
"id": 1,
"name": "ExpressVPN",
"bin_path": "/usr/bin/expressvpn",
"install_page": "https://www.expressvpn.com/support/vpn-setup/app-for-linux/",
"account_page": "https://www.expressvpn.com/subscriptions",
"cmd_overrides": {
"countries": "list all",
"log": "diagnostics",
"version": "-v"
},
"regex": {
"status": "\/not connected\/",
"pattern": "\/^(.{2,5})\\s(?:.{1,28})(.{1,26}).*$\/",
"replace": "$1,$2",
"slice": 3
}
},
{
"id": 2,
"name": "Mullvad VPN",
"bin_path": "/usr/bin/mullvad",
"install_page": "https://mullvad.net/en/download/vpn/linux",
"account_page": "https://mullvad.net/en/account",
"cmd_overrides": {
"account": "account get",
"countries": "relay list",
"log": "status -v",
"version": "--version"
},
"regex": {
"status": "\/disconnected\/",
"pattern": "\/^(.*),.*$\/",
"replace": "$1"
}
},
{
"id": 3,
"name": "NordVPN",
"bin_path": "/usr/bin/nordvpn",
"install_page": "https://nordvpn.com/download/linux/",
"account_page": "https://my.nordaccount.com/dashboard/",
"cmd_overrides": {
"log": "status"
},
"regex": {
"status": "\/status: disconnected\/",
"pattern": "(\\w+)\\s+",
"replace": "$1,$1\\n"
}
}
]
}

View File

@ -8,6 +8,7 @@ $defaults = [
'RASPI_BRAND_TEXT' => 'RaspAP', 'RASPI_BRAND_TEXT' => 'RaspAP',
'RASPI_VERSION' => '2.9.7', 'RASPI_VERSION' => '2.9.7',
'RASPI_CONFIG_NETWORK' => RASPI_CONFIG.'/networking/defaults.json', 'RASPI_CONFIG_NETWORK' => RASPI_CONFIG.'/networking/defaults.json',
'RASPI_CONFIG_PROVIDERS' => 'config/vpn-providers.json',
'RASPI_ADMIN_DETAILS' => RASPI_CONFIG.'/raspap.auth', 'RASPI_ADMIN_DETAILS' => RASPI_CONFIG.'/raspap.auth',
'RASPI_WIFI_AP_INTERFACE' => 'wlan0', 'RASPI_WIFI_AP_INTERFACE' => 'wlan0',
'RASPI_CACHE_PATH' => sys_get_temp_dir() . '/raspap', 'RASPI_CACHE_PATH' => sys_get_temp_dir() . '/raspap',
@ -45,6 +46,7 @@ $defaults = [
'RASPI_DHCP_ENABLED' => true, 'RASPI_DHCP_ENABLED' => true,
'RASPI_ADBLOCK_ENABLED' => false, 'RASPI_ADBLOCK_ENABLED' => false,
'RASPI_OPENVPN_ENABLED' => false, 'RASPI_OPENVPN_ENABLED' => false,
'RASPI_VPN_PROVIDER_ENABLED' => false,
'RASPI_WIREGUARD_ENABLED' => false, 'RASPI_WIREGUARD_ENABLED' => false,
'RASPI_TORPROXY_ENABLED' => false, 'RASPI_TORPROXY_ENABLED' => false,
'RASPI_CONFAUTH_ENABLED' => true, 'RASPI_CONFAUTH_ENABLED' => true,

View File

@ -169,6 +169,24 @@ function getDefaultNetOpts($svc,$key)
} }
} }
/**
* Returns a value for the specified VPN provider
*
* @param numeric $id
* @param string $key
* @return object $json
*/
function getProviderValue($id,$key)
{
$obj = json_decode(file_get_contents(RASPI_CONFIG_PROVIDERS), true);
if ($obj === null) {
return false;
} else {
$id--;
return $obj['providers'][$id][$key];
}
}
/* Functions to write ini files */ /* Functions to write ini files */
/** /**
@ -669,6 +687,7 @@ function initializeApp()
$_SESSION["theme_url"] = getThemeOpt(); $_SESSION["theme_url"] = getThemeOpt();
$_SESSION["toggleState"] = getSidebarState(); $_SESSION["toggleState"] = getSidebarState();
$_SESSION["bridgedEnabled"] = getBridgedState(); $_SESSION["bridgedEnabled"] = getBridgedState();
$_SESSION["providerID"] = getProviderID();
} }
function getThemeOpt() function getThemeOpt()
@ -709,6 +728,17 @@ function getBridgedState()
return $arrHostapdConf['BridgedEnable']; return $arrHostapdConf['BridgedEnable'];
} }
// Returns VPN provider ID, if defined
function getProviderID()
{
if (RASPI_VPN_PROVIDER_ENABLED) {
$arrProvider = parse_ini_file(RASPI_CONFIG.'/provider.ini');
if (isset($arrProvider['providerID'])) {
return $arrProvider['providerID'];
}
}
}
/** /**
* Validates the format of a CIDR notation string * Validates the format of a CIDR notation string
* *

View File

@ -27,6 +27,9 @@
case "/wg_conf": case "/wg_conf":
DisplayWireGuardConfig(); DisplayWireGuardConfig();
break; break;
case "/provider_conf":
DisplayProviderConfig();
break;
case "/torproxy_conf": case "/torproxy_conf":
DisplayTorProxyConfig(); DisplayTorProxyConfig();
break; break;

316
includes/provider.php Executable file
View File

@ -0,0 +1,316 @@
<?php
require_once 'includes/config.php';
/*
* Display VPN provider configuration
*/
function DisplayProviderConfig()
{
// initialize status object
$status = new \RaspAP\Messages\StatusMessage;
// set defaults
$id = $_SESSION["providerID"];
$binPath = getProviderValue($id, "bin_path");
$providerName = getProviderValue($id, "name");
$providerVersion = getProviderVersion($id, $binPath);
$installPage = getProviderValue($id, "install_page");
$publicIP = get_public_ip();
$serviceStatus = 'down';
$statusDisplay = 'down';
if (!file_exists($binPath)) {
$status->addMessage(sprintf(_('Expected %s binary not found at: %s'), $providerName, $binPath), 'warning');
$status->addMessage(sprintf(_('Visit the <a href="%s" target="_blank">installation instructions</a> for %s\'s Linux CLI.'), $installPage, $providerName), 'warning');
$ctlState = 'disabled';
$providerVersion = 'not found';
} elseif (empty($providerVersion)) {
$status->addMessage(sprintf(_('Unable to execute %s binary found at: %s'), $providerName, $binPath), 'warning');
$status->addMessage(_('Check that binary is executable and permissions exist in raspap.sudoers'), 'warning');
$ctlState = 'disabled';
$providerVersion = 'not found';
} else {
// fetch provider status
$serviceStatus = getProviderStatus($id, $binPath);
$statusDisplay = $serviceStatus == "down" ? "inactive" : "active";
// fetch provider log
$providerLog = getProviderLog($id, $binPath, $country);
// fetch account info
$accountInfo = getAccountInfo($id, $binPath, $providerName);
$accountLink = getProviderValue($id, "account_page");
// fetch available countries
$countries = getCountries($id, $binPath);
}
if (!RASPI_MONITOR_ENABLED) {
if (isset($_POST['SaveProviderSettings'])) {
if (isset($_POST['country'])) {
$country = trim($_POST['country']);
if (strlen($country) == 0) {
$status->addMessage('Select a country from the server location list', 'danger');
} else {
$return = saveProviderConfig($status, $binPath, $country, $id);
}
}
} elseif (isset($_POST['StartProviderVPN'])) {
$status->addMessage('Attempting to connect VPN provider', 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'connect');
exec("sudo $binPath $cmd", $return);
$return = stripArtifacts($return);
foreach ($return as $line) {
if (strlen(trim($line)) > 0) {
$line = preg_replace('/\e\[\?[0-9]*l\s(.*)\e.*$/', '$1', $line);
$line = preg_replace('/\e\[0m\e\[[0-9;]*m(.*)/', '$1', $line);
$status->addMessage($line, 'info');
}
}
} elseif (isset($_POST['StopProviderVPN'])) {
$status->addMessage('Attempting to disconnect VPN provider', 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'disconnect');
exec("sudo $binPath $cmd", $return);
$return = stripArtifacts($return);
foreach ($return as $line) {
if (strlen(trim($line)) > 0) {
$line = preg_replace('/\[1;33;49m(.*)\[0m/', '$1', $line);
$status->addMessage($line, 'info');
}
}
}
}
echo renderTemplate(
"provider", compact(
"status",
"serviceStatus",
"statusDisplay",
"providerName",
"providerVersion",
"accountInfo",
"accountLink",
"countries",
"country",
"providerLog",
"publicIP",
"ctlState"
)
);
}
/**
* Validates VPN provider settings
*
* @param object $status
* @param string $binPath
* @param string $country
* @param integer $id (optional)
*/
function saveProviderConfig($status, $binPath, $country, $id = null)
{
$status->addMessage(sprintf(_('Attempting to connect to %s'),$country), 'info');
$cmd = getCliOverride($id, 'cmd_overrides', 'connect');
// mullvad requires relay set location before connect
if ($id == 2) {
exec("sudo $binPath relay set location $country", $return);
exec("sudo $binPath $cmd", $return);
} else {
exec("sudo $binPath $cmd $country", $return);
}
$return = stripArtifacts($return);
foreach ($return as $line) {
if ( strlen(trim($line)) >0 ) {
$status->addMessage($line, 'info');
}
}
}
/**
* Removes artifacts from shell_exec string values
*
* @param string $output
* @param string $pattern
* @return string $result
*/
function stripArtifacts($output, $pattern = null)
{
$result = preg_replace('/[-\/\n\t\\\\'.$pattern.'|]/', '', $output);
return $result;
}
/**
* Retrieves an override for provider CLI
*
* @param integer $id
* @param string $group
* @param string $item
* @return string $override
*/
function getCliOverride($id, $group, $item)
{
$obj = json_decode(file_get_contents(RASPI_CONFIG_PROVIDERS), true);
if ($obj === null) {
return false;
} else {
$id--;
if ($obj['providers'][$id][$group][$item] === null) {
return $item;
} else {
return $obj['providers'][$id][$group][$item];
}
}
}
/**
* Retreives VPN provider status
*
* @param integer $id
* @param string $binPath
* @return string $status
*/
function getProviderStatus($id, $binPath)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'status');
$pattern = getCliOverride($id, 'regex', 'status');
exec("sudo $binPath $cmd", $cmd_raw);
$cmd_raw = strtolower(stripArtifacts($cmd_raw[0]));
if (!empty($cmd_raw[0])) {
if (preg_match($pattern, $cmd_raw, $match)) {
$status = "down";
} else {
$status = "up";
}
} else {
$status = "down";
}
return $status;
}
/**
* Retrieves available countries
*
* @param integer $id
* @param string $binPath
* @return array $countries
*/
function getCountries($id, $binPath)
{
$countries = [];
$cmd = getCliOverride($id, 'cmd_overrides', 'countries');
$pattern = getCliOverride($id, 'regex', 'pattern');
$replace = getCliOverride($id, 'regex', 'replace');
$slice = getCliOverride($id, 'regex', 'slice');
exec("sudo $binPath $cmd", $output);
// CLI country output differs considerably between different providers.
// Ideally, custom parsing would be avoided in favor of a pure regex solution
switch ($id) {
case 1: // expressvpn
$output = array_slice($output, $slice);
foreach ($output as $item) {
$item = preg_replace($pattern, $replace, $item);
$parts = explode(',', $item);
$key = trim($parts[0]);
$value = trim($parts[1]);
$countries[$key] = $value;
}
break;
case 2: // mullvad
foreach ($output as $item) {
$item = preg_replace($pattern, $replace, $item);
if (strlen(trim($item) >0)) {
preg_match('/\s+([a-z0-9-]+)\s.*$/', $item, $match);
if (count($match) > 1) {
$key = $match[1];
$item = str_pad($item, strlen($item)+16,' ', STR_PAD_LEFT);
$countries[$key] = $item;
} else {
preg_match('/\(([a-z]+)\)/', $item, $match);
$key = $match[1];
if (strlen($match[1]) == 3) {
$item = str_pad($item, strlen($item)+8,' ', STR_PAD_LEFT);
}
$countries[$key] = $item;
}
}
}
break;
case 3: // nordvpn
$output = stripArtifacts($output,'\s');
$arrTmp = explode(",", $output[0]);
$countries = array_combine($arrTmp, $arrTmp);
foreach ($countries as $key => $value) {
$countries[$key] = str_replace("_", " ", $value);
}
break;
default:
break;
}
$select = array(' ' => _("Select a country..."));
$countries = $select + $countries;
return $countries;
}
/**
* Retrieves provider log
*
* @param integer $id
* @param string $binPath
* @param string $country
* @return string $log
*/
function getProviderLog($id, $binPath, &$country)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'log');
exec("sudo $binPath $cmd", $cmd_raw);
$output = stripArtifacts($cmd_raw);
foreach ($output as $item) {
if (preg_match('/Country: (\w+)/', $item, $match)) {
$country = $match[1];
}
$providerLog.= ltrim($item) .PHP_EOL;
}
return $providerLog;
}
/**
* Retrieves provider version information
*
* @param integer $id
* @param string $binPath
* @return string $version
*/
function getProviderVersion($id, $binPath)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'version');
$version = shell_exec("sudo $binPath $cmd");
$version = preg_replace('/^[^\w]+\s*/', '', $version);
return $version;
}
/**
* Retrieves provider account info
*
* @param integer $id
* @param string $binPath
* @param string $providerName
* @return array
*/
function getAccountInfo($id, $binPath, $providerName)
{
$cmd = getCliOverride($id, 'cmd_overrides', 'account');
exec("sudo $binPath $cmd", $acct);
foreach ($acct as &$item) {
$item = preg_replace('/^[^\w]+\s*/', '', $item);
}
if (empty($acct)) {
$msg = sprintf(_("Account information not available from %s's Linux CLI."), $providerName);
$acct[] = $msg;
}
return $acct;
}

View File

@ -60,6 +60,11 @@
<a class="nav-link" href="wg_conf"><span class="ra-wireguard mr-2"></span><span class="nav-label"><?php echo _("WireGuard"); ?></a> <a class="nav-link" href="wg_conf"><span class="ra-wireguard mr-2"></span><span class="nav-label"><?php echo _("WireGuard"); ?></a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<?php if (RASPI_VPN_PROVIDER_ENABLED) : ?>
<li class="nav-item">
<a class="nav-link" href="provider_conf"><i class="fas fa-shield-alt fa-fw mr-2"></i><span class="nav-label"><?php echo _(getProviderValue($_SESSION["providerID"], "name")); ?></a>
</li>
<?php endif; ?>
<?php if (RASPI_TORPROXY_ENABLED) : ?> <?php if (RASPI_TORPROXY_ENABLED) : ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="torproxy_conf"><i class="fas fa-eye-slash fa-fw mr-2"></i><span class="nav-label"><?php echo _("TOR proxy"); ?></a> <a class="nav-link" href="torproxy_conf"><i class="fas fa-eye-slash fa-fw mr-2"></i><span class="nav-label"><?php echo _("TOR proxy"); ?></a>

View File

@ -45,6 +45,7 @@ require_once 'includes/data_usage.php';
require_once 'includes/about.php'; require_once 'includes/about.php';
require_once 'includes/openvpn.php'; require_once 'includes/openvpn.php';
require_once 'includes/wireguard.php'; require_once 'includes/wireguard.php';
require_once 'includes/provider.php';
require_once 'includes/torproxy.php'; require_once 'includes/torproxy.php';
initializeApp(); initializeApp();

View File

@ -59,6 +59,7 @@ function _install_raspap() {
_prompt_install_openvpn _prompt_install_openvpn
_install_mobile_clients _install_mobile_clients
_prompt_install_wireguard _prompt_install_wireguard
_prompt_install_vpn_providers
_patch_system_files _patch_system_files
_install_complete _install_complete
} }
@ -90,7 +91,7 @@ function _config_installation() {
fi fi
_install_log "Configure ${opt[2]}" _install_log "Configure ${opt[2]}"
_get_linux_distro _get_linux_distro
echo "Detected OS: ${DESC}" echo "Detected OS: ${DESC} ${LONG_BIT}-bit"
echo "Using GitHub repository: ${repo} ${branch} branch" echo "Using GitHub repository: ${repo} ${branch} branch"
echo "Configuration directory: ${raspap_dir}" echo "Configuration directory: ${raspap_dir}"
echo -n "lighttpd root: ${webroot_dir}? [Y/n]: " echo -n "lighttpd root: ${webroot_dir}? [Y/n]: "
@ -126,6 +127,7 @@ function _get_linux_distro() {
RELEASE=$(lsb_release -sr) RELEASE=$(lsb_release -sr)
CODENAME=$(lsb_release -sc) CODENAME=$(lsb_release -sc)
DESC=$(lsb_release -sd) DESC=$(lsb_release -sd)
LONG_BIT=$(getconf LONG_BIT)
elif [ -f /etc/os-release ]; then # freedesktop.org elif [ -f /etc/os-release ]; then # freedesktop.org
. /etc/os-release . /etc/os-release
OS=$ID OS=$ID
@ -239,7 +241,7 @@ function _install_dependencies() {
# Set dconf-set-selections # Set dconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections
sudo apt-get install -y lighttpd git hostapd dnsmasq iptables-persistent $php_package $dhcpcd_package $iw_package vnstat qrencode || _install_status 1 "Unable to install dependencies" sudo apt-get install -y lighttpd git hostapd dnsmasq iptables-persistent $php_package $dhcpcd_package $iw_package vnstat qrencode jq || _install_status 1 "Unable to install dependencies"
_install_status 0 _install_status 0
} }
@ -407,6 +409,69 @@ function _install_adblock() {
_install_status 0 _install_status 0
} }
# Prompt to install VPN providers
function _prompt_install_vpn_providers() {
_install_log "Configure VPN provider support (Beta)"
echo -n "Enable VPN provider client configuration? [Y/n]: "
if [ "$assume_yes" == 0 ]; then
read answer < /dev/tty
if [ "$answer" != "${answer#[Nn]}" ]; then
_install_status 0 "(Skipped)"
else
_install_provider
fi
else
echo "(Skipped)"
fi
}
# Install VPN provider client configuration
function _install_provider() {
echo -e "Select an option from the list:"
while true; do
json="$webroot_dir/config/"vpn-providers.json
while IFS='|' read -r key value; do
options["$key"]="$value"
done< <(jq -r '.providers[] | "\(.id)|\(.name)|\(.bin_path)"' "$json")
# display provider options
for key in "${!options[@]}"; do
echo " $key) ${options[$key]%%|*}"
done
echo " 0) None"
echo -n "Choose an option: "
read answer < /dev/tty
if [ "$answer" != "${answer#[0]}" ]; then
_install_status 0 "(Skipped)"
break
elif [[ "$answer" =~ ^[0-9]+$ ]] && [[ -n ${options[$answer]+abc} ]]; then
selected="${options[$answer]}"
echo "Configuring support for ${selected%%|*}"
bin_path=${selected#*|}
if ! grep -q "$bin_path" "$webroot_dir/installers/raspap.sudoers"; then
echo "Adding $bin_path to raspap.sudoers"
echo "www-data ALL=(ALL) NOPASSWD:$bin_path *" | sudo tee -a "$webroot_dir/installers/raspap.sudoers" > /dev/null || _install_status 1 "Unable to modify raspap.sudoers"
fi
echo "Enabling administration option for ${selected%%|*}"
sudo sed -i "s/\('RASPI_VPN_PROVIDER_ENABLED', \)false/\1true/g" "$webroot_dir/includes/config.php" || _install_status 1 "Unable to modify config.php"
echo "Adding VPN provider to $raspap_dir/provider.ini"
if [ ! -f "$raspap_dir/provider.ini" ]; then
sudo touch "$raspap_dir/provider.ini"
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to create $raspap_dir/provider.ini"
elif ! grep -q "providerID = $answer" "$raspap_dir/provider.ini"; then
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to write to $raspap_dir/provider.ini"
fi
_install_status 0
break
else
echo "Invalid choice. Select a valid option:"
fi
done
}
# Prompt to install openvpn # Prompt to install openvpn
function _prompt_install_openvpn() { function _prompt_install_openvpn() {
_install_log "Configure OpenVPN support" _install_log "Configure OpenVPN support"
@ -498,7 +563,13 @@ function _download_latest_files() {
_install_status 3 _install_status 3
echo "Insiders please read this: https://docs.raspap.com/insiders/#authentication" echo "Insiders please read this: https://docs.raspap.com/insiders/#authentication"
fi fi
git clone --branch $branch --depth 1 -c advice.detachedHead=false $git_source_url /tmp/raspap-webgui || _install_status 1 "Unable to download files from github" git clone --branch $branch --depth 1 -c advice.detachedHead=false $git_source_url /tmp/raspap-webgui || clone=false
if [ "$clone" = false ]; then
_install_status 1 "Unable to download files from github"
echo "The installer cannot continue." >&2
exit 1
fi
sudo mv /tmp/raspap-webgui $webroot_dir || _install_status 1 "Unable to move raspap-webgui to web root" sudo mv /tmp/raspap-webgui $webroot_dir || _install_status 1 "Unable to move raspap-webgui to web root"
if [ "$upgrade" == 1 ]; then if [ "$upgrade" == 1 ]; then

Binary file not shown.

View File

@ -1293,3 +1293,66 @@ msgstr "Enable Firewall"
msgid "Apply changes" msgid "Apply changes"
msgstr "Apply changes" msgstr "Apply changes"
#: includes/provider.php
msgid "Account details"
msgstr "Account details"
msgid "My account"
msgstr "My account"
msgid "Server location"
msgstr "Server location"
msgid "Choosing <strong>Save settings</strong> will connect to the selected country."
msgstr "Choosing <strong>Save settings</strong> will connect to the selected country."
msgid "Choosing <strong>Connect %s</strong> will connect to a recommended server."
msgstr "Choosing <strong>Connect %s</strong> will connect to a recommended server."
msgid "Select a country from the server location list"
msgstr "Select a country from the server location list"
msgid "Select a country..."
msgstr "Select a country..."
msgid "Account information not available from %s's Linux CLI."
msgstr "Account information not available from %s's Linux CLI."
msgid "Attempting to connect to %s"
msgstr "Attempting to connect to %s"
msgid "Attempting to connect VPN provider"
msgstr "Attempting to connect VPN provider"
msgid "Attempting to disconnect VPN provider"
msgstr "Attempting to disconnect VPN provider"
msgid "Expected %s binary not found at: %s"
msgstr "Expected %s binary not found at: %s"
msgid "Visit the <a href=\"%s\" target=\"_blank\">installation instructions</a> for %s's Linux CLI."
msgstr "Visit the <a href=\"%s\" target=\"_blank\">installation instructions</a> for %s's Linux CLI."
msgid "Unable to execute %s binary found at: %s"
msgstr "Unable to execute %s binary found at: %s"
msgid "Check that binary is executable and permissions exist in raspap.sudoers"
msgstr "Check that binary is executable and permissions exist in raspap.sudoers"
msgid "Installed Linux CLI: <code>%s</code>"
msgstr "Installed Linux CLI: <code>%s</code>"
msgid "Current <code>%s</code> connection status is displayed below."
msgstr "Current <code>%s</code> connection status is displayed below."
msgid "Information provided by %s"
msgstr "Information provided by %s"
msgid "Connect %s"
msgstr "Connect %s"
msgid "Disconnect %s"
msgstr "Disconnect %s"

51
templates/provider.php Executable file
View File

@ -0,0 +1,51 @@
<?php ob_start() ?>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<input type="submit" <?php echo $ctlState; ?> class="btn btn-outline btn-primary <?php echo $ctlState; ?>" name="SaveProviderSettings" value="<?php echo _("Save settings"); ?>" />
<?php if ($serviceStatus == 'down') : ?>
<input type="submit" <?php echo $ctlState; ?> class="btn btn-success <?php echo $ctlState; ?>" name="StartProviderVPN" value="<?php echo sprintf(_("Connect %s"), $providerName); ?>" />
<?php else : ?>
<input type="submit" <?php echo $ctlState; ?> class="btn btn-warning <?php echo $ctlState; ?>" name="StopProviderVPN" value="<?php echo sprintf(_("Disconnect %s"), $providerName); ?>" />
<?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">
<i class="fas fa-shield-alt fa-fw mr-2"></i><?php echo _($providerName); ?>
</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"><?php echo strtolower($providerName); ?> <?php echo _($statusDisplay) ?></span>
</button>
</div>
</div><!-- /.row -->
</div><!-- /.card-header -->
<div class="card-body">
<?php $status->showMessages(); ?>
<form role="form" action="provider_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="clienttab" href="#providerclient" data-toggle="tab"><?php echo _("Settings"); ?></a></li>
<li class="nav-item"><a class="nav-link" id="loggingtab" href="#providerstatus" data-toggle="tab"><?php echo _("Status"); ?></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<?php echo renderTemplate("provider/general", $__template_data) ?>
<?php echo renderTemplate("provider/status", $__template_data) ?>
</div><!-- /.tab-content -->
<?php echo $buttons ?>
</form>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo sprintf( _("Information provided by %s"), strtolower($providerName)); ?></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->

View File

@ -0,0 +1,48 @@
<div class="tab-pane active" id="providerclient">
<h4 class="mt-3"><?php echo sprintf(_("%s settings"), $providerName) ;?></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">
<i class="fas fa-globe-americas mr-1"></i><?php echo _("IPv4 Address"); ?>
</div>
<div class="info-value col-xs-3">
<?php echo htmlspecialchars($publicIP, ENT_QUOTES); ?><a class="text-gray-500" href="https://ipapi.co/<?php echo($publicIP); ?>" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt ml-2"></i></a>
</div>
</div>
</div>
</div>
</div>
</div>
<?php if (!empty($accountInfo)) : ?>
<div class="row">
<div class="col-md-6 mt-1">
<div class="card">
<div class="card-body">
<h5><?php echo _("Account details"); ?></h5>
<?php foreach ($accountInfo as $item) {
echo '<small>'. $item .'</small><br>';
} ?>
<a href="<?php echo($accountLink); ?>" target="_blank" class="btn btn-warning btn-sm mt-2"><i class="fas fa-external-link-alt ml-1 mr-1"></i><?php echo _("My account") ?></a>
</div><!-- /.card-body -->
</div><!-- /.card -->
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="form-group col-md-6 mt-3">
<h5><?php echo _("Server location"); ?></h5>
<div>
<small><?php echo _("Choosing <strong>Save settings</strong> will connect to the selected country."); ?></small>
</div>
<div class="mb-2">
<small><?php echo sprintf(_("Choosing <strong>Connect %s</strong> will connect to a recommended server."), $providerName); ?></small>
</div>
<label for="cbxhwmode"><?php echo _("Country") ;?></label>
<?php SelectorOptions('country', $countries, $country, 'cbxcountry'); ?>
</div>
</div>
</div><!-- /.tab-pane | general tab -->

View File

@ -0,0 +1,14 @@
<!-- logging tab -->
<div class="tab-pane fade" id="providerstatus">
<h4 class="mt-3 mb-3"><?php echo sprintf(_("%s status"), $providerName) ;?></h4>
<p><?php echo sprintf(_("Installed Linux CLI: <code>%s</code>"), $providerVersion); ?></p>
<p><?php echo sprintf(_("Current <code>%s</code> connection status is displayed below."), strtolower($providerName)); ?></p>
<div class="row">
<div class="form-group col-md-8 mt-2">
<textarea class="logoutput"><?php echo htmlspecialchars($providerLog, ENT_QUOTES); ?></textarea>
</div>
</div>
</div><!-- /.tab-pane -->