v2borad-master/app/Utils/Client/Protocols/Clash.php

210 lines
8.3 KiB
PHP

<?php
namespace App\Utils\Client\Protocols;
use Symfony\Component\Yaml\Yaml;
use App\Utils\Client\Protocol;
use App\Utils\Helper;
use Config;
class Clash extends Protocol
{
public $flag = 'clash';
public function handle()
{
$servers = $this->servers;
$user = $this->user;
$reqFlags = $this->requestFlag;
$appName = urlencode(config('v2board.app_name', 'V2Board'));
header("subscription-userinfo: upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}");
header('profile-update-interval: 24');
header("content-disposition:attachment;filename*=UTF-8''".$appName);
if (strpos($reqFlags, 'pro') !== false) {
$defaultConfig = resource_path() . '/rules/default.clash.pro.yaml';
$customConfig = resource_path() . '/rules/custom.clash.pro.yaml';
} else {
$defaultConfig = base_path() . '/resources/rules/default.clash.yaml';
$customConfig = base_path() . '/resources/rules/custom.clash.yaml';
}
if (\File::exists($customConfig)) {
$config = Yaml::parseFile($customConfig);
} else {
$config = Yaml::parseFile($defaultConfig);
}
$proxy = [];
$proxies = [];
$proxiesOther = [];
foreach ($servers as $item) {
$isGroups = false;
if (!empty($item['tags'])) {
foreach ($item['tags'] as $tag) {
if (strpos($tag, 'node:') === 0) {
$group = substr($tag, 5);
if ($group !== '') {
$proxiesOther[$group][] = $item['name'];
if (strpos($item['name'], $group) !== false) {
$isGroups = true;
}
}
}
}
}
switch ($item['type']) {
case 'shadowsocks':
$proxy[] = self::buildShadowsocks($user['uuid'], $item);
break;
case 'v2ray':
$proxy[] = self::buildVmess($user['uuid'], $item);
break;
case 'trojan':
$proxy[] = self::buildTrojan($user['uuid'], $item);
break;
default:
continue 2;
}
if (!$isGroups) {
$proxies[] = $item['name'];
}
}
$proxiesOther0 = $config['proxy-groups'][0]['proxies'];
$config['proxy-groups'][0]['proxies']=array();
$config['proxies'] = array_merge($config['proxies'] ?: [], $proxy);
foreach ($config['proxy-groups'] as $k => $v) {
if (!is_array($config['proxy-groups'][$k]['proxies'])) {
continue;
}
if(array_key_exists($config['proxy-groups'][$k]['name'], $proxiesOther)){
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxiesOther[$config['proxy-groups'][$k]['name']]);
unset($proxiesOther[$config['proxy-groups'][$k]['name']]);
}else if($config['proxy-groups'][$k]['type'] !== 'select' || $config['proxy-groups'][$k]['name'] == 'manual_node'){
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
}
}
foreach ($proxiesOther as $k => $v) {
$vo = ['name' => $k, 'type' => 'fallback','proxies' => $v,'url' => "http://www.gstatic.com/generate_204",'interval' => 600];
array_push($config['proxy-groups'], $vo);
array_push($proxiesOther0,$k);
}
$config['proxy-groups'][0]['proxies'] = array_merge($proxiesOther0,$config['proxy-groups'][0]['proxies']);
// Force the current subscription domain to be a direct rule
$subsDomain = $_SERVER['SERVER_NAME'];
$subsDomainRule = "DOMAIN,{$subsDomain},DIRECT";
array_unshift($config['rules'], $subsDomainRule);
// Force the current subscription domain to be a direct rule
$subsDomain = $_SERVER['SERVER_NAME'];
$subsDomainRule = "DOMAIN,{$subsDomain},DIRECT";
array_unshift($config['rules'], $subsDomainRule);
$yaml = Yaml::dump($config);
return str_replace('$app_name', config('v2board.app_name', 'V2Board'), $yaml);
}
public static function buildShadowsocks($password, $server): array
{
$array = [];
$array['name'] = $server['name'];
$array['type'] = 'ss';
$array['server'] = $server['host'];
$array['port'] = $server['port'];
$array['cipher'] = $server['cipher'];
$array['password'] = $password;
$array['udp'] = true;
return $array;
}
public static function buildVmess($uuid, $server): array
{
$array = [];
$array['name'] = $server['name'];
$array['type'] = 'vless';
$array['server'] = $server['host'];
$array['port'] = $server['port'];
$array['uuid'] = $uuid;
$array['alterId'] = $server['alter_id'];
$array['cipher'] = 'auto';
$array['udp'] = true;
switch ($server['tls']) {
case 1:
$tlsSettings = $server['tls_settings'];
$array['tls'] = true;
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure'])) {
$array['skip-cert-verify'] = (bool)$tlsSettings['allow_insecure'];
}
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name'])) {
$array['servername'] = $tlsSettings['server_name'];
}
break;
case 2:
$array['flow'] = 'xtls-rprx-vision';
$tlsSettings = $server['tls_settings'];
$array['tls'] = true;
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure'])) {
$array['skip-cert-verify'] = (bool)$tlsSettings['allow_insecure'];
}
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name'])) {
$array['servername'] = $tlsSettings['server_name'];
}
$array['reality-opts'] = [
'public-key' => $tlsSettings['public_key'],
'short-id' => $tlsSettings['short_id']
];
$array['client-fingerprint'] = Helper::getRandFingerprint();
break;
default:
break;
}
switch ($server['network']) {
case 'ws':
$array['network'] = 'ws';
if (isset($server['network_settings'])) {
$wsSettings = $server['network_settings'];
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']];
}
}
break;
case 'grpc':
$array['network'] = 'grpc';
if (isset($server['network_settings'])) {
$grpcObject = $server['network_settings'];
$array['grpc-opts'] = [];
$array['grpc-opts']['grpc-service-name'] = $grpcObject['serviceName'];
}
break;
default:
break;
}
return $array;
}
public static function buildTrojan($password, $server): array
{
$array = [];
$array['name'] = $server['name'];
$array['type'] = 'trojan';
$array['server'] = $server['host'];
$array['port'] = $server['port'];
$array['password'] = $password;
$array['udp'] = true;
if (!empty($server['server_name'])) {
$array['sni'] = $server['server_name'];
}
if (!empty($server['allow_insecure'])) {
$array['skip-cert-verify'] = (bool)$server['allow_insecure'];
}
return $array;
}
}