增加后台用户管理面板在线设备数显示

This commit is contained in:
wyx2685 2023-10-29 17:45:17 +09:00
parent 692ad4cf54
commit 9db84a4a4a
No known key found for this signature in database
GPG Key ID: 8827A30FF1DB1379
6 changed files with 316 additions and 4 deletions

View File

@ -14,6 +14,7 @@ use App\Services\AuthService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
@ -75,6 +76,13 @@ class UserController extends Controller
}
}
$res[$i]['subscribe_url'] = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $res[$i]['token']);
//统计在线设备
$countalive = 0;
$ips_array = Cache::get('ALIVE_IP_USER_'. $res[$i]['id']);
if ($ips_array) {
$countalive = $ips_array['alive_ip'];
}
$res[$i]['alive_ip'] = $countalive;
}
return response([
'data' => $res,

View File

@ -44,6 +44,9 @@ class UniProxyController extends Controller
$users = $users->toArray();
$users = array_map(function ($user) {
if ($user['device_limit'] == null || $user['device_limit'] <= 0) {
return $user;
}
$ips_array = Cache::get('ALIVE_IP_USER_'. $user['id']);
$count = 0;
if ($ips_array) {

175
app/Protocols/Singbox.php Normal file
View File

@ -0,0 +1,175 @@
<?php
namespace App\Protocols;
use App\Models\ServerHysteria;
use App\Models\User;
class SingBox
{
public $flag = 'sing-box';
private $servers;
private $user;
public function __construct($user, $servers, array $options = null)
{
$this->user = $user;
$this->servers = $servers;
}
public function handle()
{
$appName = config('app_name', 'V2Board');
$config = $this->loadConfig();
$outbounds = $this->buildOutbounds();
$config['outbounds'] = $outbounds;
return json_encode($config);
//return response($config, 200);
}
protected function loadConfig()
{
$defaultConfig = base_path('resources/rules/default.sing-box.json');
$customConfig = base_path('resources/rules/custom.sing-box.json');
$jsonData = file_exists($customConfig) ? file_get_contents($customConfig) : file_get_contents($defaultConfig);
return json_decode($jsonData, true);
}
protected function buildOutbounds()
{
$outbounds = [];
$selector = [
"tag" => "节点选择",
"type" => "selector",
"default" => "自动选择",
"outbounds" => ["自动选择"]
];
$urltest = [
"tag" => "自动选择",
"type" => "urltest",
"outbounds" => []
];
$outbounds[] = &$selector;
foreach ($this->servers as $item) {
if ($item['type'] === 'vless') {
$vlessConfig = $this->buildVless($this->user['uuid'], $item);
$outbounds[] = $vlessConfig;
$selector['outbounds'][] = $item['name'];
$urltest['outbounds'][] = $item['name'];
} elseif ($item['type'] === 'hysteria') {
$hysteriaConfig = $this->buildHysteria($this->user['uuid'], $item, $this->user);
$outbounds[] = $hysteriaConfig;
$tag = $item['version'] == 2 ? "Hy2" : "Hy";
$selector['outbounds'][] = "[$tag]{$item['name']}";
$urltest['outbounds'][] = "[$tag]{$item['name']}";
}
}
$outbounds[] = [ "tag" => "direct", "type" => "direct" ];
$outbounds[] = [ "tag" => "block", "type" => "block" ];
$outbounds[] = [ "tag" => "dns-out", "type" => "dns" ];
$outbounds[] = $urltest;
return $outbounds;
}
/**
* Vless订阅
*/
protected function buildVless($password, $server)
{
$tlsSettings = $server['tls_settings'] ?? [];
$tlsConfig = [];
if ($server['tls']) {
$tlsConfig['enabled'] = true;
switch ($server['tls']) {
case 1:
$tlsConfig['insecure'] = (bool) ($tlsSettings['allowInsecure'] ?? false);
$tlsConfig['server_name'] = $tlsSettings['serverName'] ?? null;
break;
case 2:
$tlsConfig['insecure'] = (bool) ($tlsSettings['allowInsecure'] ?? false);
$tlsConfig['server_name'] = $tlsSettings['server_name'] ?? null;
if (
isset($tlsSettings['public_key'], $tlsSettings['short_id']) &&
!empty($tlsSettings['server_name'])
) {
$tlsConfig['reality'] = [
'enabled' => true,
'public_key' => $tlsSettings['public_key'],
'short_id' => $tlsSettings['short_id']
];
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq'];
$tlsConfig['utls'] = [
"enabled" => true,
"fingerprint" => $fingerprints[array_rand($fingerprints)]
];
}
break;
}
}
return [
"type" => "vless",
"tag" => $server['name'],
"server" => $server['host'],
"server_port" => $server['port'],
"uuid" => $password,
"flow" => $server['flow'],
"packet_encoding" => "xudp",
"tls" => $tlsConfig
];
}
protected function buildHysteria($password, $server, $user)
{
$array = [
'server' => $server['host'],
'server_port' => $server['port'],
//'up_mbps' => $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'],
//'down_mbps' => $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'],
'tls' => [
'enabled' => true,
'insecure' => $server['insecure'] ? true : false,
'server_name' => $server['server_name']
]
];
if ($server['version'] == 1) {
$array['auth_str'] = $password;
$array['tag'] = "[Hy]" . $server['name'];
$array['type'] = 'hysteria';
$array['up_mbps'] = $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'];
$array['down_mbps'] = $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'];
if ($server['is_obfs']) {
$array['obfs'] = $server['server_key'];
}
$array['disable_mtu_discovery'] = true;
$array['tls']['alpn'] = [ServerHysteria::$alpnMap[$server['alpn']]];
} elseif ($server['version'] == 2) {
$array['password'] = $password;
$array['tag'] = "[Hy2]" . $server['name'];
$array['type'] = 'hysteria2';
$array['password'] = $password;
if (isset($server['obfs'])) {
$array['obfs']['type'] = $server['obfs'];
$array['obfs']['password'] = $server['obfs_password'];
}
}
return $array;
}
}

View File

@ -70673,12 +70673,14 @@
return e
}
}, {
title: "\u8bbe\u5907\u6570\u9650\u5236",
title: "\u8bbe\u5907\u6570",
dataIndex: "device_limit",
key: "device_limit",
sorter: !0,
sorter: (e,t) => e.alive_ip - t.alive_ip,
render: (e,t)=>{
return null !== e ? e : "-"
var deviceCount = t.alive_ip !== null ? t.alive_ip : 0 ;
var deviceLimit = t.device_limit !== null ? t.device_limit : "∞";
return `${deviceCount} / ${deviceLimit}`;
}
}, {
title: "\u5230\u671f\u65f6\u95f4",

View File

@ -30880,7 +30880,7 @@
id: "\u5728\u7ebf\u8bbe\u5907 {alive_ip}/{device_limit}"
}, {
alive_ip: d.alive_ip,
device_limit: d.device_limit == null ? "-" : d.device_limit
device_limit: d.device_limit == null ? "" : d.device_limit
})))), y >= 80 && !Object(p["h"])(d.expired_at) && (null === d || void 0 === d ? void 0 : null === (e = d.plan) || void 0 === e ? void 0 : e.reset_price) && l.a.createElement("div", {
className: "mb-4"
}, l.a.createElement(i["a"], {

View File

@ -0,0 +1,124 @@
{
"dns": {
"rules": [
{
"outbound": [
"any"
],
"server": "local"
},
{
"disable_cache": true,
"geosite": [
"category-ads-all"
],
"server": "block"
},
{
"clash_mode": "global",
"server": "remote"
},
{
"clash_mode": "direct",
"server": "local"
},
{
"geosite": "cn",
"server": "local"
}
],
"servers": [
{
"address": "https://1.1.1.1/dns-query",
"detour": "节点选择",
"tag": "remote"
},
{
"address": "https://223.5.5.5/dns-query",
"detour": "direct",
"tag": "local"
},
{
"address": "rcode://success",
"tag": "block"
}
],
"strategy": "prefer_ipv4"
},
"experimental": {
"clash_api": {
"external_controller": "127.0.0.1:9090",
"secret": "",
"store_selected": true
}
},
"inbounds": [
{
"auto_route": true,
"domain_strategy": "prefer_ipv4",
"endpoint_independent_nat": true,
"inet4_address": "172.19.0.1/30",
"inet6_address": "2001:0470:f9da:fdfa::1/64",
"mtu": 9000,
"sniff": true,
"sniff_override_destination": true,
"stack": "system",
"strict_route": true,
"type": "tun"
},
{
"domain_strategy": "prefer_ipv4",
"listen": "127.0.0.1",
"listen_port": 2333,
"sniff": true,
"sniff_override_destination": true,
"tag": "socks-in",
"type": "socks",
"users": []
},
{
"domain_strategy": "prefer_ipv4",
"listen": "127.0.0.1",
"listen_port": 2334,
"sniff": true,
"sniff_override_destination": true,
"tag": "mixed-in",
"type": "mixed",
"users": []
}
],
"outbounds": [
],
"route": {
"auto_detect_interface": true,
"rules": [
{
"geosite": "category-ads-all",
"outbound": "block"
},
{
"outbound": "dns-out",
"protocol": "dns"
},
{
"clash_mode": "direct",
"outbound": "direct"
},
{
"clash_mode": "global",
"outbound": "节点选择"
},
{
"geoip": [
"cn",
"private"
],
"outbound": "direct"
},
{
"geosite": "cn",
"outbound": "direct"
}
]
}
}