Merge pull request #356 from v2board/dev

1.4.1
This commit is contained in:
tokumeikoi 2020-12-11 16:09:12 +08:00 committed by GitHub
commit c72e6cf4ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 873 additions and 772 deletions

View File

@ -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();
}
} }
} }
} }

View File

@ -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配置状态');
} }
} }

View File

@ -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();

View File

@ -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')) {

View 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
]);
}
}

View File

@ -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
]);
}
} }

View File

@ -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();

View File

@ -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
]);
}
} }

View File

@ -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')
] ]
]); ]);

View File

@ -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) {

View File

@ -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);

View File

@ -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')
] ]
]); ]);
} }

View File

@ -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,

View File

@ -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);
} }
} }

View File

@ -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));
}
} }

View File

@ -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();

View File

@ -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, '这个计划无法使用该优惠码');
} }

View File

@ -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);

View File

@ -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

View File

@ -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',
], ],
]; ];

View File

@ -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' => ''
]; ];
} }

View File

@ -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'
]; ];
} }

View File

@ -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'
]; ];
} }

View File

@ -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格式有误'
];
}
}

View File

@ -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格式有误'
];
}
}

View File

@ -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' => '',

View File

@ -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格式有误'
];
}
}

View File

@ -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) {

View File

@ -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');
}); });

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}
} }

View File

@ -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;
} }
} }

View File

@ -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' => '节点最后检查时间',

View File

@ -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;
} }
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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}");
} }
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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'
]; ];

View File

@ -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

View File

@ -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`;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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
# 最终规则 # 最终规则

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>