mirror of
https://github.com/v2board/v2board.git
synced 2025-01-11 16:49:10 +08:00
commit
c72e6cf4ea
@ -47,7 +47,8 @@ class CheckCommission extends Command
|
|||||||
{
|
{
|
||||||
if ((int)config('v2board.commission_auto_check_enable', 1)) {
|
if ((int)config('v2board.commission_auto_check_enable', 1)) {
|
||||||
Order::where('commission_status', 0)
|
Order::where('commission_status', 0)
|
||||||
->where('status', 3)
|
->where('invite_user_id', '!=', NULL)
|
||||||
|
->whereIn('status', [3, 4])
|
||||||
->where('updated_at', '<=', strtotime('-3 day', time()))
|
->where('updated_at', '<=', strtotime('-3 day', time()))
|
||||||
->update([
|
->update([
|
||||||
'commission_status' => 1
|
'commission_status' => 1
|
||||||
@ -58,17 +59,15 @@ class CheckCommission extends Command
|
|||||||
public function autoPayCommission()
|
public function autoPayCommission()
|
||||||
{
|
{
|
||||||
$order = Order::where('commission_status', 1)
|
$order = Order::where('commission_status', 1)
|
||||||
->where('status', 3)
|
->where('invite_user_id', '!=', NULL)
|
||||||
->get();
|
->get();
|
||||||
foreach ($order as $item) {
|
foreach ($order as $item) {
|
||||||
if ($item->invite_user_id) {
|
$inviter = User::find($item->invite_user_id);
|
||||||
$inviter = User::find($item->invite_user_id);
|
if (!$inviter) continue;
|
||||||
if (!$inviter) continue;
|
$inviter->commission_balance = $inviter->commission_balance + $item->commission_balance;
|
||||||
$inviter->commission_balance = $inviter->commission_balance + $item->commission_balance;
|
if ($inviter->save()) {
|
||||||
if ($inviter->save()) {
|
$item->commission_status = 2;
|
||||||
$item->commission_status = 2;
|
$item->save();
|
||||||
$item->save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,14 @@ class ConfigController extends Controller
|
|||||||
'telegram' => [
|
'telegram' => [
|
||||||
'telegram_bot_enable' => config('v2board.telegram_bot_enable', 0),
|
'telegram_bot_enable' => config('v2board.telegram_bot_enable', 0),
|
||||||
'telegram_bot_token' => config('v2board.telegram_bot_token')
|
'telegram_bot_token' => config('v2board.telegram_bot_token')
|
||||||
|
],
|
||||||
|
'app' => [
|
||||||
|
'windows_version' => config('v2board.windows_version'),
|
||||||
|
'windows_download_url' => config('v2board.windows_download_url'),
|
||||||
|
'macos_version' => config('v2board.macos_version'),
|
||||||
|
'macos_download_url' => config('v2board.macos_download_url'),
|
||||||
|
'android_version' => config('v2board.android_version'),
|
||||||
|
'android_download_url' => config('v2board.android_download_url')
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
@ -152,7 +160,7 @@ class ConfigController extends Controller
|
|||||||
abort(500, '修改失败');
|
abort(500, '修改失败');
|
||||||
}
|
}
|
||||||
if (function_exists('opcache_reset')) {
|
if (function_exists('opcache_reset')) {
|
||||||
if (!opcache_reset()) {
|
if (opcache_reset() === false) {
|
||||||
abort(500, '缓存清除失败,请卸载或检查opcache配置状态');
|
abort(500, '缓存清除失败,请卸载或检查opcache配置状态');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,12 +94,12 @@ class CouponController extends Controller
|
|||||||
private function multiGenerate(CouponGenerate $request)
|
private function multiGenerate(CouponGenerate $request)
|
||||||
{
|
{
|
||||||
$coupons = [];
|
$coupons = [];
|
||||||
|
$coupon = $request->validated();
|
||||||
|
$coupon['limit_plan_ids'] = json_encode($coupon['limit_plan_ids']);
|
||||||
|
$coupon['created_at'] = $coupon['updated_at'] = time();
|
||||||
|
unset($coupon['generate_count']);
|
||||||
for ($i = 0;$i < $request->input('generate_count');$i++) {
|
for ($i = 0;$i < $request->input('generate_count');$i++) {
|
||||||
$coupon = $request->validated();
|
|
||||||
$coupon['limit_plan_ids'] = json_encode($coupon['limit_plan_ids']);
|
|
||||||
$coupon['code'] = Helper::randomChar(8);
|
$coupon['code'] = Helper::randomChar(8);
|
||||||
$coupon['created_at'] = $coupon['updated_at'] = time();
|
|
||||||
unset($coupon['generate_count']);
|
|
||||||
array_push($coupons, $coupon);
|
array_push($coupons, $coupon);
|
||||||
}
|
}
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
@ -25,7 +25,7 @@ class OrderController extends Controller
|
|||||||
}
|
}
|
||||||
if ($request->input('is_commission')) {
|
if ($request->input('is_commission')) {
|
||||||
$orderModel->where('invite_user_id', '!=', NULL);
|
$orderModel->where('invite_user_id', '!=', NULL);
|
||||||
$orderModel->where('status', 3);
|
$orderModel->whereIn('status', [3, 4]);
|
||||||
$orderModel->where('commission_balance', '>', 0);
|
$orderModel->where('commission_balance', '>', 0);
|
||||||
}
|
}
|
||||||
if ($request->input('id')) {
|
if ($request->input('id')) {
|
||||||
|
64
app/Http/Controllers/Admin/Server/ManageController.php
Normal file
64
app/Http/Controllers/Admin/Server/ManageController.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
|
use App\Http\Requests\Admin\ServerTrojanSort;
|
||||||
|
use App\Models\Plan;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\ServerGroup;
|
||||||
|
use App\Models\ServerShadowsocks;
|
||||||
|
use App\Models\ServerTrojan;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\ServerService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class ManageController extends Controller
|
||||||
|
{
|
||||||
|
public function getNodes(Request $request)
|
||||||
|
{
|
||||||
|
$serverService = new ServerService();
|
||||||
|
$servers = array_merge(
|
||||||
|
$serverService->getShadowsocksServers(),
|
||||||
|
$serverService->getV2rayServers(),
|
||||||
|
$serverService->getTrojanServers()
|
||||||
|
);
|
||||||
|
$tmp = array_column($servers, 'sort');
|
||||||
|
array_multisort($tmp, SORT_ASC, $servers);
|
||||||
|
return response([
|
||||||
|
'data' => $servers
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sort(Request $request)
|
||||||
|
{
|
||||||
|
DB::beginTransaction();
|
||||||
|
foreach ($request->input('sorts') as $k => $v) {
|
||||||
|
switch ($v['key']) {
|
||||||
|
case 'shadowsocks':
|
||||||
|
if (!ServerShadowsocks::find($v['value'])->update(['sort' => $k + 1])) {
|
||||||
|
DB::rollBack();
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'v2ray':
|
||||||
|
if (!Server::find($v['value'])->update(['sort' => $k + 1])) {
|
||||||
|
DB::rollBack();
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'trojan':
|
||||||
|
if (!ServerTrojan::find($v['value'])->update(['sort' => $k + 1])) {
|
||||||
|
DB::rollBack();
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DB::commit();
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -15,26 +15,6 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class ShadowsocksController extends Controller
|
class ShadowsocksController extends Controller
|
||||||
{
|
{
|
||||||
public function fetch(Request $request)
|
|
||||||
{
|
|
||||||
$server = ServerShadowsocks::orderBy('sort', 'ASC')->get();
|
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'data' => $server
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save(ServerShadowsocksSave $request)
|
public function save(ServerShadowsocksSave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
@ -117,19 +97,4 @@ class ShadowsocksController extends Controller
|
|||||||
'data' => true
|
'data' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sort(ServerShadowsocksSort $request)
|
|
||||||
{
|
|
||||||
DB::beginTransaction();
|
|
||||||
foreach ($request->input('server_ids') as $k => $v) {
|
|
||||||
if (!ServerShadowsocks::find($v)->update(['sort' => $k + 1])) {
|
|
||||||
DB::rollBack();
|
|
||||||
abort(500, '保存失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,26 +15,6 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class TrojanController extends Controller
|
class TrojanController extends Controller
|
||||||
{
|
{
|
||||||
public function fetch(Request $request)
|
|
||||||
{
|
|
||||||
$server = ServerTrojan::orderBy('sort', 'ASC')->get();
|
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'data' => $server
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save(ServerTrojanSave $request)
|
public function save(ServerTrojanSave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
@ -117,22 +97,6 @@ class TrojanController extends Controller
|
|||||||
'data' => true
|
'data' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sort(ServerTrojanSort $request)
|
|
||||||
{
|
|
||||||
DB::beginTransaction();
|
|
||||||
foreach ($request->input('server_ids') as $k => $v) {
|
|
||||||
if (!ServerTrojan::find($v)->update(['sort' => $k + 1])) {
|
|
||||||
DB::rollBack();
|
|
||||||
abort(500, '保存失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function viewConfig(Request $request)
|
public function viewConfig(Request $request)
|
||||||
{
|
{
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
|
@ -15,26 +15,6 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class V2rayController extends Controller
|
class V2rayController extends Controller
|
||||||
{
|
{
|
||||||
public function fetch(Request $request)
|
|
||||||
{
|
|
||||||
$server = Server::orderBy('sort', 'ASC')->get();
|
|
||||||
for ($i = 0; $i < count($server); $i++) {
|
|
||||||
if (!empty($server[$i]['tags'])) {
|
|
||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
|
||||||
}
|
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'data' => $server
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save(ServerV2raySave $request)
|
public function save(ServerV2raySave $request)
|
||||||
{
|
{
|
||||||
$params = $request->validated();
|
$params = $request->validated();
|
||||||
@ -150,19 +130,4 @@ class V2rayController extends Controller
|
|||||||
'data' => $config
|
'data' => $config
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sort(ServerV2raySort $request)
|
|
||||||
{
|
|
||||||
DB::beginTransaction();
|
|
||||||
foreach ($request->input('server_ids') as $k => $v) {
|
|
||||||
if (!Server::find($v)->update(['sort' => $k + 1])) {
|
|
||||||
DB::rollBack();
|
|
||||||
abort(500, '保存失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB::commit();
|
|
||||||
return response([
|
|
||||||
'data' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,16 @@ class StatController extends Controller
|
|||||||
->count(),
|
->count(),
|
||||||
'commission_pendding_total' => Order::where('commission_status', 0)
|
'commission_pendding_total' => Order::where('commission_status', 0)
|
||||||
->where('invite_user_id', '!=', NULL)
|
->where('invite_user_id', '!=', NULL)
|
||||||
->where('status', 3)
|
->where('status', [3, 4])
|
||||||
->where('commission_balance', '>', 0)
|
->where('commission_balance', '>', 0)
|
||||||
->count(),
|
->count(),
|
||||||
'day_income' => Order::where('created_at', '>=', strtotime(date('Y-m-d')))
|
'day_income' => Order::where('created_at', '>=', strtotime(date('Y-m-d')))
|
||||||
->where('created_at', '<', time())
|
->where('created_at', '<', time())
|
||||||
->where('status', 3)
|
->whereIn('status', [3, 4])
|
||||||
->sum('total_amount'),
|
->sum('total_amount'),
|
||||||
'last_month_income' => Order::where('created_at', '>=', strtotime('-1 month', strtotime(date('Y-m-1'))))
|
'last_month_income' => Order::where('created_at', '>=', strtotime('-1 month', strtotime(date('Y-m-1'))))
|
||||||
->where('created_at', '<', strtotime(date('Y-m-1')))
|
->where('created_at', '<', strtotime(date('Y-m-1')))
|
||||||
->where('status', 3)
|
->whereIn('status', [3, 4])
|
||||||
->sum('total_amount')
|
->sum('total_amount')
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
@ -23,25 +23,25 @@ class AppController extends Controller
|
|||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
if ($userService->isAvailable($user)) {
|
if ($userService->isAvailable($user)) {
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$servers = $serverService->getAllServers($user);
|
$servers = $serverService->getAvailableServers($user);
|
||||||
}
|
}
|
||||||
$config = Yaml::parseFile(base_path() . '/resources/rules/app.clash.yaml');
|
$config = Yaml::parseFile(base_path() . '/resources/rules/app.clash.yaml');
|
||||||
$proxy = [];
|
$proxy = [];
|
||||||
$proxies = [];
|
$proxies = [];
|
||||||
|
|
||||||
foreach ($servers['shadowsocks'] as $item) {
|
foreach ($servers as $item) {
|
||||||
array_push($proxy, Clash::buildShadowsocks($user->uuid, $item));
|
if ($item['type'] === 'shadowsocks') {
|
||||||
array_push($proxies, $item->name);
|
array_push($proxy, Clash::buildShadowsocks($user['uuid'], $item));
|
||||||
}
|
array_push($proxies, $item['name']);
|
||||||
|
}
|
||||||
foreach ($servers['vmess'] as $item) {
|
if ($item['type'] === 'v2ray') {
|
||||||
array_push($proxy, Clash::buildVmess($user->uuid, $item));
|
array_push($proxy, Clash::buildVmess($user['uuid'], $item));
|
||||||
array_push($proxies, $item->name);
|
array_push($proxies, $item['name']);
|
||||||
}
|
}
|
||||||
|
if ($item['type'] === 'trojan') {
|
||||||
foreach ($servers['trojan'] as $item) {
|
array_push($proxy, Clash::buildTrojan($user['uuid'], $item));
|
||||||
array_push($proxy, Clash::buildTrojan($user->uuid, $item));
|
array_push($proxies, $item['name']);
|
||||||
array_push($proxies, $item->name);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
||||||
@ -51,12 +51,36 @@ class AppController extends Controller
|
|||||||
die(Yaml::dump($config));
|
die(Yaml::dump($config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVersion()
|
public function getVersion(Request $request)
|
||||||
{
|
{
|
||||||
|
if (strpos($request->header('user-agent'), 'tidalab/4.0.0') !== false
|
||||||
|
|| strpos($request->header('user-agent'), 'tunnelab/4.0.0') !== false
|
||||||
|
) {
|
||||||
|
if (strpos($request->header('user-agent'), 'Win64') !== false) {
|
||||||
|
return response([
|
||||||
|
'data' => [
|
||||||
|
'version' => config('v2board.windows_version'),
|
||||||
|
'download_url' => config('v2board.windows_download_url')
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return response([
|
||||||
|
'data' => [
|
||||||
|
'version' => config('v2board.macos_version'),
|
||||||
|
'download_url' => config('v2board.macos_download_url')
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
return response([
|
return response([
|
||||||
'data' => [
|
'data' => [
|
||||||
'version' => '4.0.0',
|
'windows_version' => config('v2board.windows_version'),
|
||||||
'download_url' => ''
|
'windows_download_url' => config('v2board.windows_download_url'),
|
||||||
|
'macos_version' => config('v2board.macos_version'),
|
||||||
|
'macos_download_url' => config('v2board.macos_download_url'),
|
||||||
|
'android_version' => config('v2board.android_version'),
|
||||||
|
'android_download_url' => config('v2board.android_download_url')
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -85,7 +109,7 @@ class AppController extends Controller
|
|||||||
$json->outbound->settings->vnext[0]->address = (string)$server->host;
|
$json->outbound->settings->vnext[0]->address = (string)$server->host;
|
||||||
$json->outbound->settings->vnext[0]->port = (int)$server->port;
|
$json->outbound->settings->vnext[0]->port = (int)$server->port;
|
||||||
$json->outbound->settings->vnext[0]->users[0]->id = (string)$user->uuid;
|
$json->outbound->settings->vnext[0]->users[0]->id = (string)$user->uuid;
|
||||||
$json->outbound->settings->vnext[0]->users[0]->alterId = (int)$user->v2ray_alter_id;
|
$json->outbound->settings->vnext[0]->users[0]->alterId = (int)$server->alter_id;
|
||||||
$json->outbound->settings->vnext[0]->remark = (string)$server->name;
|
$json->outbound->settings->vnext[0]->remark = (string)$server->name;
|
||||||
$json->outbound->streamSettings->network = $server->network;
|
$json->outbound->streamSettings->network = $server->network;
|
||||||
if ($server->networkSettings) {
|
if ($server->networkSettings) {
|
||||||
|
@ -30,52 +30,57 @@ class ClientController extends Controller
|
|||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
if ($userService->isAvailable($user)) {
|
if ($userService->isAvailable($user)) {
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$servers = $serverService->getAllServers($user);
|
$servers = $serverService->getAvailableServers($user);
|
||||||
if ($flag) {
|
if ($flag) {
|
||||||
if (strpos($flag, 'quantumult%20x') !== false) {
|
if (strpos($flag, 'quantumult%20x') !== false) {
|
||||||
die($this->quantumultX($user, $servers['shadowsocks'], $servers['vmess'], $servers['trojan']));
|
die($this->quantumultX($user, $servers));
|
||||||
}
|
}
|
||||||
if (strpos($flag, 'quantumult') !== false) {
|
if (strpos($flag, 'quantumult') !== false) {
|
||||||
die($this->quantumult($user, $servers['vmess']));
|
die($this->quantumult($user, $servers));
|
||||||
}
|
}
|
||||||
if (strpos($flag, 'clash') !== false) {
|
if (strpos($flag, 'clash') !== false) {
|
||||||
die($this->clash($user, $servers['shadowsocks'], $servers['vmess'], $servers['trojan']));
|
die($this->clash($user, $servers));
|
||||||
}
|
}
|
||||||
if (strpos($flag, 'surfboard') !== false) {
|
if (strpos($flag, 'surfboard') !== false) {
|
||||||
die($this->surfboard($user, $servers['shadowsocks'], $servers['vmess']));
|
die($this->surfboard($user, $servers));
|
||||||
}
|
}
|
||||||
if (strpos($flag, 'surge') !== false) {
|
if (strpos($flag, 'surge') !== false) {
|
||||||
die($this->surge($user, $servers['shadowsocks'], $servers['vmess'], $servers['trojan']));
|
die($this->surge($user, $servers));
|
||||||
}
|
}
|
||||||
if (strpos($flag, 'shadowrocket') !== false) {
|
if (strpos($flag, 'shadowrocket') !== false) {
|
||||||
die($this->shadowrocket($user, $servers['shadowsocks'], $servers['vmess'], $servers['trojan']));
|
die($this->shadowrocket($user, $servers));
|
||||||
|
}
|
||||||
|
if (strpos($flag, 'shadowsocks') !== false) {
|
||||||
|
die($this->shaodowsocksSIP008($user, $servers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
die($this->origin($user, $servers['shadowsocks'], $servers['vmess'], $servers['trojan']));
|
die($this->origin($user, $servers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Ready to stop support
|
// TODO: Ready to stop support
|
||||||
private function quantumult($user, $vmess = [])
|
private function quantumult($user, $servers = [])
|
||||||
{
|
{
|
||||||
$uri = '';
|
$uri = '';
|
||||||
header('subscription-userinfo: upload=' . $user->u . '; download=' . $user->d . ';total=' . $user->transfer_enable);
|
header('subscription-userinfo: upload=' . $user->u . '; download=' . $user->d . ';total=' . $user->transfer_enable);
|
||||||
foreach ($vmess as $item) {
|
foreach ($servers as $item) {
|
||||||
$str = '';
|
if ($item['type'] === 'v2ray') {
|
||||||
$str .= $item->name . '= vmess, ' . $item->host . ', ' . $item->port . ', chacha20-ietf-poly1305, "' . $user->uuid . '", over-tls=' . ($item->tls ? "true" : "false") . ', certificate=0, group=' . config('v2board.app_name', 'V2Board');
|
$str = '';
|
||||||
if ($item->network === 'ws') {
|
$str .= $item['name'] . '= vmess, ' . $item['host'] . ', ' . $item['port'] . ', chacha20-ietf-poly1305, "' . $user['uuid'] . '", over-tls=' . ($item['tls'] ? "true" : "false") . ', certificate=0, group=' . config('v2board.app_name', 'V2Board');
|
||||||
$str .= ', obfs=ws';
|
if ($item['network'] === 'ws') {
|
||||||
if ($item->networkSettings) {
|
$str .= ', obfs=ws';
|
||||||
$wsSettings = json_decode($item->networkSettings);
|
if ($item['networkSettings']) {
|
||||||
if (isset($wsSettings->path)) $str .= ', obfs-path="' . $wsSettings->path . '"';
|
$wsSettings = json_decode($item['networkSettings'], true);
|
||||||
if (isset($wsSettings->headers->Host)) $str .= ', obfs-header="Host:' . $wsSettings->headers->Host . '"';
|
if (isset($wsSettings['path'])) $str .= ', obfs-path="' . $wsSettings['path'] . '"';
|
||||||
|
if (isset($wsSettings['headers']['Host'])) $str .= ', obfs-header="Host:' . $wsSettings['headers']['Host'] . '"';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$uri .= "vmess://" . base64_encode($str) . "\r\n";
|
||||||
}
|
}
|
||||||
$uri .= "vmess://" . base64_encode($str) . "\r\n";
|
|
||||||
}
|
}
|
||||||
return base64_encode($uri);
|
return base64_encode($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function shadowrocket($user, $shadowsocks = [], $vmess = [], $trojan = [])
|
private function shadowrocket($user, $servers = [])
|
||||||
{
|
{
|
||||||
$uri = '';
|
$uri = '';
|
||||||
//display remaining traffic and expire date
|
//display remaining traffic and expire date
|
||||||
@ -84,73 +89,98 @@ class ClientController extends Controller
|
|||||||
$totalTraffic = round($user->transfer_enable / (1024*1024*1024), 2);
|
$totalTraffic = round($user->transfer_enable / (1024*1024*1024), 2);
|
||||||
$expiredDate = date('Y-m-d', $user->expired_at);
|
$expiredDate = date('Y-m-d', $user->expired_at);
|
||||||
$uri .= "STATUS=🚀↑:{$upload}GB,↓:{$download}GB,TOT:{$totalTraffic}GB💡Expires:{$expiredDate}\r\n";
|
$uri .= "STATUS=🚀↑:{$upload}GB,↓:{$download}GB,TOT:{$totalTraffic}GB💡Expires:{$expiredDate}\r\n";
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
$uri .= Shadowrocket::buildShadowsocks($user->uuid, $item);
|
if ($item['type'] === 'shadowsocks') {
|
||||||
}
|
$uri .= Shadowrocket::buildShadowsocks($user['uuid'], $item);
|
||||||
foreach ($vmess as $item) {
|
}
|
||||||
$uri .= Shadowrocket::buildVmess($user->uuid, $item);
|
if ($item['type'] === 'v2ray') {
|
||||||
}
|
$uri .= Shadowrocket::buildVmess($user['uuid'], $item);
|
||||||
foreach ($trojan as $item) {
|
}
|
||||||
$uri .= Shadowrocket::buildTrojan($user->uuid, $item);
|
if ($item['type'] === 'trojan') {
|
||||||
|
$uri .= Shadowrocket::buildTrojan($user['uuid'], $item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return base64_encode($uri);
|
return base64_encode($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function quantumultX($user, $shadowsocks = [], $vmess = [], $trojan = [])
|
private function quantumultX($user, $servers = [])
|
||||||
{
|
{
|
||||||
$uri = '';
|
$uri = '';
|
||||||
header("subscription-userinfo: upload={$user->u}; download={$user->d}; total={$user->transfer_enable}; expire={$user->expired_at}");
|
header("subscription-userinfo: upload={$user->u}; download={$user->d}; total={$user->transfer_enable}; expire={$user->expired_at}");
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
$uri .= QuantumultX::buildShadowsocks($user->uuid, $item);
|
if ($item['type'] === 'shadowsocks') {
|
||||||
}
|
$uri .= QuantumultX::buildShadowsocks($user['uuid'], $item);
|
||||||
foreach ($vmess as $item) {
|
}
|
||||||
$uri .= QuantumultX::buildVmess($user->uuid, $item);
|
if ($item['type'] === 'v2ray') {
|
||||||
}
|
$uri .= QuantumultX::buildVmess($user['uuid'], $item);
|
||||||
foreach ($trojan as $item) {
|
}
|
||||||
$uri .= QuantumultX::buildTrojan($user->uuid, $item);
|
if ($item['type'] === 'trojan') {
|
||||||
|
$uri .= QuantumultX::buildTrojan($user['uuid'], $item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return base64_encode($uri);
|
return base64_encode($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function origin($user, $shadowsocks = [], $vmess = [], $trojan = [])
|
private function origin($user, $servers = [])
|
||||||
{
|
{
|
||||||
$uri = '';
|
$uri = '';
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
$uri .= URLSchemes::buildShadowsocks($item, $user);
|
if ($item['type'] === 'shadowsocks') {
|
||||||
}
|
$uri .= URLSchemes::buildShadowsocks($item, $user);
|
||||||
foreach ($vmess as $item) {
|
}
|
||||||
$uri .= URLSchemes::buildVmess($item, $user);
|
if ($item['type'] === 'v2ray') {
|
||||||
}
|
$uri .= URLSchemes::buildVmess($item, $user);
|
||||||
foreach ($trojan as $item) {
|
}
|
||||||
$uri .= URLSchemes::buildTrojan($item, $user);
|
if ($item['type'] === 'trojan') {
|
||||||
|
$uri .= URLSchemes::buildTrojan($item, $user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return base64_encode($uri);
|
return base64_encode($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function surge($user, $shadowsocks = [], $vmess = [], $trojan = [])
|
private function shaodowsocksSIP008($user, $servers = [])
|
||||||
|
{
|
||||||
|
$configs = [];
|
||||||
|
$subs = [];
|
||||||
|
$subs['servers'] = [];
|
||||||
|
|
||||||
|
foreach ($servers as $item) {
|
||||||
|
if ($item['type'] === 'shadowsocks') {
|
||||||
|
array_push($configs, URLSchemes::buildShadowsocksSIP008($item, $user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$subs['version'] = 1;
|
||||||
|
$subs['remark'] = config('v2board.app_name', 'V2Board');
|
||||||
|
$subs['servers'] = array_merge($subs['servers'] ? $subs['servers'] : [], $configs);
|
||||||
|
|
||||||
|
return json_encode($subs, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function surge($user, $servers = [])
|
||||||
{
|
{
|
||||||
$proxies = '';
|
$proxies = '';
|
||||||
$proxyGroup = '';
|
$proxyGroup = '';
|
||||||
|
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
// [Proxy]
|
if ($item['type'] === 'shadowsocks') {
|
||||||
$proxies .= Surge::buildShadowsocks($user->uuid, $item);
|
// [Proxy]
|
||||||
// [Proxy Group]
|
$proxies .= Surge::buildShadowsocks($user['uuid'], $item);
|
||||||
$proxyGroup .= $item->name . ', ';
|
// [Proxy Group]
|
||||||
}
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
|
}
|
||||||
foreach ($vmess as $item) {
|
if ($item['type'] === 'v2ray') {
|
||||||
// [Proxy]
|
// [Proxy]
|
||||||
$proxies .= Surge::buildVmess($user->uuid, $item);
|
$proxies .= Surge::buildVmess($user['uuid'], $item);
|
||||||
// [Proxy Group]
|
// [Proxy Group]
|
||||||
$proxyGroup .= $item->name . ', ';
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
}
|
}
|
||||||
|
if ($item['type'] === 'trojan') {
|
||||||
foreach ($trojan as $item) {
|
// [Proxy]
|
||||||
// [Proxy]
|
$proxies .= Surge::buildTrojan($user['uuid'], $item);
|
||||||
$proxies .= Surge::buildTrojan($user->uuid, $item);
|
// [Proxy Group]
|
||||||
// [Proxy Group]
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
$proxyGroup .= $item->name . ', ';
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultConfig = base_path() . '/resources/rules/default.surge.conf';
|
$defaultConfig = base_path() . '/resources/rules/default.surge.conf';
|
||||||
@ -170,23 +200,24 @@ class ClientController extends Controller
|
|||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function surfboard($user, $shadowsocks = [], $vmess = [])
|
private function surfboard($user, $servers = [])
|
||||||
{
|
{
|
||||||
$proxies = '';
|
$proxies = '';
|
||||||
$proxyGroup = '';
|
$proxyGroup = '';
|
||||||
|
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
// [Proxy]
|
if ($item['type'] === 'shadowsocks') {
|
||||||
$proxies .= Surfboard::buildShadowsocks($user->uuid, $item);
|
// [Proxy]
|
||||||
// [Proxy Group]
|
$proxies .= Surfboard::buildShadowsocks($user['uuid'], $item);
|
||||||
$proxyGroup .= $item->name . ', ';
|
// [Proxy Group]
|
||||||
}
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
|
}
|
||||||
foreach ($vmess as $item) {
|
if ($item['type'] === 'v2ray') {
|
||||||
// [Proxy]
|
// [Proxy]
|
||||||
$proxies .= Surfboard::buildVmess($user->uuid, $item);
|
$proxies .= Surfboard::buildVmess($user['uuid'], $item);
|
||||||
// [Proxy Group]
|
// [Proxy Group]
|
||||||
$proxyGroup .= $item->name . ', ';
|
$proxyGroup .= $item['name'] . ', ';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultConfig = base_path() . '/resources/rules/default.surfboard.conf';
|
$defaultConfig = base_path() . '/resources/rules/default.surfboard.conf';
|
||||||
@ -206,7 +237,7 @@ class ClientController extends Controller
|
|||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function clash($user, $shadowsocks = [], $vmess = [], $trojan = [])
|
private function clash($user, $servers = [])
|
||||||
{
|
{
|
||||||
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
|
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
|
||||||
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
|
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
|
||||||
@ -218,19 +249,19 @@ class ClientController extends Controller
|
|||||||
$proxy = [];
|
$proxy = [];
|
||||||
$proxies = [];
|
$proxies = [];
|
||||||
|
|
||||||
foreach ($shadowsocks as $item) {
|
foreach ($servers as $item) {
|
||||||
array_push($proxy, Clash::buildShadowsocks($user->uuid, $item));
|
if ($item['type'] === 'shadowsocks') {
|
||||||
array_push($proxies, $item->name);
|
array_push($proxy, Clash::buildShadowsocks($user['uuid'], $item));
|
||||||
}
|
array_push($proxies, $item['name']);
|
||||||
|
}
|
||||||
foreach ($vmess as $item) {
|
if ($item['type'] === 'v2ray') {
|
||||||
array_push($proxy, Clash::buildVmess($user->uuid, $item));
|
array_push($proxy, Clash::buildVmess($user['uuid'], $item));
|
||||||
array_push($proxies, $item->name);
|
array_push($proxies, $item['name']);
|
||||||
}
|
}
|
||||||
|
if ($item['type'] === 'trojan') {
|
||||||
foreach ($trojan as $item) {
|
array_push($proxy, Clash::buildTrojan($user['uuid'], $item));
|
||||||
array_push($proxy, Clash::buildTrojan($user->uuid, $item));
|
array_push($proxies, $item['name']);
|
||||||
array_push($proxies, $item->name);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
||||||
|
@ -28,7 +28,8 @@ class CommController extends Controller
|
|||||||
: 0,
|
: 0,
|
||||||
'isRecaptcha' => (int)config('v2board.recaptcha_enable', 0) ? 1 : 0,
|
'isRecaptcha' => (int)config('v2board.recaptcha_enable', 0) ? 1 : 0,
|
||||||
'recaptchaSiteKey' => config('v2board.recaptcha_site_key'),
|
'recaptchaSiteKey' => config('v2board.recaptcha_site_key'),
|
||||||
'appDescription' => config('v2board.app_description')
|
'appDescription' => config('v2board.app_description'),
|
||||||
|
'appUrl' => config('v2board.app_url')
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,11 @@ class DeepbworkController extends Controller
|
|||||||
$user->v2ray_user = [
|
$user->v2ray_user = [
|
||||||
"uuid" => $user->uuid,
|
"uuid" => $user->uuid,
|
||||||
"email" => sprintf("%s@v2board.user", $user->uuid),
|
"email" => sprintf("%s@v2board.user", $user->uuid),
|
||||||
"alter_id" => $user->v2ray_alter_id,
|
"alter_id" => $server->alter_id,
|
||||||
"level" => $user->v2ray_level,
|
"level" => 0,
|
||||||
];
|
];
|
||||||
unset($user['uuid']);
|
unset($user['uuid']);
|
||||||
unset($user['v2ray_alter_id']);
|
unset($user['email']);
|
||||||
unset($user['v2ray_level']);
|
|
||||||
array_push($result, $user);
|
array_push($result, $user);
|
||||||
}
|
}
|
||||||
return response([
|
return response([
|
||||||
@ -64,7 +63,7 @@ class DeepbworkController extends Controller
|
|||||||
// 后端提交数据
|
// 后端提交数据
|
||||||
public function submit(Request $request)
|
public function submit(Request $request)
|
||||||
{
|
{
|
||||||
// Log::info('serverSubmitData:' . $request->input('node_id') . ':' . file_get_contents('php://input'));
|
// Log::info('serverSubmitData:' . $request->input('node_id') . ':' . file_get_contents('php://input'));
|
||||||
$server = Server::find($request->input('node_id'));
|
$server = Server::find($request->input('node_id'));
|
||||||
if (!$server) {
|
if (!$server) {
|
||||||
return response([
|
return response([
|
||||||
@ -75,27 +74,24 @@ class DeepbworkController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
$serverService = new ServerService();
|
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
foreach ($data as $item) {
|
DB::beginTransaction();
|
||||||
$u = $item['u'] * $server->rate;
|
try {
|
||||||
$d = $item['d'] * $server->rate;
|
foreach ($data as $item) {
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'])) {
|
$u = $item['u'] * $server->rate;
|
||||||
return response([
|
$d = $item['d'] * $server->rate;
|
||||||
'ret' => 0,
|
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'vmess')) {
|
||||||
'msg' => 'user fetch fail'
|
continue;
|
||||||
]);
|
}
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
$serverService->log(
|
DB::rollBack();
|
||||||
$item['user_id'],
|
return response([
|
||||||
$request->input('node_id'),
|
'ret' => 0,
|
||||||
$item['u'],
|
'msg' => 'user fetch fail'
|
||||||
$item['d'],
|
]);
|
||||||
$server->rate,
|
|
||||||
'vmess'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'ret' => 1,
|
'ret' => 1,
|
||||||
|
@ -45,12 +45,11 @@ class PoseidonController extends Controller
|
|||||||
$user->v2ray_user = [
|
$user->v2ray_user = [
|
||||||
"uuid" => $user->uuid,
|
"uuid" => $user->uuid,
|
||||||
"email" => sprintf("%s@v2board.user", $user->uuid),
|
"email" => sprintf("%s@v2board.user", $user->uuid),
|
||||||
"alter_id" => $user->v2ray_alter_id,
|
"alter_id" => $server->alter_id,
|
||||||
"level" => $user->v2ray_level,
|
"level" => 0,
|
||||||
];
|
];
|
||||||
unset($user['uuid']);
|
unset($user['uuid']);
|
||||||
unset($user['v2ray_alter_id']);
|
unset($user['email']);
|
||||||
unset($user['v2ray_level']);
|
|
||||||
array_push($result, $user);
|
array_push($result, $user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,23 +67,13 @@ class PoseidonController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
$serverService = new ServerService();
|
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
foreach ($data as $item) {
|
foreach ($data as $item) {
|
||||||
$u = $item['u'] * $server->rate;
|
$u = $item['u'] * $server->rate;
|
||||||
$d = $item['d'] * $server->rate;
|
$d = $item['d'] * $server->rate;
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'])) {
|
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'vmess')) {
|
||||||
return $this->error("user fetch fail", 500);
|
return $this->error("user fetch fail", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$serverService->log(
|
|
||||||
$item['user_id'],
|
|
||||||
$request->input('node_id'),
|
|
||||||
$item['u'],
|
|
||||||
$item['d'],
|
|
||||||
$server->rate,
|
|
||||||
'vmess'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->success('');
|
return $this->success('');
|
||||||
@ -146,9 +135,23 @@ class PoseidonController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function success($data) {
|
protected function success($data) {
|
||||||
|
$req = request();
|
||||||
|
// Only for "GET" method
|
||||||
|
if (!$req->isMethod('GET') || !$data) {
|
||||||
|
return response([
|
||||||
|
'msg' => 'ok',
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$etag = sha1(json_encode($data));
|
||||||
|
if ($etag == $req->header("IF-NONE-MATCH")) {
|
||||||
|
return response(null, 304);
|
||||||
|
}
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'msg' => 'ok',
|
'msg' => 'ok',
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
]);
|
])->header('ETAG', $etag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,28 +70,22 @@ class ShadowsocksTidalabController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
$serverService = new ServerService();
|
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
foreach ($data as $item) {
|
try {
|
||||||
$u = $item['u'] * $server->rate;
|
foreach ($data as $item) {
|
||||||
$d = $item['d'] * $server->rate;
|
$u = $item['u'] * $server->rate;
|
||||||
if (!$userService->trafficFetch((float)$u, (float)$d, (int)$item['user_id'])) {
|
$d = $item['d'] * $server->rate;
|
||||||
DB::rollBack();
|
if (!$userService->trafficFetch((float)$u, (float)$d, (int)$item['user_id'], $server, 'shadowsocks')) {
|
||||||
return response([
|
continue;
|
||||||
'ret' => 0,
|
}
|
||||||
'msg' => 'user fetch fail'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
$serverService->log(
|
DB::rollBack();
|
||||||
$item['user_id'],
|
return response([
|
||||||
$request->input('node_id'),
|
'ret' => 0,
|
||||||
$item['u'],
|
'msg' => 'user fetch fail'
|
||||||
$item['d'],
|
]);
|
||||||
$server->rate,
|
|
||||||
'shadowsocks'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
@ -100,22 +94,4 @@ class ShadowsocksTidalabController extends Controller
|
|||||||
'msg' => 'ok'
|
'msg' => 'ok'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 后端获取配置
|
|
||||||
public function config(Request $request)
|
|
||||||
{
|
|
||||||
$nodeId = $request->input('node_id');
|
|
||||||
$localPort = $request->input('local_port');
|
|
||||||
if (empty($nodeId) || empty($localPort)) {
|
|
||||||
abort(500, '参数错误');
|
|
||||||
}
|
|
||||||
$serverService = new ServerService();
|
|
||||||
try {
|
|
||||||
$json = $serverService->getTrojanConfig($nodeId, $localPort);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
abort(500, $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
die(json_encode($json, JSON_UNESCAPED_UNICODE));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,7 @@ class TrojanTidalabController extends Controller
|
|||||||
"password" => $user->uuid,
|
"password" => $user->uuid,
|
||||||
];
|
];
|
||||||
unset($user['uuid']);
|
unset($user['uuid']);
|
||||||
unset($user['v2ray_alter_id']);
|
unset($user['email']);
|
||||||
unset($user['v2ray_level']);
|
|
||||||
array_push($result, $user);
|
array_push($result, $user);
|
||||||
}
|
}
|
||||||
return response([
|
return response([
|
||||||
@ -72,28 +71,22 @@ class TrojanTidalabController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
$serverService = new ServerService();
|
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
foreach ($data as $item) {
|
try {
|
||||||
$u = $item['u'] * $server->rate;
|
foreach ($data as $item) {
|
||||||
$d = $item['d'] * $server->rate;
|
$u = $item['u'] * $server->rate;
|
||||||
if (!$userService->trafficFetch($u, $d, $item['user_id'])) {
|
$d = $item['d'] * $server->rate;
|
||||||
DB::rollBack();
|
if (!$userService->trafficFetch($u, $d, $item['user_id'], $server, 'trojan')) {
|
||||||
return response([
|
continue;
|
||||||
'ret' => 0,
|
}
|
||||||
'msg' => 'user fetch fail'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
$serverService->log(
|
DB::rollBack();
|
||||||
$item['user_id'],
|
return response([
|
||||||
$request->input('node_id'),
|
'ret' => 0,
|
||||||
$item['u'],
|
'msg' => 'user fetch fail'
|
||||||
$item['d'],
|
]);
|
||||||
$server->rate,
|
|
||||||
'trojan'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ class CouponController extends Controller
|
|||||||
}
|
}
|
||||||
if ($coupon->limit_plan_ids) {
|
if ($coupon->limit_plan_ids) {
|
||||||
$limitPlanIds = json_decode($coupon->limit_plan_ids);
|
$limitPlanIds = json_decode($coupon->limit_plan_ids);
|
||||||
info($limitPlanIds);
|
|
||||||
if (!in_array($request->input('plan_id'), $limitPlanIds)) {
|
if (!in_array($request->input('plan_id'), $limitPlanIds)) {
|
||||||
abort(500, '这个计划无法使用该优惠码');
|
abort(500, '这个计划无法使用该优惠码');
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ class OrderController extends Controller
|
|||||||
|
|
||||||
if ((!$plan->show && !$plan->renew) || (!$plan->show && $user->plan_id !== $plan->id)) {
|
if ((!$plan->show && !$plan->renew) || (!$plan->show && $user->plan_id !== $plan->id)) {
|
||||||
if ($request->input('cycle') !== 'reset_price') {
|
if ($request->input('cycle') !== 'reset_price') {
|
||||||
abort(500, '该订阅已售罄');
|
abort(500, '该订阅已售罄,请更换其他订阅');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +96,10 @@ class OrderController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$plan->show && $plan->renew && !$userService->isAvailable($user)) {
|
||||||
|
abort(500, '订阅已过期,请更换其他订阅');
|
||||||
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$order = new Order();
|
$order = new Order();
|
||||||
$orderService = new OrderService($order);
|
$orderService = new OrderService($order);
|
||||||
|
@ -23,8 +23,7 @@ class ServerController extends Controller
|
|||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
if ($userService->isAvailable($user)) {
|
if ($userService->isAvailable($user)) {
|
||||||
$serverService = new ServerService();
|
$serverService = new ServerService();
|
||||||
$servers = $serverService->getAllServers($user);
|
$servers = $serverService->getAvailableServers($user);
|
||||||
$servers = array_merge($servers['shadowsocks'], $servers['vmess'], $servers['trojan']);
|
|
||||||
}
|
}
|
||||||
return response([
|
return response([
|
||||||
'data' => $servers
|
'data' => $servers
|
||||||
|
@ -43,7 +43,6 @@ class Kernel extends HttpKernel
|
|||||||
\Illuminate\Session\Middleware\StartSession::class,
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
\App\Http\Middleware\ForceJson::class,
|
\App\Http\Middleware\ForceJson::class,
|
||||||
\App\Http\Middleware\CORS::class,
|
\App\Http\Middleware\CORS::class,
|
||||||
'throttle:120,1',
|
|
||||||
'bindings',
|
'bindings',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -100,7 +100,14 @@ class ConfigSave extends FormRequest
|
|||||||
'telegram_bot_enable' => 'in:0,1',
|
'telegram_bot_enable' => 'in:0,1',
|
||||||
'telegram_bot_token' => '',
|
'telegram_bot_token' => '',
|
||||||
'telegram_discuss_id' => '',
|
'telegram_discuss_id' => '',
|
||||||
'telegram_channel_id' => ''
|
'telegram_channel_id' => '',
|
||||||
|
// app
|
||||||
|
'windows_version' => '',
|
||||||
|
'windows_download_url' => '',
|
||||||
|
'macos_version' => '',
|
||||||
|
'macos_download_url' => '',
|
||||||
|
'android_version' => '',
|
||||||
|
'android_download_url' => ''
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class OrderAssign extends FormRequest
|
|||||||
'plan_id' => 'required',
|
'plan_id' => 'required',
|
||||||
'email' => 'required',
|
'email' => 'required',
|
||||||
'total_amount' => 'required',
|
'total_amount' => 'required',
|
||||||
'cycle' => 'required|in:month_price,quarter_price,half_year_price,year_price,onetime_price,reset_price'
|
'cycle' => 'required|in:month_price,quarter_price,half_year_price,year_price,two_year_price,three_year_price,onetime_price,reset_price'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class OrderUpdate extends FormRequest
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'status' => 'in:0,1,2,3',
|
'status' => 'in:0,1,2,3',
|
||||||
'commission_status' => 'in:0,1,2'
|
'commission_status' => 'in:0,1,3'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Admin;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class ServerShadowsocksSort extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids' => 'required|array'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function messages()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids.required' => '服务器ID不能为空',
|
|
||||||
'server_ids.array' => '服务器ID格式有误'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Admin;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class ServerTrojanSort extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids' => 'required|array'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function messages()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids.required' => '服务器ID不能为空',
|
|
||||||
'server_ids.array' => '服务器ID格式有误'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,6 +24,7 @@ class ServerV2raySave extends FormRequest
|
|||||||
'tls' => 'required',
|
'tls' => 'required',
|
||||||
'tags' => 'nullable|array',
|
'tags' => 'nullable|array',
|
||||||
'rate' => 'required|numeric',
|
'rate' => 'required|numeric',
|
||||||
|
'alter_id' => 'required|integer',
|
||||||
'network' => 'required|in:tcp,kcp,ws,http,domainsocket,quic',
|
'network' => 'required|in:tcp,kcp,ws,http,domainsocket,quic',
|
||||||
'networkSettings' => '',
|
'networkSettings' => '',
|
||||||
'ruleSettings' => '',
|
'ruleSettings' => '',
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Admin;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class ServerV2raySort extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids' => 'required|array'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function messages()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'server_ids.required' => '服务器ID不能为空',
|
|
||||||
'server_ids.array' => '服务器ID格式有误'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,6 +26,8 @@ class AdminRoute
|
|||||||
$router->get ('/server/group/fetch', 'Admin\\Server\\GroupController@fetch');
|
$router->get ('/server/group/fetch', 'Admin\\Server\\GroupController@fetch');
|
||||||
$router->post('/server/group/save', 'Admin\\Server\\GroupController@save');
|
$router->post('/server/group/save', 'Admin\\Server\\GroupController@save');
|
||||||
$router->post('/server/group/drop', 'Admin\\Server\\GroupController@drop');
|
$router->post('/server/group/drop', 'Admin\\Server\\GroupController@drop');
|
||||||
|
$router->get ('/server/manage/getNodes', 'Admin\\Server\\ManageController@getNodes');
|
||||||
|
$router->post('/server/manage/sort', 'Admin\\Server\\ManageController@sort');
|
||||||
$router->group([
|
$router->group([
|
||||||
'prefix' => 'server/trojan'
|
'prefix' => 'server/trojan'
|
||||||
], function ($router) {
|
], function ($router) {
|
||||||
|
@ -17,7 +17,7 @@ class GuestRoute
|
|||||||
$router->post('/order/stripeNotify', 'Guest\\OrderController@stripeNotify');
|
$router->post('/order/stripeNotify', 'Guest\\OrderController@stripeNotify');
|
||||||
$router->post('/order/bitpayXNotify', 'Guest\\OrderController@bitpayXNotify');
|
$router->post('/order/bitpayXNotify', 'Guest\\OrderController@bitpayXNotify');
|
||||||
$router->post('/order/mgateNotify', 'Guest\\OrderController@mgateNotify');
|
$router->post('/order/mgateNotify', 'Guest\\OrderController@mgateNotify');
|
||||||
$router->post('/order/epayNotify', 'Guset\\OrderController@epayNotify');
|
$router->post('/order/epayNotify', 'Guest\\OrderController@epayNotify');
|
||||||
// Telegram
|
// Telegram
|
||||||
$router->post('/telegram/webhook', 'Guest\\TelegramController@webhook');
|
$router->post('/telegram/webhook', 'Guest\\TelegramController@webhook');
|
||||||
});
|
});
|
||||||
|
@ -29,8 +29,9 @@ class MailService
|
|||||||
|
|
||||||
private function remindTrafficIsWarnValue($ud, $transfer_enable)
|
private function remindTrafficIsWarnValue($ud, $transfer_enable)
|
||||||
{
|
{
|
||||||
if ($ud <= 0) return false;
|
if (!$ud) return false;
|
||||||
$percentage = $ud / $transfer_enable * 100;
|
if (!$transfer_enable) return false;
|
||||||
|
$percentage = ($ud / $transfer_enable) * 100;
|
||||||
if ($percentage < 80) return false;
|
if ($percentage < 80) return false;
|
||||||
if ($percentage >= 100) return false;
|
if ($percentage >= 100) return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -127,7 +127,7 @@ class OrderService
|
|||||||
if ($user->invite_user_id && $order->total_amount > 0) {
|
if ($user->invite_user_id && $order->total_amount > 0) {
|
||||||
$order->invite_user_id = $user->invite_user_id;
|
$order->invite_user_id = $user->invite_user_id;
|
||||||
$commissionFirstTime = (int)config('v2board.commission_first_time_enable', 1);
|
$commissionFirstTime = (int)config('v2board.commission_first_time_enable', 1);
|
||||||
if (!$commissionFirstTime || ($commissionFirstTime && !Order::where('user_id', $user->id)->where('status', 3)->first())) {
|
if (!$commissionFirstTime || ($commissionFirstTime && !$this->haveValidOrder($user))) {
|
||||||
$inviter = User::find($user->invite_user_id);
|
$inviter = User::find($user->invite_user_id);
|
||||||
if ($inviter && $inviter->commission_rate) {
|
if ($inviter && $inviter->commission_rate) {
|
||||||
$order->commission_balance = $order->total_amount * ($inviter->commission_rate / 100);
|
$order->commission_balance = $order->total_amount * ($inviter->commission_rate / 100);
|
||||||
@ -138,6 +138,13 @@ class OrderService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function haveValidOrder(User $user)
|
||||||
|
{
|
||||||
|
return Order::where('user_id', $user->id)
|
||||||
|
->whereIn('status', [3, 4])
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
private function getSurplusValue(User $user, Order $order)
|
private function getSurplusValue(User $user, Order $order)
|
||||||
{
|
{
|
||||||
if ($user->expired_at === NULL) {
|
if ($user->expired_at === NULL) {
|
||||||
|
@ -15,91 +15,93 @@ use Illuminate\Support\Facades\Cache;
|
|||||||
class ServerService
|
class ServerService
|
||||||
{
|
{
|
||||||
|
|
||||||
CONST V2RAY_CONFIG = '{"api":{"services":["HandlerService","StatsService"],"tag":"api"},"dns":{},"stats":{},"inbound":{"port":443,"protocol":"vmess","settings":{"clients":[]},"sniffing":{"enabled":true,"destOverride":["http","tls"]},"streamSettings":{"network":"tcp"},"tag":"proxy"},"inboundDetour":[{"listen":"0.0.0.0","port":23333,"protocol":"dokodemo-door","settings":{"address":"0.0.0.0"},"tag":"api"}],"log":{"loglevel":"debug","access":"access.log","error":"error.log"},"outbound":{"protocol":"freedom","settings":{}},"outboundDetour":[{"protocol":"blackhole","settings":{},"tag":"block"}],"routing":{"rules":[{"inboundTag":"api","outboundTag":"api","type":"field"}]},"policy":{"levels":{"0":{"handshake":4,"connIdle":300,"uplinkOnly":5,"downlinkOnly":30,"statsUserUplink":true,"statsUserDownlink":true}}}}';
|
CONST V2RAY_CONFIG = '{"api":{"services":["HandlerService","StatsService"],"tag":"api"},"dns":{},"stats":{},"inbound":{"port":443,"protocol":"vmess","settings":{"clients":[]},"sniffing":{"enabled":true,"destOverride":["http","tls"]},"streamSettings":{"network":"tcp"},"tag":"proxy"},"inboundDetour":[{"listen":"127.0.0.1","port":23333,"protocol":"dokodemo-door","settings":{"address":"0.0.0.0"},"tag":"api"}],"log":{"loglevel":"debug","access":"access.log","error":"error.log"},"outbound":{"protocol":"freedom","settings":{}},"outboundDetour":[{"protocol":"blackhole","settings":{},"tag":"block"}],"routing":{"rules":[{"inboundTag":"api","outboundTag":"api","type":"field"}]},"policy":{"levels":{"0":{"handshake":4,"connIdle":300,"uplinkOnly":5,"downlinkOnly":30,"statsUserUplink":true,"statsUserDownlink":true}}}}';
|
||||||
CONST TROJAN_CONFIG = '{"run_type":"server","local_addr":"0.0.0.0","local_port":443,"remote_addr":"www.taobao.com","remote_port":80,"password":[],"ssl":{"cert":"server.crt","key":"server.key","sni":"domain.com"},"api":{"enabled":true,"api_addr":"127.0.0.1","api_port":10000}}';
|
CONST TROJAN_CONFIG = '{"run_type":"server","local_addr":"0.0.0.0","local_port":443,"remote_addr":"www.taobao.com","remote_port":80,"password":[],"ssl":{"cert":"server.crt","key":"server.key","sni":"domain.com"},"api":{"enabled":true,"api_addr":"127.0.0.1","api_port":10000}}';
|
||||||
public function getVmess(User $user, $all = false):array
|
public function getV2ray(User $user, $all = false):array
|
||||||
{
|
{
|
||||||
$vmess = [];
|
$servers = [];
|
||||||
$model = Server::orderBy('sort', 'ASC');
|
$model = Server::orderBy('sort', 'ASC');
|
||||||
if (!$all) {
|
if (!$all) {
|
||||||
$model->where('show', 1);
|
$model->where('show', 1);
|
||||||
}
|
}
|
||||||
$vmesss = $model->get();
|
$v2ray = $model->get();
|
||||||
foreach ($vmesss as $k => $v) {
|
for ($i = 0; $i < count($v2ray); $i++) {
|
||||||
$vmesss[$k]['protocol_type'] = 'vmess';
|
$v2ray[$i]['type'] = 'v2ray';
|
||||||
$groupId = json_decode($vmesss[$k]['group_id']);
|
$groupId = json_decode($v2ray[$i]['group_id']);
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
$vmesss[$k]['link'] = URLSchemes::buildVmess($vmesss[$k], $user);
|
$v2ray[$i]['link'] = URLSchemes::buildVmess($v2ray[$i], $user);
|
||||||
if ($vmesss[$k]['parent_id']) {
|
if ($v2ray[$i]['parent_id']) {
|
||||||
$vmesss[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $vmesss[$k]['parent_id']));
|
$v2ray[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $v2ray[$i]['parent_id']));
|
||||||
} else {
|
} else {
|
||||||
$vmesss[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $vmesss[$k]['id']));
|
$v2ray[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $v2ray[$i]['id']));
|
||||||
}
|
}
|
||||||
array_push($vmess, $vmesss[$k]);
|
array_push($servers, $v2ray[$i]->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $vmess;
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTrojan(User $user, $all = false)
|
public function getTrojan(User $user, $all = false):array
|
||||||
{
|
{
|
||||||
$trojan = [];
|
$servers = [];
|
||||||
$model = ServerTrojan::orderBy('sort', 'ASC');
|
$model = ServerTrojan::orderBy('sort', 'ASC');
|
||||||
if (!$all) {
|
if (!$all) {
|
||||||
$model->where('show', 1);
|
$model->where('show', 1);
|
||||||
}
|
}
|
||||||
$trojans = $model->get();
|
$trojan = $model->get();
|
||||||
foreach ($trojans as $k => $v) {
|
for ($i = 0; $i < count($trojan); $i++) {
|
||||||
$trojans[$k]['protocol_type'] = 'trojan';
|
$trojan[$i]['type'] = 'trojan';
|
||||||
$groupId = json_decode($trojans[$k]['group_id']);
|
$groupId = json_decode($trojan[$i]['group_id']);
|
||||||
$trojans[$k]['link'] = URLSchemes::buildTrojan($trojans[$k], $user);
|
$trojan[$i]['link'] = URLSchemes::buildTrojan($trojan[$i], $user);
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
if ($trojans[$k]['parent_id']) {
|
if ($trojan[$i]['parent_id']) {
|
||||||
$trojans[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojans[$k]['parent_id']));
|
$trojan[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$i]['parent_id']));
|
||||||
} else {
|
} else {
|
||||||
$trojans[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojans[$k]['id']));
|
$trojan[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $trojan[$i]['id']));
|
||||||
}
|
}
|
||||||
array_push($trojan, $trojans[$k]);
|
array_push($servers, $trojan[$i]->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return $trojan;
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShadowsocks(User $user, $all = false)
|
public function getShadowsocks(User $user, $all = false)
|
||||||
{
|
{
|
||||||
$shadowsocks = [];
|
$servers = [];
|
||||||
$model = ServerShadowsocks::orderBy('sort', 'ASC');
|
$model = ServerShadowsocks::orderBy('sort', 'ASC');
|
||||||
if (!$all) {
|
if (!$all) {
|
||||||
$model->where('show', 1);
|
$model->where('show', 1);
|
||||||
}
|
}
|
||||||
$shadowsockss = $model->get();
|
$shadowsocks = $model->get();
|
||||||
foreach ($shadowsockss as $k => $v) {
|
for ($i = 0; $i < count($shadowsocks); $i++) {
|
||||||
$shadowsockss[$k]['protocol_type'] = 'shadowsocks';
|
$shadowsocks[$i]['type'] = 'shadowsocks';
|
||||||
$groupId = json_decode($shadowsockss[$k]['group_id']);
|
$groupId = json_decode($shadowsocks[$i]['group_id']);
|
||||||
$shadowsockss[$k]['link'] = URLSchemes::buildShadowsocks($shadowsockss[$k], $user);
|
$shadowsocks[$i]['link'] = URLSchemes::buildShadowsocks($shadowsocks[$i], $user);
|
||||||
if (in_array($user->group_id, $groupId)) {
|
if (in_array($user->group_id, $groupId)) {
|
||||||
if ($shadowsockss[$k]['parent_id']) {
|
if ($shadowsocks[$i]['parent_id']) {
|
||||||
$shadowsockss[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsockss[$k]['parent_id']));
|
$shadowsocks[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsocks[$i]['parent_id']));
|
||||||
} else {
|
} else {
|
||||||
$shadowsockss[$k]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsockss[$k]['id']));
|
$shadowsocks[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $shadowsocks[$i]['id']));
|
||||||
}
|
}
|
||||||
array_push($shadowsocks, $shadowsockss[$k]);
|
array_push($servers, $shadowsocks[$i]->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return $shadowsocks;
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllServers(User $user, $all = false)
|
public function getAvailableServers(User $user, $all = false)
|
||||||
{
|
{
|
||||||
return [
|
$servers = array_merge(
|
||||||
'shadowsocks' => $this->getShadowsocks($user, $all),
|
$this->getShadowsocks($user, $all),
|
||||||
'vmess' => $this->getVmess($user, $all),
|
$this->getV2ray($user, $all),
|
||||||
'trojan' => $this->getTrojan($user, $all)
|
$this->getTrojan($user, $all)
|
||||||
];
|
);
|
||||||
|
$tmp = array_column($servers, 'sort');
|
||||||
|
array_multisort($tmp, SORT_ASC, $servers);
|
||||||
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -119,9 +121,7 @@ class ServerService
|
|||||||
'u',
|
'u',
|
||||||
'd',
|
'd',
|
||||||
'transfer_enable',
|
'transfer_enable',
|
||||||
'uuid',
|
'uuid'
|
||||||
'v2ray_alter_id',
|
|
||||||
'v2ray_level'
|
|
||||||
])
|
])
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ class ServerService
|
|||||||
abort(500, '节点不存在');
|
abort(500, '节点不存在');
|
||||||
}
|
}
|
||||||
$json = json_decode(self::V2RAY_CONFIG);
|
$json = json_decode(self::V2RAY_CONFIG);
|
||||||
$json->log->loglevel = config('v2board.server_log_level', 'none');
|
$json->log->loglevel = (int)config('v2board.server_log_enable') ? 'debug' : 'none';
|
||||||
$json->inboundDetour[0]->port = (int)$localPort;
|
$json->inboundDetour[0]->port = (int)$localPort;
|
||||||
$json->inbound->port = (int)$server->server_port;
|
$json->inbound->port = (int)$server->server_port;
|
||||||
$json->inbound->streamSettings->network = $server->network;
|
$json->inbound->streamSettings->network = $server->network;
|
||||||
@ -270,6 +270,7 @@ class ServerService
|
|||||||
->where('user_id', $userId)
|
->where('user_id', $userId)
|
||||||
->where('rate', $rate)
|
->where('rate', $rate)
|
||||||
->where('method', $method)
|
->where('method', $method)
|
||||||
|
->lockForUpdate()
|
||||||
->first();
|
->first();
|
||||||
if ($serverLog) {
|
if ($serverLog) {
|
||||||
$serverLog->u = $serverLog->u + $u;
|
$serverLog->u = $serverLog->u + $u;
|
||||||
@ -287,4 +288,70 @@ class ServerService
|
|||||||
$serverLog->save();
|
$serverLog->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getShadowsocksServers()
|
||||||
|
{
|
||||||
|
$server = ServerShadowsocks::orderBy('sort', 'ASC')->get();
|
||||||
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
|
$server[$i]['type'] = 'shadowsocks';
|
||||||
|
if (!empty($server[$i]['tags'])) {
|
||||||
|
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
||||||
|
}
|
||||||
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
|
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
||||||
|
if ($server[$i]['parent_id']) {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['parent_id']));
|
||||||
|
} else {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['id']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $server->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getV2rayServers()
|
||||||
|
{
|
||||||
|
$server = Server::orderBy('sort', 'ASC')->get();
|
||||||
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
|
$server[$i]['type'] = 'v2ray';
|
||||||
|
if (!empty($server[$i]['tags'])) {
|
||||||
|
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
||||||
|
}
|
||||||
|
if (!empty($server[$i]['dnsSettings'])) {
|
||||||
|
$server[$i]['dnsSettings'] = json_decode($server[$i]['dnsSettings']);
|
||||||
|
}
|
||||||
|
if (!empty($server[$i]['tlsSettings'])) {
|
||||||
|
$server[$i]['tlsSettings'] = json_decode($server[$i]['tlsSettings']);
|
||||||
|
}
|
||||||
|
if (!empty($server[$i]['ruleSettings'])) {
|
||||||
|
$server[$i]['ruleSettings'] = json_decode($server[$i]['ruleSettings']);
|
||||||
|
}
|
||||||
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
|
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
||||||
|
if ($server[$i]['parent_id']) {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['parent_id']));
|
||||||
|
} else {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['id']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $server->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTrojanServers()
|
||||||
|
{
|
||||||
|
$server = ServerTrojan::orderBy('sort', 'ASC')->get();
|
||||||
|
for ($i = 0; $i < count($server); $i++) {
|
||||||
|
$server[$i]['type'] = 'trojan';
|
||||||
|
if (!empty($server[$i]['tags'])) {
|
||||||
|
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
||||||
|
}
|
||||||
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
|
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
||||||
|
if ($server[$i]['parent_id']) {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['parent_id']));
|
||||||
|
} else {
|
||||||
|
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['id']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $server->toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\Server;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
class UserService
|
class UserService
|
||||||
@ -76,9 +77,10 @@ class UserService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trafficFetch(int $u, int $d, int $userId):bool
|
public function trafficFetch(int $u, int $d, int $userId, object $server, string $protocol):bool
|
||||||
{
|
{
|
||||||
$user = User::find($userId);
|
$user = User::lockForUpdate()
|
||||||
|
->find($userId);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -89,7 +91,19 @@ class UserService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$mailService = new MailService();
|
$mailService = new MailService();
|
||||||
$mailService->remindTraffic($user);
|
$serverService = new ServerService();
|
||||||
|
try {
|
||||||
|
$mailService->remindTraffic($user);
|
||||||
|
$serverService->log(
|
||||||
|
$userId,
|
||||||
|
$server->id,
|
||||||
|
$u,
|
||||||
|
$d,
|
||||||
|
$server->rate,
|
||||||
|
$protocol
|
||||||
|
);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ namespace App\Utils;
|
|||||||
class CacheKey
|
class CacheKey
|
||||||
{
|
{
|
||||||
CONST KEYS = [
|
CONST KEYS = [
|
||||||
'EMAIL_VERIFY_CODE' => '邮箱验证吗',
|
'EMAIL_VERIFY_CODE' => '邮箱验证码',
|
||||||
'LAST_SEND_EMAIL_VERIFY_TIMESTAMP' => '最后一次发送邮箱验证码时间',
|
'LAST_SEND_EMAIL_VERIFY_TIMESTAMP' => '最后一次发送邮箱验证码时间',
|
||||||
'SERVER_V2RAY_ONLINE_USER' => '节点在线用户',
|
'SERVER_V2RAY_ONLINE_USER' => '节点在线用户',
|
||||||
'SERVER_V2RAY_LAST_CHECK_AT' => '节点最后检查时间',
|
'SERVER_V2RAY_LAST_CHECK_AT' => '节点最后检查时间',
|
||||||
|
@ -8,11 +8,11 @@ class Clash
|
|||||||
public static function buildShadowsocks($uuid, $server)
|
public static function buildShadowsocks($uuid, $server)
|
||||||
{
|
{
|
||||||
$array = [];
|
$array = [];
|
||||||
$array['name'] = $server->name;
|
$array['name'] = $server['name'];
|
||||||
$array['type'] = 'ss';
|
$array['type'] = 'ss';
|
||||||
$array['server'] = $server->host;
|
$array['server'] = $server['host'];
|
||||||
$array['port'] = $server->port;
|
$array['port'] = $server['port'];
|
||||||
$array['cipher'] = $server->cipher;
|
$array['cipher'] = $server['cipher'];
|
||||||
$array['password'] = $uuid;
|
$array['password'] = $uuid;
|
||||||
$array['udp'] = true;
|
$array['udp'] = true;
|
||||||
return $array;
|
return $array;
|
||||||
@ -21,44 +21,50 @@ class Clash
|
|||||||
public static function buildVmess($uuid, $server)
|
public static function buildVmess($uuid, $server)
|
||||||
{
|
{
|
||||||
$array = [];
|
$array = [];
|
||||||
$array['name'] = $server->name;
|
$array['name'] = $server['name'];
|
||||||
$array['type'] = 'vmess';
|
$array['type'] = 'vmess';
|
||||||
$array['server'] = $server->host;
|
$array['server'] = $server['host'];
|
||||||
$array['port'] = $server->port;
|
$array['port'] = $server['port'];
|
||||||
$array['uuid'] = $uuid;
|
$array['uuid'] = $uuid;
|
||||||
$array['alterId'] = 2;
|
$array['alterId'] = $server['alter_id'];
|
||||||
$array['cipher'] = 'auto';
|
$array['cipher'] = 'auto';
|
||||||
$array['udp'] = true;
|
$array['udp'] = true;
|
||||||
if ($server->tls) {
|
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
if ($server['tls']) {
|
||||||
$array['tls'] = true;
|
$array['tls'] = true;
|
||||||
if (!empty($tlsSettings->allowInsecure)) $array['skip-cert-verify'] = ($tlsSettings->allowInsecure ? true : false );
|
if ($server['tlsSettings']) {
|
||||||
if (!empty($tlsSettings->serverName)) $array['servername'] = $tlsSettings->serverName;
|
$tlsSettings = json_decode($server['tlsSettings'], true);
|
||||||
}
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
if ($server->network == 'ws') {
|
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
||||||
$array['network'] = $server->network;
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
if ($server->networkSettings) {
|
$array['servername'] = $tlsSettings['serverName'];
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
|
||||||
if (isset($wsSettings->path)) $array['ws-path'] = $wsSettings->path;
|
|
||||||
if (isset($wsSettings->headers->Host)) $array['ws-headers'] = [
|
|
||||||
'Host' => $wsSettings->headers->Host
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($server['network'] === 'ws') {
|
||||||
|
$array['network'] = 'ws';
|
||||||
|
if ($server['networkSettings']) {
|
||||||
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
|
$array['ws-path'] = $wsSettings['path'];
|
||||||
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
|
$array['ws-headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildTrojan($password, $server)
|
public static function buildTrojan($password, $server)
|
||||||
{
|
{
|
||||||
$array = [];
|
$array = [];
|
||||||
$array['name'] = $server->name;
|
$array['name'] = $server['name'];
|
||||||
$array['type'] = 'trojan';
|
$array['type'] = 'trojan';
|
||||||
$array['server'] = $server->host;
|
$array['server'] = $server['host'];
|
||||||
$array['port'] = $server->port;
|
$array['port'] = $server['port'];
|
||||||
$array['password'] = $password;
|
$array['password'] = $password;
|
||||||
$array['udp'] = true;
|
$array['udp'] = true;
|
||||||
if (!empty($server->server_name)) $array['sni'] = $server->server_name;
|
if (!empty($server['server_name'])) $array['sni'] = $server['server_name'];
|
||||||
if (!empty($server->allow_insecure)) $array['skip-cert-verify'] = ($server->allow_insecure ? true : false );
|
if (!empty($server['allow_insecure'])) $array['skip-cert-verify'] = ($server['allow_insecure'] ? true : false);
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,12 @@ class QuantumultX
|
|||||||
public static function buildShadowsocks($password, $server)
|
public static function buildShadowsocks($password, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"shadowsocks={$server->host}:{$server->port}",
|
"shadowsocks={$server['host']}:{$server['port']}",
|
||||||
"method={$server->cipher}",
|
"method={$server['cipher']}",
|
||||||
"password={$password}",
|
"password={$password}",
|
||||||
'fast-open=true',
|
'fast-open=true',
|
||||||
'udp-relay=true',
|
'udp-relay=true',
|
||||||
"tag={$server->name}"
|
"tag={$server['name']}"
|
||||||
];
|
];
|
||||||
$config = array_filter($config);
|
$config = array_filter($config);
|
||||||
$uri = implode(',', $config);
|
$uri = implode(',', $config);
|
||||||
@ -24,41 +24,40 @@ class QuantumultX
|
|||||||
public static function buildVmess($uuid, $server)
|
public static function buildVmess($uuid, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"vmess={$server->host}:{$server->port}",
|
"vmess={$server['host']}:{$server['port']}",
|
||||||
'method=chacha20-poly1305',
|
'method=chacha20-poly1305',
|
||||||
"password={$uuid}",
|
"password={$uuid}",
|
||||||
'fast-open=true',
|
'fast-open=true',
|
||||||
'udp-relay=true',
|
'udp-relay=true',
|
||||||
"tag={$server->name}"
|
"tag={$server['name']}"
|
||||||
];
|
];
|
||||||
if ($server->network === 'tcp') {
|
|
||||||
if ($server->tls) {
|
if ($server['tls']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
if ($server['network'] === 'tcp') {
|
||||||
array_push($config, 'obfs=over-tls');
|
array_push($config, 'obfs=over-tls');
|
||||||
if (isset($tlsSettings->allowInsecure)) {
|
} else {
|
||||||
// Tips: allowInsecure=false = tls-verification=true
|
array_push($config, 'obfs=wss');
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'tls-verification=false' : 'tls-verification=true');
|
|
||||||
}
|
|
||||||
if (!empty($tlsSettings->serverName)) {
|
|
||||||
array_push($config, "obfs-host={$tlsSettings->serverName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if ($server['network'] === 'ws') {
|
||||||
|
array_push($config, 'obfs=ws');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($server->network === 'ws') {
|
if ($server['tls']) {
|
||||||
if ($server->tls) {
|
if ($server['tlsSettings']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
$tlsSettings = json_decode($server['tlsSettings'], true);
|
||||||
array_push($config, 'obfs=wss');
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
if (isset($tlsSettings->allowInsecure)) {
|
array_push($config, 'tls-verification=' . ($tlsSettings['allowInsecure'] ? 'false' : 'true'));
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'tls-verification=false' : 'tls-verification=true');
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
}
|
array_push($config, "tls-host={$tlsSettings['serverName']}");
|
||||||
} else {
|
|
||||||
array_push($config, 'obfs=ws');
|
|
||||||
}
|
}
|
||||||
if ($server->networkSettings) {
|
}
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
if ($server['network'] === 'ws') {
|
||||||
if (isset($wsSettings->path)) array_push($config, "obfs-uri={$wsSettings->path}");
|
if ($server['networkSettings']) {
|
||||||
if (isset($wsSettings->headers->Host)) array_push($config, "obfs-host={$wsSettings->headers->Host}");
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
|
array_push($config, "obfs-uri={$wsSettings['path']}");
|
||||||
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
|
array_push($config, "obfs-host={$wsSettings['headers']['Host']}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,15 +69,15 @@ class QuantumultX
|
|||||||
public static function buildTrojan($password, $server)
|
public static function buildTrojan($password, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"trojan={$server->host}:{$server->port}",
|
"trojan={$server['host']}:{$server['port']}",
|
||||||
"password={$password}",
|
"password={$password}",
|
||||||
'over-tls=true',
|
'over-tls=true',
|
||||||
$server->server_name ? "tls-host={$server->server_name}" : "",
|
$server['server_name'] ? "tls-host={$server['server_name']}" : "",
|
||||||
// Tips: allowInsecure=false = tls-verification=true
|
// Tips: allowInsecure=false = tls-verification=true
|
||||||
$server->allow_insecure ? 'tls-verification=false' : 'tls-verification=true',
|
$server['allow_insecure'] ? 'tls-verification=false' : 'tls-verification=true',
|
||||||
'fast-open=true',
|
'fast-open=true',
|
||||||
'udp-relay=true',
|
'udp-relay=true',
|
||||||
"tag={$server->name}"
|
"tag={$server['name']}"
|
||||||
];
|
];
|
||||||
$config = array_filter($config);
|
$config = array_filter($config);
|
||||||
$uri = implode(',', $config);
|
$uri = implode(',', $config);
|
||||||
|
@ -7,47 +7,57 @@ class Shadowrocket
|
|||||||
{
|
{
|
||||||
public static function buildShadowsocks($password, $server)
|
public static function buildShadowsocks($password, $server)
|
||||||
{
|
{
|
||||||
$name = rawurlencode($server->name);
|
$name = rawurlencode($server['name']);
|
||||||
$str = str_replace(
|
$str = str_replace(
|
||||||
['+', '/', '='],
|
['+', '/', '='],
|
||||||
['-', '_', ''],
|
['-', '_', ''],
|
||||||
base64_encode("{$server->cipher}:{$password}")
|
base64_encode("{$server['cipher']}:{$password}")
|
||||||
);
|
);
|
||||||
return "ss://{$str}@{$server->host}:{$server->port}#{$name}\r\n";
|
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildVmess($uuid, $server)
|
public static function buildVmess($uuid, $server)
|
||||||
{
|
{
|
||||||
$userinfo = base64_encode('auto:' . $uuid . '@' . $server->host . ':' . $server->port);
|
$userinfo = base64_encode('auto:' . $uuid . '@' . $server['host'] . ':' . $server['port']);
|
||||||
$config = [
|
$config = [
|
||||||
'remark' => $server->name
|
'tfo' => 1,
|
||||||
|
'remark' => $server['name'],
|
||||||
|
'alterId' => $server['alter_id']
|
||||||
];
|
];
|
||||||
if ($server->tls) {
|
if ($server['tls']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
|
||||||
$config['tls'] = 1;
|
$config['tls'] = 1;
|
||||||
if (isset($tlsSettings->serverName)) $config['peer'] = $tlsSettings->serverName;
|
if ($server['tlsSettings']) {
|
||||||
if (isset($tlsSettings->allowInsecure)) $config['allowInsecure'] = 1;
|
$tlsSettings = json_decode($server['tlsSettings'], true);
|
||||||
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
|
$config['allowInsecure'] = (int)$tlsSettings['allowInsecure'];
|
||||||
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
|
$config['peer'] = $tlsSettings['serverName'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($server->network === 'ws') {
|
if ($server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
|
||||||
$config['obfs'] = "websocket";
|
$config['obfs'] = "websocket";
|
||||||
if (isset($wsSettings->path)) $config['path'] = $wsSettings->path;
|
if ($server['networkSettings']) {
|
||||||
if (isset($wsSettings->headers->Host)) $config['obfsParam'] = $wsSettings->headers->Host;
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
|
$config['path'] = $wsSettings['path'];
|
||||||
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
|
$config['obfsParam'] = $wsSettings['headers']['Host'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$query = http_build_query($config, null, '&', PHP_QUERY_RFC3986);
|
$query = http_build_query($config, '', '&', PHP_QUERY_RFC3986);
|
||||||
$uri = "vmess://{$userinfo}?{$query}&tfo=1";
|
$uri = "vmess://{$userinfo}?{$query}";
|
||||||
$uri .= "\r\n";
|
$uri .= "\r\n";
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildTrojan($password, $server)
|
public static function buildTrojan($password, $server)
|
||||||
{
|
{
|
||||||
$name = rawurlencode($server->name);
|
$name = rawurlencode($server['name']);
|
||||||
$query = http_build_query([
|
$query = http_build_query([
|
||||||
'allowInsecure' => $server->allow_insecure,
|
'allowInsecure' => $server['allow_insecure'],
|
||||||
'peer' => $server->server_name
|
'peer' => $server['server_name']
|
||||||
]);
|
]);
|
||||||
$uri = "trojan://{$password}@{$server->host}:{$server->port}?{$query}&tfo=1#{$name}";
|
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}&tfo=1#{$name}";
|
||||||
$uri .= "\r\n";
|
$uri .= "\r\n";
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ class Surfboard
|
|||||||
public static function buildShadowsocks($password, $server)
|
public static function buildShadowsocks($password, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"{$server->name}=custom",
|
"{$server['name']}=custom",
|
||||||
"{$server->host}",
|
"{$server['host']}",
|
||||||
"{$server->port}",
|
"{$server['port']}",
|
||||||
"{$server->cipher}",
|
"{$server['cipher']}",
|
||||||
"{$password}",
|
"{$password}",
|
||||||
'https://raw.githubusercontent.com/Hackl0us/proxy-tool-backup/master/SSEncrypt.module',
|
'https://raw.githubusercontent.com/Hackl0us/proxy-tool-backup/master/SSEncrypt.module',
|
||||||
'tfo=true',
|
'tfo=true',
|
||||||
@ -26,36 +26,32 @@ class Surfboard
|
|||||||
public static function buildVmess($uuid, $server)
|
public static function buildVmess($uuid, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"{$server->name}=vmess",
|
"{$server['name']}=vmess",
|
||||||
"{$server->host}",
|
"{$server['host']}",
|
||||||
"{$server->port}",
|
"{$server['port']}",
|
||||||
"username={$uuid}",
|
"username={$uuid}",
|
||||||
'tfo=true',
|
'tfo=true',
|
||||||
'udp-relay=true'
|
'udp-relay=true'
|
||||||
];
|
];
|
||||||
if ($server->network === 'tcp') {
|
|
||||||
if ($server->tls) {
|
if ($server['tls']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
array_push($config, 'tls=true');
|
||||||
array_push($config, $server->tls ? 'tls=true' : 'tls=false');
|
if ($server['tlsSettings']) {
|
||||||
if (!empty($tlsSettings->allowInsecure)) {
|
$tlsSettings = json_decode($server['tlsSettings'], true);
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
}
|
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
||||||
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
|
array_push($config, "sni={$tlsSettings['serverName']}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($server['network'] === 'ws') {
|
||||||
if ($server->network === 'ws') {
|
|
||||||
array_push($config, 'ws=true');
|
array_push($config, 'ws=true');
|
||||||
if ($server->tls) {
|
if ($server['networkSettings']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
array_push($config, $server->tls ? 'tls=true' : 'tls=false');
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
if (!empty($tlsSettings->allowInsecure)) {
|
array_push($config, "ws-path={$wsSettings['path']}");
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
}
|
array_push($config, "ws-headers=Host:{$wsSettings['headers']['Host']}");
|
||||||
}
|
|
||||||
if ($server->networkSettings) {
|
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
|
||||||
if (isset($wsSettings->path)) array_push($config, "ws-path={$wsSettings->path}");
|
|
||||||
if (isset($wsSettings->headers->Host)) array_push($config, "ws-headers=host:{$wsSettings->headers->Host}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ class Surge
|
|||||||
public static function buildShadowsocks($password, $server)
|
public static function buildShadowsocks($password, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"{$server->name}=ss",
|
"{$server['name']}=ss",
|
||||||
"{$server->host}",
|
"{$server['host']}",
|
||||||
"{$server->port}",
|
"{$server['port']}",
|
||||||
"encrypt-method={$server->cipher}",
|
"encrypt-method={$server['cipher']}",
|
||||||
"password={$password}",
|
"password={$password}",
|
||||||
'tfo=true',
|
'tfo=true',
|
||||||
'udp-relay=true'
|
'udp-relay=true'
|
||||||
@ -25,39 +25,32 @@ class Surge
|
|||||||
public static function buildVmess($uuid, $server)
|
public static function buildVmess($uuid, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"{$server->name}=vmess",
|
"{$server['name']}=vmess",
|
||||||
"{$server->host}",
|
"{$server['host']}",
|
||||||
"{$server->port}",
|
"{$server['port']}",
|
||||||
"username={$uuid}",
|
"username={$uuid}",
|
||||||
'tfo=true',
|
'tfo=true',
|
||||||
'udp-relay=true'
|
'udp-relay=true'
|
||||||
];
|
];
|
||||||
if ($server->network === 'tcp') {
|
|
||||||
if ($server->tls) {
|
if ($server['tls']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
array_push($config, 'tls=true');
|
||||||
array_push($config, $server->tls ? 'tls=true' : 'tls=false');
|
if ($server['tlsSettings']) {
|
||||||
if (!empty($tlsSettings->allowInsecure)) {
|
$tlsSettings = json_decode($server['tlsSettings'], true);
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||||
}
|
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allowInsecure'] ? 'true' : 'false'));
|
||||||
if (!empty($tlsSettings->serverName)) {
|
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||||
array_push($config, "sni={$tlsSettings->serverName}");
|
array_push($config, "sni={$tlsSettings['serverName']}");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($server['network'] === 'ws') {
|
||||||
if ($server->network === 'ws') {
|
|
||||||
array_push($config, 'ws=true');
|
array_push($config, 'ws=true');
|
||||||
if ($server->tls) {
|
if ($server['networkSettings']) {
|
||||||
$tlsSettings = json_decode($server->tlsSettings);
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
array_push($config, $server->tls ? 'tls=true' : 'tls=false');
|
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||||
if (!empty($tlsSettings->allowInsecure)) {
|
array_push($config, "ws-path={$wsSettings['path']}");
|
||||||
array_push($config, $tlsSettings->allowInsecure ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||||
}
|
array_push($config, "ws-headers=Host:{$wsSettings['headers']['Host']}");
|
||||||
}
|
|
||||||
if ($server->networkSettings) {
|
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
|
||||||
if (isset($wsSettings->path)) array_push($config, "ws-path={$wsSettings->path}");
|
|
||||||
if (isset($wsSettings->headers->Host)) array_push($config, "ws-headers=host:{$wsSettings->headers->Host}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +62,16 @@ class Surge
|
|||||||
public static function buildTrojan($password, $server)
|
public static function buildTrojan($password, $server)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"{$server->name}=trojan",
|
"{$server['name']}=trojan",
|
||||||
"{$server->host}",
|
"{$server['host']}",
|
||||||
"{$server->port}",
|
"{$server['port']}",
|
||||||
"password={$password}",
|
"password={$password}",
|
||||||
$server->server_name ? "sni={$server->server_name}" : "",
|
$server['server_name'] ? "sni={$server['server_name']}" : "",
|
||||||
'tfo=true',
|
'tfo=true',
|
||||||
'udp-relay=true'
|
'udp-relay=true'
|
||||||
];
|
];
|
||||||
if (!empty($server->allow_insecure)) {
|
if (!empty($server['allow_insecure'])) {
|
||||||
array_push($config, $server->allow_insecure ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
array_push($config, $server['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||||
}
|
}
|
||||||
$config = array_filter($config);
|
$config = array_filter($config);
|
||||||
$uri = implode(',', $config);
|
$uri = implode(',', $config);
|
||||||
|
@ -2,56 +2,66 @@
|
|||||||
namespace App\Utils;
|
namespace App\Utils;
|
||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\ServerShadowsocks;
|
|
||||||
use App\Models\ServerTrojan;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
class URLSchemes
|
class URLSchemes
|
||||||
{
|
{
|
||||||
public static function buildShadowsocks(ServerShadowsocks $server, User $user)
|
public static function buildShadowsocks($server, User $user)
|
||||||
{
|
{
|
||||||
$name = rawurlencode($server->name);
|
$name = rawurlencode($server['name']);
|
||||||
$str = str_replace(
|
$str = str_replace(
|
||||||
['+', '/', '='],
|
['+', '/', '='],
|
||||||
['-', '_', ''],
|
['-', '_', ''],
|
||||||
base64_encode("{$server->cipher}:{$user->uuid}")
|
base64_encode("{$server['cipher']}:{$user['uuid']}")
|
||||||
);
|
);
|
||||||
return "ss://{$str}@{$server->host}:{$server->port}#{$name}\r\n";
|
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function buildShadowsocksSIP008($server, User $user)
|
||||||
|
{
|
||||||
|
$config = [
|
||||||
|
"id" => $server['id'],
|
||||||
|
"remark" => $server['name'],
|
||||||
|
"server" => $server['host'],
|
||||||
|
"server_port" => $server['port'],
|
||||||
|
"password" => $user['uuid'],
|
||||||
|
"method" => $server['cipher']
|
||||||
|
];
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
public static function buildVmess(Server $server, User $user)
|
public static function buildVmess($server, User $user)
|
||||||
{
|
{
|
||||||
$config = [
|
$config = [
|
||||||
"v" => "2",
|
"v" => "2",
|
||||||
"ps" => $server->name,
|
"ps" => $server['name'],
|
||||||
"add" => $server->host,
|
"add" => $server['host'],
|
||||||
"port" => $server->port,
|
"port" => $server['port'],
|
||||||
"id" => $user->uuid,
|
"id" => $user['uuid'],
|
||||||
"aid" => "2",
|
"aid" => $server['alter_id'],
|
||||||
"net" => $server->network,
|
"net" => $server['network'],
|
||||||
"type" => "none",
|
"type" => "none",
|
||||||
"host" => "",
|
"host" => "",
|
||||||
"path" => "",
|
"path" => "",
|
||||||
"tls" => $server->tls ? "tls" : ""
|
"tls" => $server['tls'] ? "tls" : ""
|
||||||
];
|
];
|
||||||
if ((string)$server->network === 'ws') {
|
if ((string)$server['network'] === 'ws') {
|
||||||
$wsSettings = json_decode($server->networkSettings);
|
$wsSettings = json_decode($server['networkSettings'], true);
|
||||||
if (isset($wsSettings->path)) $config['path'] = $wsSettings->path;
|
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||||
if (isset($wsSettings->headers->Host)) $config['host'] = $wsSettings->headers->Host;
|
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||||
}
|
}
|
||||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildTrojan(ServerTrojan $server, User $user)
|
public static function buildTrojan($server, User $user)
|
||||||
{
|
{
|
||||||
$name = rawurlencode($server->name);
|
$name = rawurlencode($server['name']);
|
||||||
$query = http_build_query([
|
$query = http_build_query([
|
||||||
'allowInsecure' => $server->allow_insecure,
|
'allowInsecure' => $server['allow_insecure'],
|
||||||
'peer' => $server->server_name,
|
'peer' => $server['server_name'],
|
||||||
'sni' => $server->server_name
|
'sni' => $server['server_name']
|
||||||
]);
|
]);
|
||||||
$uri = "trojan://{$user->uuid}@{$server->host}:{$server->port}?{$query}#{$name}";
|
$uri = "trojan://{$user['uuid']}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||||
$uri .= "\r\n";
|
$uri .= "\r\n";
|
||||||
return $uri;
|
return $uri;
|
||||||
}
|
}
|
||||||
|
@ -236,5 +236,5 @@ return [
|
|||||||
| The only modification by laravel config
|
| The only modification by laravel config
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
'version' => '1.4'
|
'version' => '1.4.1.1605605380'
|
||||||
];
|
];
|
||||||
|
@ -107,7 +107,7 @@ CREATE TABLE `v2_order` (
|
|||||||
`balance_amount` int(11) DEFAULT NULL COMMENT '使用余额',
|
`balance_amount` int(11) DEFAULT NULL COMMENT '使用余额',
|
||||||
`surplus_order_ids` text COMMENT '折抵订单',
|
`surplus_order_ids` text COMMENT '折抵订单',
|
||||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
||||||
`commission_status` tinyint(1) NOT NULL DEFAULT '0',
|
`commission_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待确认1发放中2有效3无效',
|
||||||
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
@ -152,6 +152,7 @@ CREATE TABLE `v2_server` (
|
|||||||
`tags` varchar(255) DEFAULT NULL,
|
`tags` varchar(255) DEFAULT NULL,
|
||||||
`rate` varchar(11) NOT NULL,
|
`rate` varchar(11) NOT NULL,
|
||||||
`network` text NOT NULL,
|
`network` text NOT NULL,
|
||||||
|
`alter_id` int(11) NOT NULL DEFAULT '1',
|
||||||
`settings` text,
|
`settings` text,
|
||||||
`rules` text,
|
`rules` text,
|
||||||
`networkSettings` text,
|
`networkSettings` text,
|
||||||
@ -217,6 +218,7 @@ DROP TABLE IF EXISTS `v2_server_stat`;
|
|||||||
CREATE TABLE `v2_server_stat` (
|
CREATE TABLE `v2_server_stat` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`server_id` int(11) NOT NULL,
|
`server_id` int(11) NOT NULL,
|
||||||
|
`method` varchar(255) NOT NULL,
|
||||||
`u` varchar(255) NOT NULL,
|
`u` varchar(255) NOT NULL,
|
||||||
`d` varchar(255) NOT NULL,
|
`d` varchar(255) NOT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
@ -295,8 +297,6 @@ CREATE TABLE `v2_user` (
|
|||||||
`last_login_at` int(11) DEFAULT NULL,
|
`last_login_at` int(11) DEFAULT NULL,
|
||||||
`last_login_ip` int(11) DEFAULT NULL,
|
`last_login_ip` int(11) DEFAULT NULL,
|
||||||
`uuid` varchar(36) NOT NULL,
|
`uuid` varchar(36) NOT NULL,
|
||||||
`v2ray_alter_id` tinyint(4) NOT NULL DEFAULT '2',
|
|
||||||
`v2ray_level` tinyint(4) NOT NULL DEFAULT '0',
|
|
||||||
`group_id` int(11) DEFAULT NULL,
|
`group_id` int(11) DEFAULT NULL,
|
||||||
`plan_id` int(11) DEFAULT NULL,
|
`plan_id` int(11) DEFAULT NULL,
|
||||||
`remind_expire` tinyint(4) DEFAULT '1',
|
`remind_expire` tinyint(4) DEFAULT '1',
|
||||||
@ -310,4 +310,4 @@ CREATE TABLE `v2_user` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- 2020-11-03 18:08:25
|
-- 2020-11-17 10:46:49
|
||||||
|
@ -342,3 +342,13 @@ CREATE TABLE `v2_knowledge` (
|
|||||||
|
|
||||||
ALTER TABLE `v2_order`
|
ALTER TABLE `v2_order`
|
||||||
ADD `coupon_id` int(11) NULL AFTER `plan_id`;
|
ADD `coupon_id` int(11) NULL AFTER `plan_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_server_stat`
|
||||||
|
ADD `method` varchar(255) NOT NULL AFTER `server_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_server`
|
||||||
|
ADD `alter_id` int(11) NOT NULL DEFAULT '1' AFTER `network`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_user`
|
||||||
|
DROP `v2ray_alter_id`,
|
||||||
|
DROP `v2ray_level`;
|
||||||
|
2
public/assets/admin/components.async.js
vendored
2
public/assets/admin/components.async.js
vendored
File diff suppressed because one or more lines are too long
28
public/assets/admin/components.chunk.css
vendored
28
public/assets/admin/components.chunk.css
vendored
File diff suppressed because one or more lines are too long
4
public/assets/admin/umi.css
vendored
4
public/assets/admin/umi.css
vendored
File diff suppressed because one or more lines are too long
2
public/assets/admin/umi.js
vendored
2
public/assets/admin/umi.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/admin/vendors.async.js
vendored
2
public/assets/admin/vendors.async.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/components.async.js
vendored
2
public/assets/user/components.async.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/umi.js
vendored
2
public/assets/user/umi.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/vendors.async.js
vendored
2
public/assets/user/vendors.async.js
vendored
File diff suppressed because one or more lines are too long
@ -8,14 +8,26 @@ experimental:
|
|||||||
ignore-resolve-fail: true
|
ignore-resolve-fail: true
|
||||||
dns:
|
dns:
|
||||||
enable: true
|
enable: true
|
||||||
|
# listen: 0.0.0.0:53
|
||||||
ipv6: false
|
ipv6: false
|
||||||
enhanced-mode: redir-host
|
|
||||||
nameserver:
|
default-nameserver:
|
||||||
- 1.2.4.8
|
|
||||||
- 223.5.5.5
|
- 223.5.5.5
|
||||||
|
- 119.29.29.29
|
||||||
|
enhanced-mode: redir-host
|
||||||
|
fake-ip-range: 198.18.0.1/16
|
||||||
|
use-hosts: true
|
||||||
|
nameserver:
|
||||||
|
- https://dns.alidns.com/dns-query
|
||||||
|
- https://doh.pub/dns-query
|
||||||
fallback:
|
fallback:
|
||||||
- tls://1.0.0.1:853
|
- tls://1.0.0.1:853
|
||||||
- tls://dns.google:853
|
- https://dns.google/dns-query
|
||||||
|
fallback-filter:
|
||||||
|
geoip: true
|
||||||
|
ipcidr:
|
||||||
|
- 240.0.0.0/4
|
||||||
|
|
||||||
proxies:
|
proxies:
|
||||||
|
|
||||||
proxy-groups:
|
proxy-groups:
|
||||||
|
@ -1,21 +1,37 @@
|
|||||||
port: 7890
|
# port: 7890
|
||||||
socks-port: 7891
|
# socks-port: 7891
|
||||||
allow-lan: false
|
# redir-port: 7892
|
||||||
|
# tproxy-port: 7893
|
||||||
|
mixed-port: 7890
|
||||||
|
allow-lan: true
|
||||||
|
bind-address: "*"
|
||||||
mode: rule
|
mode: rule
|
||||||
log-level: info
|
log-level: info
|
||||||
external-controller: 127.0.0.1:9090
|
external-controller: 127.0.0.1:9090
|
||||||
experimental:
|
|
||||||
ignore-resolve-fail: true
|
|
||||||
dns:
|
dns:
|
||||||
enable: true
|
enable: true
|
||||||
|
# listen: 0.0.0.0:53
|
||||||
ipv6: false
|
ipv6: false
|
||||||
enhanced-mode: redir-host
|
|
||||||
nameserver:
|
default-nameserver:
|
||||||
- 1.2.4.8
|
|
||||||
- 223.5.5.5
|
- 223.5.5.5
|
||||||
|
- 119.29.29.29
|
||||||
|
enhanced-mode: redir-host
|
||||||
|
fake-ip-range: 198.18.0.1/16
|
||||||
|
use-hosts: true
|
||||||
|
nameserver:
|
||||||
|
- https://doh.pub/dns-query
|
||||||
fallback:
|
fallback:
|
||||||
- tls://1.0.0.1:853
|
- tls://1.0.0.1:853
|
||||||
- tls://dns.google:853
|
- https://cloudflare-dns.com/dns-query
|
||||||
|
- https://dns.google/dns-query
|
||||||
|
fallback-filter:
|
||||||
|
geoip: true
|
||||||
|
ipcidr:
|
||||||
|
- 240.0.0.0/4
|
||||||
|
- 0.0.0.0/32
|
||||||
|
|
||||||
proxies:
|
proxies:
|
||||||
|
|
||||||
proxy-groups:
|
proxy-groups:
|
||||||
@ -24,34 +40,44 @@ proxy-groups:
|
|||||||
- { name: "故障转移", type: fallback, proxies: [], url: "http://www.gstatic.com/generate_204", interval: 7200 }
|
- { name: "故障转移", type: fallback, proxies: [], url: "http://www.gstatic.com/generate_204", interval: 7200 }
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
|
# 自定义规则
|
||||||
|
## 您可以在此处插入您补充的自定义规则(请注意保持缩进)
|
||||||
|
|
||||||
# Apple
|
# Apple
|
||||||
- DOMAIN,safebrowsing.urlsec.qq.com,DIRECT # 如果您并不信任此服务提供商或防止其下载消耗过多带宽资源,可以进入 Safari 设置,关闭 Fraudulent Website Warning 功能,并使用 REJECT 策略。
|
- DOMAIN,safebrowsing.urlsec.qq.com,DIRECT # 如果您并不信任此服务提供商或防止其下载消耗过多带宽资源,可以进入 Safari 设置,关闭 Fraudulent Website Warning 功能,并使用 REJECT 策略。
|
||||||
- DOMAIN,safebrowsing.googleapis.com,DIRECT # 如果您并不信任此服务提供商或防止其下载消耗过多带宽资源,可以进入 Safari 设置,关闭 Fraudulent Website Warning 功能,并使用 REJECT 策略。
|
- DOMAIN,safebrowsing.googleapis.com,DIRECT # 如果您并不信任此服务提供商或防止其下载消耗过多带宽资源,可以进入 Safari 设置,关闭 Fraudulent Website Warning 功能,并使用 REJECT 策略。
|
||||||
- DOMAIN,ocsp.apple.com,$app_name
|
- DOMAIN,developer.apple.com,$app_name
|
||||||
- DOMAIN-SUFFIX,digicert.com,$app_name
|
- DOMAIN-SUFFIX,digicert.com,$app_name
|
||||||
- DOMAIN-SUFFIX,entrust.net,$app_name
|
- DOMAIN,ocsp.apple.com,$app_name
|
||||||
|
- DOMAIN,ocsp.comodoca.com,$app_name
|
||||||
|
- DOMAIN,ocsp.usertrust.com,$app_name
|
||||||
|
- DOMAIN,ocsp.sectigo.com,$app_name
|
||||||
- DOMAIN,ocsp.verisign.net,$app_name
|
- DOMAIN,ocsp.verisign.net,$app_name
|
||||||
- DOMAIN-SUFFIX,apps.apple.com,$app_name
|
- DOMAIN-SUFFIX,apple-dns.net,$app_name
|
||||||
|
- DOMAIN,testflight.apple.com,$app_name
|
||||||
|
- DOMAIN,sandbox.itunes.apple.com,$app_name
|
||||||
- DOMAIN,itunes.apple.com,$app_name
|
- DOMAIN,itunes.apple.com,$app_name
|
||||||
|
- DOMAIN-SUFFIX,apps.apple.com,$app_name
|
||||||
- DOMAIN-SUFFIX,blobstore.apple.com,$app_name
|
- DOMAIN-SUFFIX,blobstore.apple.com,$app_name
|
||||||
- DOMAIN-SUFFIX,music.apple.com,DIRECT
|
- DOMAIN,cvws.icloud-content.com,$app_name
|
||||||
- DOMAIN-SUFFIX,mzstatic.com,DIRECT
|
- DOMAIN-SUFFIX,mzstatic.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,itunes.apple.com,DIRECT
|
- DOMAIN-SUFFIX,itunes.apple.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,icloud.com,DIRECT
|
- DOMAIN-SUFFIX,icloud.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,icloud-content.com,DIRECT
|
- DOMAIN-SUFFIX,icloud-content.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,me.com,DIRECT
|
- DOMAIN-SUFFIX,me.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,mzstatic.com,DIRECT
|
|
||||||
- DOMAIN-SUFFIX,akadns.net,DIRECT
|
|
||||||
- DOMAIN-SUFFIX,aaplimg.com,DIRECT
|
- DOMAIN-SUFFIX,aaplimg.com,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,cdn20.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,cdn-apple.com,DIRECT
|
- DOMAIN-SUFFIX,cdn-apple.com,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,akadns.net,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,akamaiedge.net,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,edgekey.net,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,mwcloudcdn.com,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,mwcname.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,apple.com,DIRECT
|
- DOMAIN-SUFFIX,apple.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT
|
- DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT
|
||||||
|
- DOMAIN-SUFFIX,apple-mapkit.com,DIRECT
|
||||||
# - DOMAIN,e.crashlytics.com,REJECT //注释此选项有助于大多数App开发者分析崩溃信息;如果您拒绝一切崩溃数据统计、搜集,请取消 # 注释。
|
# - DOMAIN,e.crashlytics.com,REJECT //注释此选项有助于大多数App开发者分析崩溃信息;如果您拒绝一切崩溃数据统计、搜集,请取消 # 注释。
|
||||||
|
|
||||||
|
|
||||||
# 自定义规则
|
|
||||||
## 您可以在此处插入您补充的自定义规则(请注意保持缩进)
|
|
||||||
|
|
||||||
# 国内网站
|
# 国内网站
|
||||||
- DOMAIN-SUFFIX,cn,DIRECT
|
- DOMAIN-SUFFIX,cn,DIRECT
|
||||||
- DOMAIN-KEYWORD,-cn,DIRECT
|
- DOMAIN-KEYWORD,-cn,DIRECT
|
||||||
@ -65,7 +91,6 @@ rules:
|
|||||||
- DOMAIN-SUFFIX,acfun.tv,DIRECT
|
- DOMAIN-SUFFIX,acfun.tv,DIRECT
|
||||||
- DOMAIN-SUFFIX,air-matters.com,DIRECT
|
- DOMAIN-SUFFIX,air-matters.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,aixifan.com,DIRECT
|
- DOMAIN-SUFFIX,aixifan.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,akamaized.net,DIRECT
|
|
||||||
- DOMAIN-KEYWORD,alicdn,DIRECT
|
- DOMAIN-KEYWORD,alicdn,DIRECT
|
||||||
- DOMAIN-KEYWORD,alipay,DIRECT
|
- DOMAIN-KEYWORD,alipay,DIRECT
|
||||||
- DOMAIN-KEYWORD,taobao,DIRECT
|
- DOMAIN-KEYWORD,taobao,DIRECT
|
||||||
@ -97,7 +122,6 @@ rules:
|
|||||||
- DOMAIN-SUFFIX,godic.net,DIRECT
|
- DOMAIN-SUFFIX,godic.net,DIRECT
|
||||||
- DOMAIN-SUFFIX,gtimg.com,DIRECT
|
- DOMAIN-SUFFIX,gtimg.com,DIRECT
|
||||||
- DOMAIN,cdn.hockeyapp.net,DIRECT
|
- DOMAIN,cdn.hockeyapp.net,DIRECT
|
||||||
- DOMAIN-SUFFIX,hdslb.com,DIRECT
|
|
||||||
- DOMAIN-SUFFIX,hongxiu.com,DIRECT
|
- DOMAIN-SUFFIX,hongxiu.com,DIRECT
|
||||||
- DOMAIN-SUFFIX,hxcdn.net,DIRECT
|
- DOMAIN-SUFFIX,hxcdn.net,DIRECT
|
||||||
- DOMAIN-SUFFIX,iciba.com,DIRECT
|
- DOMAIN-SUFFIX,iciba.com,DIRECT
|
||||||
@ -209,21 +233,24 @@ rules:
|
|||||||
- DOMAIN-KEYWORD,adsrvmedia,REJECT
|
- DOMAIN-KEYWORD,adsrvmedia,REJECT
|
||||||
- DOMAIN-KEYWORD,adwords,REJECT
|
- DOMAIN-KEYWORD,adwords,REJECT
|
||||||
- DOMAIN-KEYWORD,adservice,REJECT
|
- DOMAIN-KEYWORD,adservice,REJECT
|
||||||
|
- DOMAIN-SUFFIX,appsflyer.com,REJECT
|
||||||
- DOMAIN-KEYWORD,domob,REJECT
|
- DOMAIN-KEYWORD,domob,REJECT
|
||||||
|
- DOMAIN-SUFFIX,doubleclick.net,REJECT
|
||||||
- DOMAIN-KEYWORD,duomeng,REJECT
|
- DOMAIN-KEYWORD,duomeng,REJECT
|
||||||
- DOMAIN-KEYWORD,dwtrack,REJECT
|
- DOMAIN-KEYWORD,dwtrack,REJECT
|
||||||
- DOMAIN-KEYWORD,guanggao,REJECT
|
- DOMAIN-KEYWORD,guanggao,REJECT
|
||||||
- DOMAIN-KEYWORD,lianmeng,REJECT
|
- DOMAIN-KEYWORD,lianmeng,REJECT
|
||||||
- DOMAIN-SUFFIX,mmstat.com,REJECT
|
- DOMAIN-SUFFIX,mmstat.com,REJECT
|
||||||
|
- DOMAIN-KEYWORD,mopub,REJECT
|
||||||
- DOMAIN-KEYWORD,omgmta,REJECT
|
- DOMAIN-KEYWORD,omgmta,REJECT
|
||||||
- DOMAIN-KEYWORD,openx,REJECT
|
- DOMAIN-KEYWORD,openx,REJECT
|
||||||
- DOMAIN-KEYWORD,partnerad,REJECT
|
- DOMAIN-KEYWORD,partnerad,REJECT
|
||||||
- DOMAIN-KEYWORD,pingfore,REJECT
|
- DOMAIN-KEYWORD,pingfore,REJECT
|
||||||
- DOMAIN-KEYWORD,supersonicads,REJECT
|
- DOMAIN-KEYWORD,supersonicads,REJECT
|
||||||
- DOMAIN-KEYWORD,tracking,REJECT
|
|
||||||
- DOMAIN-KEYWORD,uedas,REJECT
|
- DOMAIN-KEYWORD,uedas,REJECT
|
||||||
- DOMAIN-KEYWORD,umeng,REJECT
|
- DOMAIN-KEYWORD,umeng,REJECT
|
||||||
- DOMAIN-KEYWORD,usage,REJECT
|
- DOMAIN-KEYWORD,usage,REJECT
|
||||||
|
- DOMAIN-SUFFIX,vungle.com,REJECT
|
||||||
- DOMAIN-KEYWORD,wlmonitor,REJECT
|
- DOMAIN-KEYWORD,wlmonitor,REJECT
|
||||||
- DOMAIN-KEYWORD,zjtoolbar,REJECT
|
- DOMAIN-KEYWORD,zjtoolbar,REJECT
|
||||||
|
|
||||||
@ -232,6 +259,7 @@ rules:
|
|||||||
- DOMAIN-SUFFIX,abpchina.org,$app_name
|
- DOMAIN-SUFFIX,abpchina.org,$app_name
|
||||||
- DOMAIN-SUFFIX,adblockplus.org,$app_name
|
- DOMAIN-SUFFIX,adblockplus.org,$app_name
|
||||||
- DOMAIN-SUFFIX,adobe.com,$app_name
|
- DOMAIN-SUFFIX,adobe.com,$app_name
|
||||||
|
- DOMAIN-SUFFIX,akamaized.net,$app_name
|
||||||
- DOMAIN-SUFFIX,alfredapp.com,$app_name
|
- DOMAIN-SUFFIX,alfredapp.com,$app_name
|
||||||
- DOMAIN-SUFFIX,amplitude.com,$app_name
|
- DOMAIN-SUFFIX,amplitude.com,$app_name
|
||||||
- DOMAIN-SUFFIX,ampproject.org,$app_name
|
- DOMAIN-SUFFIX,ampproject.org,$app_name
|
||||||
@ -499,18 +527,18 @@ rules:
|
|||||||
# Telegram
|
# Telegram
|
||||||
- DOMAIN-SUFFIX,telegra.ph,$app_name
|
- DOMAIN-SUFFIX,telegra.ph,$app_name
|
||||||
- DOMAIN-SUFFIX,telegram.org,$app_name
|
- DOMAIN-SUFFIX,telegram.org,$app_name
|
||||||
|
|
||||||
- IP-CIDR,91.108.4.0/22,$app_name,no-resolve
|
- IP-CIDR,91.108.4.0/22,$app_name,no-resolve
|
||||||
- IP-CIDR,91.108.8.0/22,$app_name,no-resolve
|
- IP-CIDR,91.108.8.0/21,$app_name,no-resolve
|
||||||
- IP-CIDR,91.108.12.0/22,$app_name,no-resolve
|
|
||||||
- IP-CIDR,91.108.16.0/22,$app_name,no-resolve
|
- IP-CIDR,91.108.16.0/22,$app_name,no-resolve
|
||||||
- IP-CIDR,91.108.56.0/22,$app_name,no-resolve
|
- IP-CIDR,91.108.56.0/22,$app_name,no-resolve
|
||||||
- IP-CIDR,149.154.160.0/22,$app_name,no-resolve
|
- IP-CIDR,149.154.160.0/20,$app_name,no-resolve
|
||||||
- IP-CIDR,149.154.164.0/22,$app_name,no-resolve
|
- IP-CIDR6,2001:67c:4e8::/48,$app_name,no-resolve
|
||||||
- IP-CIDR,149.154.168.0/22,$app_name,no-resolve
|
- IP-CIDR6,2001:b28:f23d::/48,$app_name,no-resolve
|
||||||
- IP-CIDR,149.154.172.0/22,$app_name,no-resolve
|
- IP-CIDR6,2001:b28:f23f::/48,$app_name,no-resolve
|
||||||
|
|
||||||
# LAN
|
# LAN
|
||||||
|
- DOMAIN,injections.adguard.org,DIRECT
|
||||||
|
- DOMAIN,local.adguard.org,DIRECT
|
||||||
- DOMAIN-SUFFIX,local,DIRECT
|
- DOMAIN-SUFFIX,local,DIRECT
|
||||||
- IP-CIDR,127.0.0.0/8,DIRECT
|
- IP-CIDR,127.0.0.0/8,DIRECT
|
||||||
- IP-CIDR,172.16.0.0/12,DIRECT
|
- IP-CIDR,172.16.0.0/12,DIRECT
|
||||||
@ -518,6 +546,8 @@ rules:
|
|||||||
- IP-CIDR,10.0.0.0/8,DIRECT
|
- IP-CIDR,10.0.0.0/8,DIRECT
|
||||||
- IP-CIDR,17.0.0.0/8,DIRECT
|
- IP-CIDR,17.0.0.0/8,DIRECT
|
||||||
- IP-CIDR,100.64.0.0/10,DIRECT
|
- IP-CIDR,100.64.0.0/10,DIRECT
|
||||||
|
- IP-CIDR,224.0.0.0/4,DIRECT
|
||||||
|
- IP-CIDR6,fe80::/10,DIRECT
|
||||||
|
|
||||||
# 最终规则
|
# 最终规则
|
||||||
- GEOIP,CN,DIRECT
|
- GEOIP,CN,DIRECT
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
[General]
|
[General]
|
||||||
loglevel = notify
|
loglevel = notify
|
||||||
interface = 127.0.0.1
|
interface = 127.0.0.1
|
||||||
skip-proxy = localhost, *.local, 0.0.0.0/8, 10.0.0.0/8, 17.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, 255.255.255.255/32
|
skip-proxy = localhost, *.local, injections.adguard.org, local.adguard.org, 0.0.0.0/8, 10.0.0.0/8, 17.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, 255.255.255.255/32
|
||||||
ipv6 = false
|
ipv6 = true
|
||||||
dns-server = 1.2.4.8, 114.114.114.114, 223.5.5.5, 8.8.8.8, system
|
dns-server = 1.2.4.8, 114.114.114.114, 223.5.5.5, 119.29.29.29
|
||||||
exclude-simple-hostnames = true
|
exclude-simple-hostnames = true
|
||||||
enhanced-mode-by-rule = true
|
enhanced-mode-by-rule = true
|
||||||
|
|
||||||
@ -39,24 +39,38 @@ DOMAIN-SUFFIX,appspot.com,Proxy,force-remote-dns
|
|||||||
DOMAIN-KEYWORD,google,Proxy,force-remote-dns
|
DOMAIN-KEYWORD,google,Proxy,force-remote-dns
|
||||||
|
|
||||||
# Apple
|
# Apple
|
||||||
DOMAIN,ocsp.apple.com,Proxy
|
DOMAIN,safebrowsing.urlsec.qq.com,DIRECT
|
||||||
|
DOMAIN,safebrowsing.googleapis.com,DIRECT
|
||||||
|
DOMAIN,developer.apple.com,Proxy
|
||||||
DOMAIN-SUFFIX,digicert.com,Proxy
|
DOMAIN-SUFFIX,digicert.com,Proxy
|
||||||
DOMAIN-SUFFIX,entrust.net,Proxy
|
DOMAIN,ocsp.apple.com,Proxy
|
||||||
|
DOMAIN,ocsp.comodoca.com,Proxy
|
||||||
|
DOMAIN,ocsp.usertrust.com,Proxy
|
||||||
|
DOMAIN,ocsp.sectigo.com,Proxy
|
||||||
DOMAIN,ocsp.verisign.net,Proxy
|
DOMAIN,ocsp.verisign.net,Proxy
|
||||||
DOMAIN,itunes.apple.com,Proxy,force-remote-dns
|
DOMAIN-SUFFIX,apple-dns.net,Proxy
|
||||||
DOMAIN-SUFFIX,apps.apple.com,Proxy,force-remote-dns
|
DOMAIN,testflight.apple.com,Proxy
|
||||||
|
DOMAIN,sandbox.itunes.apple.com,Proxy
|
||||||
|
DOMAIN,itunes.apple.com,Proxy
|
||||||
|
DOMAIN-SUFFIX,apps.apple.com,Proxy
|
||||||
DOMAIN-SUFFIX,blobstore.apple.com,Proxy
|
DOMAIN-SUFFIX,blobstore.apple.com,Proxy
|
||||||
DOMAIN-SUFFIX,music.apple.com,DIRECT,force-remote-dns
|
DOMAIN,cvws.icloud-content.com,Proxy
|
||||||
DOMAIN-SUFFIX,mzstatic.com,DIRECT
|
DOMAIN-SUFFIX,mzstatic.com,DIRECT
|
||||||
DOMAIN-SUFFIX,itunes.apple.com,DIRECT
|
DOMAIN-SUFFIX,itunes.apple.com,DIRECT
|
||||||
DOMAIN-SUFFIX,icloud.com,DIRECT
|
DOMAIN-SUFFIX,icloud.com,DIRECT
|
||||||
DOMAIN-SUFFIX,icloud-content.com,DIRECT
|
DOMAIN-SUFFIX,icloud-content.com,DIRECT
|
||||||
DOMAIN-SUFFIX,me.com,DIRECT
|
DOMAIN-SUFFIX,me.com,DIRECT
|
||||||
DOMAIN-SUFFIX,akadns.net,DIRECT
|
|
||||||
DOMAIN-SUFFIX,aaplimg.com,DIRECT
|
DOMAIN-SUFFIX,aaplimg.com,DIRECT
|
||||||
|
DOMAIN-SUFFIX,cdn20.com,DIRECT
|
||||||
DOMAIN-SUFFIX,cdn-apple.com,DIRECT
|
DOMAIN-SUFFIX,cdn-apple.com,DIRECT
|
||||||
|
DOMAIN-SUFFIX,akadns.net,DIRECT
|
||||||
|
DOMAIN-SUFFIX,akamaiedge.net,DIRECT
|
||||||
|
DOMAIN-SUFFIX,edgekey.net,DIRECT
|
||||||
|
DOMAIN-SUFFIX,mwcloudcdn.com,DIRECT
|
||||||
|
DOMAIN-SUFFIX,mwcname.com,DIRECT
|
||||||
DOMAIN-SUFFIX,apple.com,DIRECT
|
DOMAIN-SUFFIX,apple.com,DIRECT
|
||||||
DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT
|
DOMAIN-SUFFIX,apple-cloudkit.com,DIRECT
|
||||||
|
DOMAIN-SUFFIX,apple-mapkit.com,DIRECT
|
||||||
|
|
||||||
# 国内网站
|
# 国内网站
|
||||||
DOMAIN-SUFFIX,cn,DIRECT
|
DOMAIN-SUFFIX,cn,DIRECT
|
||||||
@ -71,7 +85,6 @@ DOMAIN-SUFFIX,36kr.com,DIRECT
|
|||||||
DOMAIN-SUFFIX,acfun.tv,DIRECT
|
DOMAIN-SUFFIX,acfun.tv,DIRECT
|
||||||
DOMAIN-SUFFIX,air-matters.com,DIRECT
|
DOMAIN-SUFFIX,air-matters.com,DIRECT
|
||||||
DOMAIN-SUFFIX,aixifan.com,DIRECT
|
DOMAIN-SUFFIX,aixifan.com,DIRECT
|
||||||
DOMAIN-SUFFIX,akamaized.net,DIRECT
|
|
||||||
DOMAIN-KEYWORD,alicdn,DIRECT
|
DOMAIN-KEYWORD,alicdn,DIRECT
|
||||||
DOMAIN-KEYWORD,alipay,DIRECT
|
DOMAIN-KEYWORD,alipay,DIRECT
|
||||||
DOMAIN-KEYWORD,taobao,DIRECT
|
DOMAIN-KEYWORD,taobao,DIRECT
|
||||||
@ -190,8 +203,38 @@ DOMAIN-SUFFIX,zhimg.com,DIRECT
|
|||||||
DOMAIN-SUFFIX,zimuzu.tv,DIRECT
|
DOMAIN-SUFFIX,zimuzu.tv,DIRECT
|
||||||
DOMAIN-SUFFIX,zoho.com,DIRECT
|
DOMAIN-SUFFIX,zoho.com,DIRECT
|
||||||
|
|
||||||
# 抗 DNS 污染
|
# 常见广告域名屏蔽
|
||||||
|
DOMAIN-KEYWORD,admarvel,REJECT
|
||||||
|
DOMAIN-KEYWORD,admaster,REJECT
|
||||||
|
DOMAIN-KEYWORD,adsage,REJECT
|
||||||
|
DOMAIN-KEYWORD,adsmogo,REJECT
|
||||||
|
DOMAIN-KEYWORD,adsrvmedia,REJECT
|
||||||
|
DOMAIN-KEYWORD,adwords,REJECT
|
||||||
|
DOMAIN-KEYWORD,adservice,REJECT
|
||||||
|
DOMAIN-SUFFIX,appsflyer.com,REJECT
|
||||||
|
DOMAIN-KEYWORD,domob,REJECT
|
||||||
|
DOMAIN-SUFFIX,doubleclick.net,REJECT
|
||||||
|
DOMAIN-KEYWORD,duomeng,REJECT
|
||||||
|
DOMAIN-KEYWORD,dwtrack,REJECT
|
||||||
|
DOMAIN-KEYWORD,guanggao,REJECT
|
||||||
|
DOMAIN-KEYWORD,lianmeng,REJECT
|
||||||
|
DOMAIN-SUFFIX,mmstat.com,REJECT
|
||||||
|
DOMAIN-KEYWORD,mopub,REJECT
|
||||||
|
DOMAIN-KEYWORD,omgmta,REJECT
|
||||||
|
DOMAIN-KEYWORD,openx,REJECT
|
||||||
|
DOMAIN-KEYWORD,partnerad,REJECT
|
||||||
|
DOMAIN-KEYWORD,pingfore,REJECT
|
||||||
|
DOMAIN-KEYWORD,supersonicads,REJECT
|
||||||
|
DOMAIN-KEYWORD,uedas,REJECT
|
||||||
|
DOMAIN-KEYWORD,umeng,REJECT
|
||||||
|
DOMAIN-KEYWORD,usage,REJECT
|
||||||
|
DOMAIN-SUFFIX,vungle.com,REJECT
|
||||||
|
DOMAIN-KEYWORD,wlmonitor,REJECT
|
||||||
|
DOMAIN-KEYWORD,zjtoolbar,REJECT
|
||||||
|
|
||||||
|
# 抗 DNS 污染
|
||||||
DOMAIN-KEYWORD,amazon,Proxy
|
DOMAIN-KEYWORD,amazon,Proxy
|
||||||
|
DOMAIN-KEYWORD,google,Proxy
|
||||||
DOMAIN-KEYWORD,gmail,Proxy
|
DOMAIN-KEYWORD,gmail,Proxy
|
||||||
DOMAIN-KEYWORD,youtube,Proxy
|
DOMAIN-KEYWORD,youtube,Proxy
|
||||||
DOMAIN-KEYWORD,facebook,Proxy
|
DOMAIN-KEYWORD,facebook,Proxy
|
||||||
@ -205,36 +248,12 @@ DOMAIN-KEYWORD,blogspot,Proxy
|
|||||||
DOMAIN-SUFFIX,youtu.be,Proxy
|
DOMAIN-SUFFIX,youtu.be,Proxy
|
||||||
DOMAIN-KEYWORD,whatsapp,Proxy
|
DOMAIN-KEYWORD,whatsapp,Proxy
|
||||||
|
|
||||||
# 常见广告域名关键词屏蔽
|
|
||||||
DOMAIN-KEYWORD,admarvel,REJECT
|
|
||||||
DOMAIN-KEYWORD,admaster,REJECT
|
|
||||||
DOMAIN-KEYWORD,adsage,REJECT
|
|
||||||
DOMAIN-KEYWORD,adsmogo,REJECT
|
|
||||||
DOMAIN-KEYWORD,adsrvmedia,REJECT
|
|
||||||
DOMAIN-KEYWORD,adwords,REJECT
|
|
||||||
DOMAIN-KEYWORD,adservice,REJECT
|
|
||||||
DOMAIN-KEYWORD,domob,REJECT
|
|
||||||
DOMAIN-KEYWORD,duomeng,REJECT
|
|
||||||
DOMAIN-KEYWORD,dwtrack,REJECT
|
|
||||||
DOMAIN-KEYWORD,guanggao,REJECT
|
|
||||||
DOMAIN-KEYWORD,lianmeng,REJECT
|
|
||||||
DOMAIN-SUFFIX,mmstat.com,REJECT
|
|
||||||
DOMAIN-KEYWORD,omgmta,REJECT
|
|
||||||
DOMAIN-KEYWORD,openx,REJECT
|
|
||||||
DOMAIN-KEYWORD,partnerad,REJECT
|
|
||||||
DOMAIN-KEYWORD,pingfore,REJECT
|
|
||||||
DOMAIN-KEYWORD,supersonicads,REJECT
|
|
||||||
DOMAIN-KEYWORD,uedas,REJECT
|
|
||||||
DOMAIN-KEYWORD,umeng,REJECT
|
|
||||||
DOMAIN-KEYWORD,usage,REJECT
|
|
||||||
DOMAIN-KEYWORD,wlmonitor,REJECT
|
|
||||||
DOMAIN-KEYWORD,zjtoolbar,REJECT
|
|
||||||
|
|
||||||
# 国外网站
|
# 国外网站
|
||||||
DOMAIN-SUFFIX,9to5mac.com,Proxy
|
DOMAIN-SUFFIX,9to5mac.com,Proxy
|
||||||
DOMAIN-SUFFIX,abpchina.org,Proxy
|
DOMAIN-SUFFIX,abpchina.org,Proxy
|
||||||
DOMAIN-SUFFIX,adblockplus.org,Proxy
|
DOMAIN-SUFFIX,adblockplus.org,Proxy
|
||||||
DOMAIN-SUFFIX,adobe.com,Proxy
|
DOMAIN-SUFFIX,adobe.com,Proxy
|
||||||
|
DOMAIN-SUFFIX,akamaized.net,Proxy
|
||||||
DOMAIN-SUFFIX,alfredapp.com,Proxy
|
DOMAIN-SUFFIX,alfredapp.com,Proxy
|
||||||
DOMAIN-SUFFIX,amplitude.com,Proxy
|
DOMAIN-SUFFIX,amplitude.com,Proxy
|
||||||
DOMAIN-SUFFIX,ampproject.org,Proxy
|
DOMAIN-SUFFIX,ampproject.org,Proxy
|
||||||
@ -499,16 +518,14 @@ DOMAIN-SUFFIX,ytimg.com,Proxy
|
|||||||
# Telegram
|
# Telegram
|
||||||
DOMAIN-SUFFIX,telegra.ph,Proxy
|
DOMAIN-SUFFIX,telegra.ph,Proxy
|
||||||
DOMAIN-SUFFIX,telegram.org,Proxy
|
DOMAIN-SUFFIX,telegram.org,Proxy
|
||||||
|
IP-CIDR,91.108.4.0/22,Proxy,no-resolve
|
||||||
IP-CIDR,91.108.4.0/22,Proxy
|
IP-CIDR,91.108.8.0/21,Proxy,no-resolve
|
||||||
IP-CIDR,91.108.8.0/22,Proxy
|
IP-CIDR,91.108.16.0/22,Proxy,no-resolve
|
||||||
IP-CIDR,91.108.12.0/22,Proxy
|
IP-CIDR,91.108.56.0/22,Proxy,no-resolve
|
||||||
IP-CIDR,91.108.16.0/22,Proxy
|
IP-CIDR,149.154.160.0/20,Proxy,no-resolve
|
||||||
IP-CIDR,91.108.56.0/22,Proxy
|
IP-CIDR6,2001:67c:4e8::/48,Proxy,no-resolve
|
||||||
IP-CIDR,149.154.160.0/22,Proxy
|
IP-CIDR6,2001:b28:f23d::/48,Proxy,no-resolve
|
||||||
IP-CIDR,149.154.164.0/22,Proxy
|
IP-CIDR6,2001:b28:f23f::/48,Proxy,no-resolve
|
||||||
IP-CIDR,149.154.168.0/22,Proxy
|
|
||||||
IP-CIDR,149.154.172.0/22,Proxy
|
|
||||||
|
|
||||||
# LAN
|
# LAN
|
||||||
DOMAIN-SUFFIX,local,DIRECT
|
DOMAIN-SUFFIX,local,DIRECT
|
||||||
@ -518,6 +535,8 @@ IP-CIDR,192.168.0.0/16,DIRECT
|
|||||||
IP-CIDR,10.0.0.0/8,DIRECT
|
IP-CIDR,10.0.0.0/8,DIRECT
|
||||||
IP-CIDR,17.0.0.0/8,DIRECT
|
IP-CIDR,17.0.0.0/8,DIRECT
|
||||||
IP-CIDR,100.64.0.0/10,DIRECT
|
IP-CIDR,100.64.0.0/10,DIRECT
|
||||||
|
IP-CIDR,224.0.0.0/4,DIRECT
|
||||||
|
IP-CIDR6,fe80::/10,DIRECT
|
||||||
|
|
||||||
# 最终规则
|
# 最终规则
|
||||||
GEOIP,CN,DIRECT
|
GEOIP,CN,DIRECT
|
||||||
|
@ -1,26 +1,33 @@
|
|||||||
#!MANAGED-CONFIG $subs_link interval=43200 strict=true
|
#!MANAGED-CONFIG $subs_link interval=43200 strict=true
|
||||||
|
# Surge 的规则配置手册: https://manual.nssurge.com/
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
loglevel = notify
|
loglevel = notify
|
||||||
dns-server = 1.2.4.8, 114.114.114.114, 223.5.5.5, 8.8.8.8, system
|
# 从 Surge iOS 4 / Surge Mac 3.3.0 起,工具开始支持 DoH
|
||||||
|
doh-server = https://doh.pub/dns-query
|
||||||
|
# https://dns.alidns.com/dns-query, https://13800000000.rubyfish.cn/, https://dns.google/dns-query
|
||||||
|
dns-server = 223.5.5.5, 114.114.114.114
|
||||||
tun-excluded-routes = 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 255.255.255.255/32
|
tun-excluded-routes = 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 255.255.255.255/32
|
||||||
skip-proxy = localhost, *.local, captive.apple.com, 0.0.0.0/8, 10.0.0.0/8, 17.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, 255.255.255.255/32
|
skip-proxy = localhost, *.local, injections.adguard.org, local.adguard.org, captive.apple.com, guzzoni.apple.com, 0.0.0.0/8, 10.0.0.0/8, 17.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, 255.255.255.255/32
|
||||||
|
|
||||||
|
wifi-assist = true
|
||||||
allow-wifi-access = true
|
allow-wifi-access = true
|
||||||
wifi-access-http-port = 6152
|
wifi-access-http-port = 6152
|
||||||
wifi-access-socks5-port = 6153
|
wifi-access-socks5-port = 6153
|
||||||
http-listen = 0.0.0.0:6152
|
http-listen = 0.0.0.0:6152
|
||||||
socks5-listen = 0.0.0.0:6153
|
socks5-listen = 0.0.0.0:6153
|
||||||
|
|
||||||
test-timeout = 4
|
|
||||||
network-framework = false
|
|
||||||
proxy-test-url = http://www.gstatic.com/generate_204
|
|
||||||
|
|
||||||
external-controller-access = surgepasswd@0.0.0.0:6170
|
external-controller-access = surgepasswd@0.0.0.0:6170
|
||||||
exclude-simple-hostnames = true
|
|
||||||
ipv6 = false
|
|
||||||
replica = false
|
replica = false
|
||||||
|
|
||||||
|
tls-provider = openssl
|
||||||
|
network-framework = false
|
||||||
|
exclude-simple-hostnames = true
|
||||||
|
ipv6 = true
|
||||||
|
|
||||||
|
test-timeout = 4
|
||||||
|
proxy-test-url = http://www.gstatic.com/generate_204
|
||||||
|
|
||||||
[Replica]
|
[Replica]
|
||||||
hide-apple-request = true
|
hide-apple-request = true
|
||||||
hide-crashlytics-request = true
|
hide-crashlytics-request = true
|
||||||
@ -29,6 +36,8 @@ hide-udp = false
|
|||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
# Surge 的几种策略配置规范,请参考 https://manual.nssurge.com/policy/proxy.html
|
# Surge 的几种策略配置规范,请参考 https://manual.nssurge.com/policy/proxy.html
|
||||||
|
# 不同的代理策略有*很多*可选参数,请参考上方连接的 Parameters 一段,根据需求自行添加参数。
|
||||||
|
#
|
||||||
# Surge 现已支持 UDP 转发功能,请参考: https://trello.com/c/ugOMxD3u/53-udp-%E8%BD%AC%E5%8F%91
|
# Surge 现已支持 UDP 转发功能,请参考: https://trello.com/c/ugOMxD3u/53-udp-%E8%BD%AC%E5%8F%91
|
||||||
# Surge 现已支持 TCP-Fast-Open 技术,请参考: https://trello.com/c/ij65BU6Q/48-tcp-fast-open-troubleshooting-guide
|
# Surge 现已支持 TCP-Fast-Open 技术,请参考: https://trello.com/c/ij65BU6Q/48-tcp-fast-open-troubleshooting-guide
|
||||||
# Surge 现已支持 ss-libev 的全部加密方式和混淆,请参考: https://trello.com/c/BTr0vG1O/47-ss-libev-%E7%9A%84%E6%94%AF%E6%8C%81%E6%83%85%E5%86%B5
|
# Surge 现已支持 ss-libev 的全部加密方式和混淆,请参考: https://trello.com/c/BTr0vG1O/47-ss-libev-%E7%9A%84%E6%94%AF%E6%8C%81%E6%83%85%E5%86%B5
|
||||||
@ -47,13 +56,13 @@ fallback = fallback, $proxy_group, url=http://www.gstatic.com/generate_204, inte
|
|||||||
## 您可以在此处插入自定义规则
|
## 您可以在此处插入自定义规则
|
||||||
|
|
||||||
# 实用规则片段集
|
# 实用规则片段集
|
||||||
# RULE-SET,SYSTEM,DIRECT
|
# RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/Apple-News.list,Proxy
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Basic/Apple-proxy.list,Proxy
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/Apple-proxy.list,Proxy
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Basic/Apple-direct.list,DIRECT
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/Apple-direct.list,DIRECT
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Basic/CN.list,DIRECT
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/CN.list,DIRECT
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Basic/common-ad-keyword.list,REJECT-TINYGIF
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/common-ad-keyword.list,REJECT-TINYGIF
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Basic/foreign.list,Proxy
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/Basic/foreign.list,Proxy
|
||||||
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/App/social/Telegram.list,Proxy
|
RULE-SET,https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Surge/App/social/Telegram.list,Proxy
|
||||||
RULE-SET,LAN,DIRECT
|
RULE-SET,LAN,DIRECT
|
||||||
|
|
||||||
# 最终规则
|
# 最终规则
|
||||||
|
@ -169,7 +169,7 @@
|
|||||||
align="center" valign="top">
|
align="center" valign="top">
|
||||||
<a href="{{$url}}/#/subscribe"
|
<a href="{{$url}}/#/subscribe"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
||||||
<a href="{{$url}}/#/tutorial"
|
<a href="{{$url}}/#/knowledge"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -169,7 +169,7 @@
|
|||||||
align="center" valign="top">
|
align="center" valign="top">
|
||||||
<a href="{{$url}}/#/subscribe"
|
<a href="{{$url}}/#/subscribe"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
||||||
<a href="{{$url}}/#/tutorial"
|
<a href="{{$url}}/#/knowledge"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -184,4 +184,4 @@
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -169,7 +169,7 @@
|
|||||||
align="center" valign="top">
|
align="center" valign="top">
|
||||||
<a href="{{$url}}/#/subscribe"
|
<a href="{{$url}}/#/subscribe"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
||||||
<a href="{{$url}}/#/tutorial"
|
<a href="{{$url}}/#/knowledge"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -184,4 +184,4 @@
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -177,7 +177,7 @@
|
|||||||
align="center" valign="top">
|
align="center" valign="top">
|
||||||
<a href="{{$url}}/#/subscribe"
|
<a href="{{$url}}/#/subscribe"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">我的订阅</a> |
|
||||||
<a href="{{$url}}/#/tutorial"
|
<a href="{{$url}}/#/knowledge"
|
||||||
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: none; margin: 0;">使用教程</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -192,4 +192,4 @@
|
|||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user