|
@@ -25,10 +25,7 @@ use App\Models\{
|
|
|
TelegramSession,
|
|
|
UserSubscribeLog
|
|
|
};
|
|
|
-use App\Services\{
|
|
|
- Mail,
|
|
|
- Config
|
|
|
-};
|
|
|
+use App\Services\Config;
|
|
|
use App\Utils\{
|
|
|
GA,
|
|
|
QQWry,
|
|
@@ -37,18 +34,43 @@ use App\Utils\{
|
|
|
Telegram,
|
|
|
DatatablesHelper
|
|
|
};
|
|
|
-use Exception;
|
|
|
use ArrayObject;
|
|
|
-use RuntimeException;
|
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
|
|
-class Job
|
|
|
+class Job extends Command
|
|
|
{
|
|
|
- public static function syncnode()
|
|
|
+ public $description = ''
|
|
|
+ . '├─=: php xcat Job [选项]' . PHP_EOL
|
|
|
+ . '│ ├─ UserGa - 二次验证' . PHP_EOL
|
|
|
+ . '│ ├─ syncnode - 更新节点 IP,每分钟' . PHP_EOL
|
|
|
+ . '│ ├─ DailyJob - 每日任务' . PHP_EOL
|
|
|
+ . '│ ├─ CheckJob - 检查任务,每分钟' . PHP_EOL
|
|
|
+ . '│ ├─ syncnasnode - ???' . PHP_EOL
|
|
|
+ . '│ ├─ updatedownload - 检查客户端更新' . PHP_EOL;
|
|
|
+
|
|
|
+ public function boot()
|
|
|
+ {
|
|
|
+ if (count($this->argv) === 2) {
|
|
|
+ echo $this->description;
|
|
|
+ } else {
|
|
|
+ $methodName = $this->argv[2];
|
|
|
+ if (method_exists($this, $methodName)) {
|
|
|
+ $this->$methodName();
|
|
|
+ } else {
|
|
|
+ echo '方法不存在.' . PHP_EOL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新节点 IP,每分钟
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function syncnode()
|
|
|
{
|
|
|
$nodes = Node::all();
|
|
|
$allNodeID = [];
|
|
|
-
|
|
|
foreach ($nodes as $node) {
|
|
|
$allNodeID[] = $node->id;
|
|
|
$nodeSort = [2, 5, 9, 999]; // 无需更新 IP 的节点类型
|
|
@@ -62,95 +84,18 @@ class Job
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
// 删除无效的中转
|
|
|
$allNodeID = implode(', ', $allNodeID);
|
|
|
$datatables = new DatatablesHelper();
|
|
|
$datatables->query('DELETE FROM `relay` WHERE `source_node_id` NOT IN(' . $allNodeID . ') OR `dist_node_id` NOT IN(' . $allNodeID . ')');
|
|
|
}
|
|
|
|
|
|
- public static function backup($full = false)
|
|
|
- {
|
|
|
- ini_set('memory_limit', '-1');
|
|
|
- $to = $_ENV['auto_backup_email'];
|
|
|
- if ($to == null) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (!mkdir('/tmp/ssmodbackup/') && !is_dir('/tmp/ssmodbackup/')) {
|
|
|
- throw new RuntimeException(sprintf('Directory "%s" was not created', '/tmp/ssmodbackup/'));
|
|
|
- }
|
|
|
- $db_address_array = explode(':', $_ENV['db_host']);
|
|
|
- if ($full) {
|
|
|
- system('mysqldump --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' ' . $_ENV['db_database'] . ' > /tmp/ssmodbackup/mod.sql');
|
|
|
- } else {
|
|
|
- system(
|
|
|
- 'mysqldump --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' ' . $_ENV['db_database'] . ' announcement auto blockip bought code coupon disconnect_ip link login_ip payback radius_ban shop speedtest ss_invite_code ss_node ss_password_reset ticket unblockip user user_token email_verify detect_list relay paylist> /tmp/ssmodbackup/mod.sql',
|
|
|
- $ret
|
|
|
- );
|
|
|
- system(
|
|
|
- 'mysqldump --opt --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' -d ' . $_ENV['db_database'] . ' alive_ip ss_node_info ss_node_online_log user_traffic_log detect_log telegram_session >> /tmp/ssmodbackup/mod.sql',
|
|
|
- $ret
|
|
|
- );
|
|
|
- if ($_ENV['enable_radius'] == true) {
|
|
|
- $db_address_array = explode(':', $_ENV['radius_db_host']);
|
|
|
- system(
|
|
|
- 'mysqldump --user=' . $_ENV['radius_db_user'] . ' --password=' . $_ENV['radius_db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . '' . $_ENV['radius_db_database'] . '> /tmp/ssmodbackup/radius.sql',
|
|
|
- $ret
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- system('cp ' . BASE_PATH . '/config/.config.php /tmp/ssmodbackup/configbak.php', $ret);
|
|
|
- echo $ret;
|
|
|
- system('zip -r /tmp/ssmodbackup.zip /tmp/ssmodbackup/* -P ' . $_ENV['auto_backup_passwd'], $ret);
|
|
|
- $subject = $_ENV['appName'] . '-备份成功';
|
|
|
- $text = '您好,系统已经为您自动备份,请查看附件,用您设定的密码解压。';
|
|
|
- try {
|
|
|
- Mail::send($to, $subject, 'news/backup.tpl', [
|
|
|
- 'text' => $text
|
|
|
- ], [
|
|
|
- '/tmp/ssmodbackup.zip'
|
|
|
- ]);
|
|
|
- } catch (Exception $e) {
|
|
|
- echo $e->getMessage();
|
|
|
- }
|
|
|
- system('rm -rf /tmp/ssmodbackup', $ret);
|
|
|
- system('rm /tmp/ssmodbackup.zip', $ret);
|
|
|
-
|
|
|
- if ($_ENV['backup_notify'] == true) {
|
|
|
- Telegram::Send('备份完毕了喵~今天又是安全祥和的一天呢。');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static function UserGa()
|
|
|
- {
|
|
|
- $users = User::all();
|
|
|
- foreach ($users as $user) {
|
|
|
- $ga = new GA();
|
|
|
- $secret = $ga->createSecret();
|
|
|
-
|
|
|
- $user->ga_token = $secret;
|
|
|
- $user->save();
|
|
|
- }
|
|
|
- echo 'ok';
|
|
|
- }
|
|
|
-
|
|
|
- public static function syncnasnode()
|
|
|
- {
|
|
|
- $nodes = Node::all();
|
|
|
- foreach ($nodes as $node) {
|
|
|
- $rule = preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $node->server);
|
|
|
- if (!$rule && (in_array($node->sort, array(0, 10, 12, 13)))) {
|
|
|
- $ip = gethostbyname($node->server);
|
|
|
- $node->node_ip = $ip;
|
|
|
- $node->save();
|
|
|
-
|
|
|
- Radius::AddNas($node->node_ip, $node->server);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static function DailyJob()
|
|
|
+ /**
|
|
|
+ * 每日任务
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function DailyJob()
|
|
|
{
|
|
|
ini_set('memory_limit', '-1');
|
|
|
$nodes = Node::all();
|
|
@@ -263,16 +208,15 @@ class Job
|
|
|
rename(BASE_PATH . '/storage/qqwry.dat.bak', BASE_PATH . '/storage/qqwry.dat');
|
|
|
}
|
|
|
|
|
|
- self::updatedownload();
|
|
|
+ $this->updatedownload();
|
|
|
}
|
|
|
|
|
|
- // 定时任务开启的情况下,每天自动检测有没有最新版的后端,github源来自Miku
|
|
|
- public static function updatedownload()
|
|
|
- {
|
|
|
- system('cd ' . BASE_PATH . '/public/ssr-download/ && git pull https://github.com/xcxnig/ssr-download.git && git gc');
|
|
|
- }
|
|
|
-
|
|
|
- public static function CheckJob()
|
|
|
+ /**
|
|
|
+ * 检查任务,每分钟
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function CheckJob()
|
|
|
{
|
|
|
//在线人数检测
|
|
|
$users = User::where('node_connector', '>', 0)->get();
|
|
@@ -772,18 +716,14 @@ class Job
|
|
|
}
|
|
|
|
|
|
if ($_ENV['enable_telegram'] === true) {
|
|
|
- self::Telegram();
|
|
|
- }
|
|
|
-
|
|
|
- if ($_ENV['enable_auto_detect_ban'] === true) {
|
|
|
- self::DetectBan();
|
|
|
+ $this->Telegram();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Telegram 任务
|
|
|
*/
|
|
|
- public static function Telegram(): void
|
|
|
+ public function Telegram(): void
|
|
|
{
|
|
|
# 删除 tg 消息
|
|
|
$TelegramTasks = TelegramTasks::where('type', 1)->where('executetime', '<', time())->get();
|
|
@@ -795,199 +735,45 @@ class Job
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 审计封禁任务
|
|
|
+ * 定时任务开启的情况下,每天自动检测有没有最新版的后端,github源来自Miku
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
*/
|
|
|
- public static function DetectBan(): void
|
|
|
+ public function updatedownload()
|
|
|
{
|
|
|
- echo '审计封禁检查开始.' . PHP_EOL;
|
|
|
- $new_logs = DetectLog::where('status', '=', 0)->orderBy('id', 'asc')->take($_ENV['auto_detect_ban_numProcess'])->get();
|
|
|
- if (count($new_logs) != 0) {
|
|
|
-
|
|
|
- $user_logs = [];
|
|
|
- foreach ($new_logs as $log) {
|
|
|
- // 分类各个用户的记录数量
|
|
|
- if (!in_array($log->user_id, array_keys($user_logs))) {
|
|
|
- $user_logs[$log->user_id] = 0;
|
|
|
- }
|
|
|
- $user_logs[$log->user_id]++;
|
|
|
- $log->status = 1;
|
|
|
- $log->save();
|
|
|
- }
|
|
|
-
|
|
|
- foreach ($user_logs as $userid => $value) {
|
|
|
- // 执行封禁
|
|
|
- $user = User::find($userid);
|
|
|
- if ($user == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- $user->all_detect_number += $value;
|
|
|
- $user->save();
|
|
|
+ system('cd ' . BASE_PATH . '/public/ssr-download/ && git pull https://github.com/xcxnig/ssr-download.git && git gc');
|
|
|
+ }
|
|
|
|
|
|
- if ($user->enable == 0 || ($user->is_admin && $_ENV['auto_detect_ban_allow_admin'] === true) || in_array($user->id, $_ENV['auto_detect_ban_allow_users'])) {
|
|
|
- // 如果用户已被封禁
|
|
|
- // 如果用户是管理员
|
|
|
- // 如果属于钦定用户
|
|
|
- // 则跳过
|
|
|
- continue;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 二次验证
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function UserGa()
|
|
|
+ {
|
|
|
+ $users = User::all();
|
|
|
+ foreach ($users as $user) {
|
|
|
+ $ga = new GA();
|
|
|
+ $secret = $ga->createSecret();
|
|
|
|
|
|
- if ($_ENV['auto_detect_ban_type'] == 1) {
|
|
|
- $last_DetectBanLog = DetectBanLog::where('user_id', $userid)->orderBy('id', 'desc')->first();
|
|
|
- $last_all_detect_number = ($last_DetectBanLog == null ? 0 : (int) $last_DetectBanLog->all_detect_number);
|
|
|
- $detect_number = ($user->all_detect_number - $last_all_detect_number);
|
|
|
- if ($detect_number >= $_ENV['auto_detect_ban_number']) {
|
|
|
- $last_detect_ban_time = $user->last_detect_ban_time;
|
|
|
- $end_time = date('Y-m-d H:i:s');
|
|
|
- $user->enable = 0;
|
|
|
- $user->last_detect_ban_time = $end_time;
|
|
|
- $user->save();
|
|
|
- $DetectBanLog = new DetectBanLog();
|
|
|
- $DetectBanLog->user_name = $user->user_name;
|
|
|
- $DetectBanLog->user_id = $user->id;
|
|
|
- $DetectBanLog->email = $user->email;
|
|
|
- $DetectBanLog->detect_number = $detect_number;
|
|
|
- $DetectBanLog->ban_time = $_ENV['auto_detect_ban_time'];
|
|
|
- $DetectBanLog->start_time = strtotime($last_detect_ban_time);
|
|
|
- $DetectBanLog->end_time = strtotime($end_time);
|
|
|
- $DetectBanLog->all_detect_number = $user->all_detect_number;
|
|
|
- $DetectBanLog->save();
|
|
|
- }
|
|
|
- } else {
|
|
|
- $number = $user->all_detect_number;
|
|
|
- $tmp = 0;
|
|
|
- foreach ($_ENV['auto_detect_ban'] as $key => $value) {
|
|
|
- if ($number >= $key) {
|
|
|
- if ($key >= $tmp) {
|
|
|
- $tmp = $key;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if ($tmp != 0) {
|
|
|
- if ($_ENV['auto_detect_ban'][$tmp]['type'] == 'kill') {
|
|
|
- $user->kill_user();
|
|
|
- } else {
|
|
|
- $last_detect_ban_time = $user->last_detect_ban_time;
|
|
|
- $end_time = date('Y-m-d H:i:s');
|
|
|
- $user->enable = 0;
|
|
|
- $user->last_detect_ban_time = $end_time;
|
|
|
- $user->save();
|
|
|
- $DetectBanLog = new DetectBanLog();
|
|
|
- $DetectBanLog->user_name = $user->user_name;
|
|
|
- $DetectBanLog->user_id = $user->id;
|
|
|
- $DetectBanLog->email = $user->email;
|
|
|
- $DetectBanLog->detect_number = $number;
|
|
|
- $DetectBanLog->ban_time = $_ENV['auto_detect_ban'][$tmp]['time'];
|
|
|
- $DetectBanLog->start_time = strtotime('1989-06-04 00:05:00');
|
|
|
- $DetectBanLog->end_time = strtotime($end_time);
|
|
|
- $DetectBanLog->all_detect_number = $number;
|
|
|
- $DetectBanLog->save();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- echo '- 暂无新记录.' . PHP_EOL;
|
|
|
+ $user->ga_token = $secret;
|
|
|
+ $user->save();
|
|
|
}
|
|
|
- echo '审计封禁检查结束.' . PHP_EOL;
|
|
|
+ echo 'ok';
|
|
|
}
|
|
|
|
|
|
- public static function detectGFW()
|
|
|
+ public function syncnasnode()
|
|
|
{
|
|
|
- //节点被墙检测
|
|
|
- $last_time = file_get_contents(BASE_PATH . '/storage/last_detect_gfw_time');
|
|
|
- for ($count = 1; $count <= 12; $count++) {
|
|
|
- if (time() - $last_time >= $_ENV['detect_gfw_interval']) {
|
|
|
- $file_interval = fopen(BASE_PATH . '/storage/last_detect_gfw_time', 'wb');
|
|
|
- fwrite($file_interval, time());
|
|
|
- fclose($file_interval);
|
|
|
- $nodes = Node::all();
|
|
|
- $adminUser = User::where('is_admin', '=', '1')->get();
|
|
|
- foreach ($nodes as $node) {
|
|
|
- if (
|
|
|
- $node->node_ip == '' ||
|
|
|
- $node->node_ip == null ||
|
|
|
- $node->online == false
|
|
|
- ) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- $api_url = $_ENV['detect_gfw_url'];
|
|
|
- $api_url = str_replace(
|
|
|
- array('{ip}', '{port}'),
|
|
|
- array($node->node_ip, $_ENV['detect_gfw_port']),
|
|
|
- $api_url
|
|
|
- );
|
|
|
- //因为考虑到有v2ray之类的节点,所以不得不使用ip作为参数
|
|
|
- $result_tcping = false;
|
|
|
- $detect_time = $_ENV['detect_gfw_count'];
|
|
|
- for ($i = 1; $i <= $detect_time; $i++) {
|
|
|
- $json_tcping = json_decode(file_get_contents($api_url), true);
|
|
|
- if (eval('return ' . $_ENV['detect_gfw_judge'] . ';')) {
|
|
|
- $result_tcping = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($result_tcping == false) {
|
|
|
- //被墙了
|
|
|
- echo ($node->id . ':false' . PHP_EOL);
|
|
|
- //判断有没有发送过邮件
|
|
|
- if ($node->gfw_block == true) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- foreach ($adminUser as $user) {
|
|
|
- echo 'Send gfw mail to user: ' . $user->id . '-';
|
|
|
- $user->sendMail(
|
|
|
- $_ENV['appName'] . '-系统警告',
|
|
|
- 'news/warn.tpl',
|
|
|
- [
|
|
|
- 'text' => '管理员您好,系统发现节点 ' . $node->name . ' 被墙了,请您及时处理。'
|
|
|
- ],
|
|
|
- []
|
|
|
- );
|
|
|
- $notice_text = str_replace(
|
|
|
- '%node_name%',
|
|
|
- $node->name,
|
|
|
- Config::getconfig('Telegram.string.NodeGFW')
|
|
|
- );
|
|
|
- }
|
|
|
- if (Config::getconfig('Telegram.bool.NodeGFW')) {
|
|
|
- Telegram::Send($notice_text);
|
|
|
- }
|
|
|
- $node->gfw_block = true;
|
|
|
- $node->save();
|
|
|
- } else {
|
|
|
- //没有被墙
|
|
|
- echo ($node->id . ':true' . PHP_EOL);
|
|
|
- if ($node->gfw_block == false) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- foreach ($adminUser as $user) {
|
|
|
- echo 'Send gfw mail to user: ' . $user->id . '-';
|
|
|
- $user->sendMail(
|
|
|
- $_ENV['appName'] . '-系统提示',
|
|
|
- 'news/warn.tpl',
|
|
|
- [
|
|
|
- 'text' => '管理员您好,系统发现节点 ' . $node->name . ' 溜出墙了。'
|
|
|
- ],
|
|
|
- []
|
|
|
- );
|
|
|
- $notice_text = str_replace(
|
|
|
- '%node_name%',
|
|
|
- $node->name,
|
|
|
- Config::getconfig('Telegram.string.NodeGFW_recover')
|
|
|
- );
|
|
|
- }
|
|
|
- if (Config::getconfig('Telegram.bool.NodeGFW_recover')) {
|
|
|
- Telegram::Send($notice_text);
|
|
|
- }
|
|
|
- $node->gfw_block = false;
|
|
|
- $node->save();
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
+ $nodes = Node::all();
|
|
|
+ foreach ($nodes as $node) {
|
|
|
+ $rule = preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $node->server);
|
|
|
+ if (!$rule && (in_array($node->sort, array(0, 10, 12, 13)))) {
|
|
|
+ $ip = gethostbyname($node->server);
|
|
|
+ $node->node_ip = $ip;
|
|
|
+ $node->save();
|
|
|
|
|
|
- echo ($node->id . 'interval skip' . PHP_EOL);
|
|
|
- sleep(3);
|
|
|
+ Radius::AddNas($node->node_ip, $node->server);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|