Skip to content

Commit

Permalink
Merge pull request #1131 from proditis/master
Browse files Browse the repository at this point in the history
Multiple improvements and fixes from dev environment
  • Loading branch information
proditis authored Mar 21, 2024
2 parents 1583647 + 8ab0391 commit f0d77af
Show file tree
Hide file tree
Showing 24 changed files with 509 additions and 59 deletions.
112 changes: 94 additions & 18 deletions backend/commands/VpnController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
use yii\helpers\Console;
use yii\console\Controller;
use app\modules\frontend\models\Player;
use app\modules\activity\models\PlayerLast;
use app\components\OpenVPN;
use yii\console\ExitCode;
/**
* Manages VPN specific operations.
*
Expand Down Expand Up @@ -65,7 +67,15 @@ public function actionKill($player)
throw new ConsoleException(Yii::t('app', 'Player not found with id or username of [{values}]', ['values' => $player]));
}
printf("Killing %d with last local IP [%s]\n",$pM->id,$pM->last->vpn_local_address_octet);
OpenVPN::kill($pM->id,intval($pM->last->vpn_local_address));
try {
OpenVPN::kill($pM->id,intval($pM->last->vpn_local_address));
}
catch(\Exception $e)
{
echo "Error: ",$e->getMessage(),"\n";
return ExitCode::UNSPECIFIED_ERROR;
}

}

/**
Expand All @@ -74,58 +84,124 @@ public function actionKill($player)
public function actionKillall()
{

foreach(Player::find()->where(['status'=>10])->all() as $pM)
foreach(PlayerLast::find()->all() as $pM)
{
printf("Logging out %d\n",$pM->id);
OpenVPN::logout($pM->id);
try {
if($pM->vpn_local_address!==null)
{
printf("Killing %s => %d\n",$pM->player->username,$pM->id);
OpenVPN::kill($pM->id,intval($pM->vpn_local_address));
}
}
catch(\Exception $e)
{
echo "Error: ",$e->getMessage(),"\n";
}
}
Yii::$app->db->createCommand("UPDATE player_last SET vpn_local_address=NULL, vpn_remote_address=NULL")->execute();

}
/**
* Logoutall stall connections from OpenVPN.
* Logout all stall connections from all player_last entries
*/
public function actionLogoutall()
{
Yii::$app->db->createCommand("UPDATE player_last SET vpn_local_address=NULL, vpn_remote_address=NULL")->execute();
}

/**
* Load configuration from filesystem
* Load OpenVPN configuration from filesystem and store to the database.
* Parses the configuration file for management interface and ranges.
* @param string $filename The filename to read and store to the database
*/
public function actionLoad($filepath)
{
$file=basename($filepath);
$conf=file_get_contents($filepath);
try{
$contents=file_get_contents($filepath);
Yii::$app->db->createCommand("UPDATE openvpn SET conf=:config WHERE name=:filename",[':config'=>$contents,':filename'=>$file])->execute();
if(preg_match('/server (.*) (.*)/',$conf,$matches) && count($matches)>1)
{
$ovpnModel=\app\modules\settings\models\Openvpn::find()->where(['name'=>$file,'net'=>ip2long($matches[1])]);
}
if(($ovpn=$ovpnModel->one())===null)
{
$ovpn=new \app\modules\settings\models\Openvpn;
}
$ovpn->conf=file_get_contents($filepath);
$ovpn->name=$file;
$ovpn->server=gethostbyaddr(gethostbyname(gethostname()));
if(preg_match('/status (.*)/',$conf,$matches) && count($matches)>1)
{
$ovpn->status_log=trim($matches[1]);
}
if(preg_match('/management (.*) (.*) (.*)/',$conf,$matches) && count($matches)>1)
{
$ovpn->management_ip_octet=$matches[1];
$ovpn->management_port=$matches[2];
if(str_starts_with($matches[3], '/'))
{
if(file_exists($matches[3]))
$ovpn->management_passwd=file_get_contents($matches[3]);
else
echo "WARNING: The provided config uses a file as a management password\n\t but the file [",$matches[3], "] does not exist!\n";
}
}
if(preg_match('/server (.*) (.*)/',$conf,$matches) && count($matches)>1)
{
$ovpn->net_octet=$matches[1];
$ovpn->mask_octet=$matches[2];
}
if($ovpn->save())
{
echo $ovpn->isNewRecord ? "Record created successfully!\n" : "Record updated successfully!\n";
}
else
{
echo "Failed to save record: ",$ovpn->getErrorSummary(true),"\n";
}
}
catch (\Exception $e)
{
printf("Error: ",$e->getMessage());
printf("Error: %s",$e->getMessage());
}

}
/**
* Save configuration to filesystem
* Save OpenVPN configuration to filesystem.
* Uses the provided file basename and current system hostname to find the actual entry.
* @param string $filepath The full path to store the config contents.
*/
public function actionSave($filepath)
{
try{
$file=basename($filepath);
$contents=Yii::$app->db->createCommand("SELECT conf FROM openvpn WHERE name=:filename",[':filename'=>$file])->queryScalar();
file_put_contents($filepath,$contents);
$ovpnModel=\app\modules\settings\models\Openvpn::find()->where(['server'=>gethostname(),'name'=>$file]);
if(($ovpn=$ovpnModel->one())===null)
{
echo "No record found for the given file and server!\n";
return ExitCode::CANTCREAT;
}
if(file_put_contents($filepath,$ovpn->conf))
{
echo "File saved at ",$filepath,"\n";
}
else
{
echo "Failed to save ",$filepath,"\n";
return ExitCode::UNSPECIFIED_ERROR;
}
}
catch (\Exception $e)
{
printf("Error: ",$e->getMessage());
printf("Error: %s",$e->getMessage());
}
}

/**
* Display openvpn status enriched with database details
*/
public function actionStatus($provider_id=null)
public function actionStatus()
{
$q=\app\modules\settings\models\Openvpn::find()->select('status_log')->andFilterWhere(['LIKE','provider_id',$provider_id]);
$q=\app\modules\settings\models\Openvpn::find()->select('status_log')->andFilterWhere(['server'=>gethostname()]);
$status['routing_table']=[];
$status['client_list']=[];
foreach($q->all() as $entry)
Expand All @@ -139,11 +215,11 @@ public function actionStatus($provider_id=null)
}
catch (\Exception $e)
{

printf("Error: %s",$e->getMessage());
}
unset($entry);
}
$this->stdout( sprintf("%-5s %-10s %-10s %-18s %-10s %-10s\n", 'ID', 'Username','Local IP','Remote IP', 'Received', 'Send'), Console::BOLD);
$this->stdout(sprintf("%-5s %-10s %-10s %-18s %-10s %-10s\n", 'ID', 'Username','Local IP','Remote IP', 'Received', 'Send'), Console::BOLD);
foreach($status['client_list'] as $entry)
{
$p=\app\modules\frontend\models\Player::findOne($entry->player_id);
Expand Down
8 changes: 6 additions & 2 deletions backend/components/OpenVPN.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ static public function kill(int $player_id,int $player_ip)
{
echo "connected to {$creds->management_ip_octet}\n";
fwrite($fp, "$creds->management_passwd\n");
echo "send {$creds->management_ip_octet}\n";
echo "sending to ",$creds->management_ip_octet,"\n";
usleep(250000);
fwrite($fp, "kill ${player_id}\n");
fwrite($fp, "kill $player_id\n");
usleep(250000);
fwrite($fp, "exit\n");
usleep(250000);
Expand All @@ -77,6 +77,10 @@ static public function determineServerByAddr(int $player_ip)

static public function parseStatus(string $location)
{
if(!file_exists($location))
{
throw new yii\base\UserException("Status file does not exist");
}
$statusLines=explode("\n",file_get_contents($location));
if(count($statusLines)==0)
return new stdClass;
Expand Down
112 changes: 112 additions & 0 deletions backend/components/validators/VerifymailValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Validate email with Verifymail.io
*/
namespace app\components\validators;

use yii\validators\Validator;
use yii\helpers\ArrayHelper;

class VerifymailValidator extends Validator
{
public $url = 'https://verifymail.io/api/';
public $message="Verifymail.io: Disposable email detected! Please use a different email address.";

public function init()
{
parent::init();
}

public function validateValue($value)
{
if(\Yii::$app->sys->signup_ValidatemailValidator===false)
return;

$data = http_build_query(['key'=>\Yii::$app->sys->verifymail_key]);

$domain=$value;

if(str_contains($value,'@'))
{
$parts=explode("@",$value);
if(count($parts)<2)
{
return ['Verifymail.io: Failed to parse email!', [
'email' => $value,
]];
}
$domain=end($parts);
}

$req=$this->url.$domain.'?'.$data;
$ch = curl_init($req);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);

try
{
$result = curl_exec($ch);
curl_close($ch);
$retData=json_decode($result);
if($retData != null && $retData->disposable===true)
{
return [$this->message, [
'email' => $value,
]];
}
}
catch(\Exception $e)
{
if(curl_errno($ch)===0)
return [$this->message, ['email' => $value]];
}
}

public function validateAttribute($model, $attribute)
{
if(\Yii::$app->sys->signup_ValidatemailValidator===false)
return;
$value = $model->$attribute;

$data = http_build_query(['key'=>\Yii::$app->sys->verifymail_key]);

if(str_contains($value,'@'))
{
$parts=explode("@",$value);
if(count($parts)<2)
{
return ['Verifymail.io: Failed to parse email!', [
'email' => $value,
]];
}
$domain=end($parts);
}

$req=$this->url.$domain.'?'.$data;
$ch = curl_init($req);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);

try
{
$result = curl_exec($ch);
curl_close($ch);
$retData=json_decode($result);
if($retData && $retData->message)
{
\Yii::error("Verifymail.io return message: ".$retData->message);
}
if($retData != null && $retData->disposable===true)
{
return [$this->message, ['email' => $value]];
}
}
catch(\Exception $e)
{
if(curl_errno($ch)===0)
return [$this->message, ['email' => $value]];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use yii\db\Migration;

/**
* Handles adding columns to table `{{%openvpn}}`.
*/
class m240320_235210_add_server_column_to_openvpn_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('{{%openvpn}}', 'server', $this->string()->after('id'));
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('{{%openvpn}}', 'server');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use yii\db\Migration;

/**
* Class m240320_235211_alter_openvpn_table_unique_keys
*/
class m240320_235211_alter_openvpn_table_unique_keys extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->dropIndex('name', 'openvpn');
$this->dropIndex('net', 'openvpn');
$this->createIndex('server_name_net', 'openvpn', ['server','name','net'], true );


}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropIndex('server_name_net', 'openvpn');
$this->createIndex('name', 'openvpn', ['name'], true );
$this->createIndex('net', 'openvpn', ['name'], true );
}
}
4 changes: 4 additions & 0 deletions backend/modules/activity/models/PlayerLast.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public function attributeLabels()
'signup_ip' => 'Signup IP',
];
}
public function resetVPN() {
return $this->updateAttributes(['vpn_remote_address' => null,'vpn_local_address'=>null]);
}

public function afterFind() {
parent::afterFind();
$this->signin_ipoctet=long2ip($this->signin_ip);
Expand Down
Loading

0 comments on commit f0d77af

Please sign in to comment.