feat: new xboard
This commit is contained in:
+85
-75
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Contracts\ProtocolInterface;
|
||||
use App\Utils\Helper;
|
||||
use phpDocumentor\Reflection\Types\Self_;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class Clash
|
||||
class Clash implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'clash';
|
||||
public $flags = ['clash'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -18,6 +18,11 @@ class Clash
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -35,8 +40,9 @@ class Clash
|
||||
|
||||
foreach ($servers as $item) {
|
||||
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], [
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item['protocol_settings'], 'cipher'), [
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
@@ -58,28 +64,32 @@ class Clash
|
||||
|
||||
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
||||
foreach ($config['proxy-groups'] as $k => $v) {
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies'])) $config['proxy-groups'][$k]['proxies'] = [];
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies']))
|
||||
$config['proxy-groups'][$k]['proxies'] = [];
|
||||
$isFilter = false;
|
||||
foreach ($config['proxy-groups'][$k]['proxies'] as $src) {
|
||||
foreach ($proxies as $dst) {
|
||||
if (!$this->isRegex($src)) continue;
|
||||
if (!$this->isRegex($src))
|
||||
continue;
|
||||
$isFilter = true;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_values(array_diff($config['proxy-groups'][$k]['proxies'], [$src]));
|
||||
if ($this->isMatch($src, $dst)) {
|
||||
array_push($config['proxy-groups'][$k]['proxies'], $dst);
|
||||
}
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
|
||||
}
|
||||
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function($group) {
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function ($group) {
|
||||
return $group['proxies'];
|
||||
});
|
||||
$config['proxy-groups'] = array_values($config['proxy-groups']);
|
||||
|
||||
|
||||
$config = $this->buildRules($config);
|
||||
|
||||
|
||||
@@ -103,10 +113,10 @@ class Clash
|
||||
array_unshift($config['rules'], "DOMAIN,{$subsDomain},DIRECT");
|
||||
}
|
||||
// Force the nodes ip to be a direct rule
|
||||
collect($this->servers)->pluck('host')->map(function($host){
|
||||
collect($this->servers)->pluck('host')->map(function ($host) {
|
||||
$host = trim($host);
|
||||
return filter_var($host, FILTER_VALIDATE_IP) ? [$host] : Helper::getIpByDomainName($host);
|
||||
})->flatten()->unique()->each(function($nodeIP) use ( &$config ) {
|
||||
})->flatten()->unique()->each(function ($nodeIP) use (&$config) {
|
||||
array_unshift($config['rules'], "IP-CIDR,{$nodeIP}/32,DIRECT,no-resolve");
|
||||
});
|
||||
|
||||
@@ -115,12 +125,13 @@ class Clash
|
||||
|
||||
public static function buildShadowsocks($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'ss';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['cipher'] = $server['cipher'];
|
||||
$array['cipher'] = data_get($protocol_settings, 'cipher');
|
||||
$array['password'] = $uuid;
|
||||
$array['udp'] = true;
|
||||
return $array;
|
||||
@@ -128,6 +139,7 @@ class Clash
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'vmess';
|
||||
@@ -138,58 +150,45 @@ class Clash
|
||||
$array['cipher'] = 'auto';
|
||||
$array['udp'] = true;
|
||||
|
||||
if ($server['tls']) {
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
$array['tls'] = true;
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$array['servername'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $array['network'] = $tcpSettings['header']['type'];
|
||||
|
||||
if (isset($tcpSettings['header']['request']['headers'])){
|
||||
$headers = $$tcpSettings['header']['request']['headers'];
|
||||
$array['http-opts']['headers'] = $headers;
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$array['http-opts']['path'] = $paths;
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['network'] = 'ws';
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
$array['ws-opts'] = [];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['ws-opts']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||
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']];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['network'] = 'grpc';
|
||||
if ($server['networkSettings']) {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
$array['grpc-opts'] = [];
|
||||
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
|
||||
$array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'tls_settings.allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['servername'] = $serverName;
|
||||
}
|
||||
}
|
||||
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
if (data_get($protocol_settings, 'network_settings.header.type', 'none') !== 'none') {
|
||||
$array['http-opts'] = [
|
||||
'headers' => data_get($protocol_settings, 'network_settings.header.request.headers'),
|
||||
'path' => \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']))
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['ws-opts']['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['grpc-opts']['grpc-service-name'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'trojan';
|
||||
@@ -197,23 +196,31 @@ class Clash
|
||||
$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'] = ($server['allow_insecure'] ? true : false);
|
||||
// trojan-go配置
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
$array['network'] = $server['network'];
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $server['networkSettings']['serviceName'];
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$array['ws-opts']['path'] = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$array['ws-opts']['headers']['Host'] = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
}
|
||||
};
|
||||
if ($serverName = data_get($protocol_settings, 'server_name')) {
|
||||
$array['sni'] = $serverName;
|
||||
}
|
||||
$array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'allow_insecure');
|
||||
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = 'tcp';
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['ws-opts']['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['grpc-opts']['grpc-service-name'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
$array['network'] = 'tcp';
|
||||
break;
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
@@ -224,6 +231,9 @@ class Clash
|
||||
|
||||
private function isRegex($exp)
|
||||
{
|
||||
return @preg_match($exp, null) !== false;
|
||||
if (empty($exp)) {
|
||||
return false;
|
||||
}
|
||||
return @preg_match((string) $exp, '') !== false;
|
||||
}
|
||||
}
|
||||
|
||||
+180
-179
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Contracts\ProtocolInterface;
|
||||
use App\Models\ServerHysteria;
|
||||
use App\Utils\Helper;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class ClashMeta
|
||||
class ClashMeta implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'meta,verge';
|
||||
public $flags = ['meta', 'verge', 'flclash'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -18,6 +19,11 @@ class ClashMeta
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -28,15 +34,16 @@ class ClashMeta
|
||||
$customConfig = base_path() . '/resources/rules/custom.clashmeta.yaml';
|
||||
if (\File::exists($customConfig)) {
|
||||
$config = Yaml::parseFile($customConfig);
|
||||
} elseif(\File::exists($customClashConfig)) {
|
||||
} elseif (\File::exists($customClashConfig)) {
|
||||
$config = Yaml::parseFile($customClashConfig);
|
||||
} else{
|
||||
} else {
|
||||
$config = Yaml::parseFile($defaultConfig);
|
||||
}
|
||||
$proxy = [];
|
||||
$proxies = [];
|
||||
|
||||
foreach ($servers as $item) {
|
||||
$protocol_settings = $item['protocol_settings'];
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
array_push($proxy, self::buildShadowsocks($item['password'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
@@ -49,7 +56,10 @@ class ClashMeta
|
||||
array_push($proxy, self::buildTrojan($user['uuid'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
if (
|
||||
$item['type'] === 'vless'
|
||||
&& in_array(data_get($protocol_settings, 'network'), ['tcp', 'ws', 'grpc', 'http', 'h2'])
|
||||
) {
|
||||
array_push($proxy, self::buildVless($user['uuid'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
}
|
||||
@@ -61,23 +71,27 @@ class ClashMeta
|
||||
|
||||
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
||||
foreach ($config['proxy-groups'] as $k => $v) {
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies'])) $config['proxy-groups'][$k]['proxies'] = [];
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies']))
|
||||
$config['proxy-groups'][$k]['proxies'] = [];
|
||||
$isFilter = false;
|
||||
foreach ($config['proxy-groups'][$k]['proxies'] as $src) {
|
||||
foreach ($proxies as $dst) {
|
||||
if (!$this->isRegex($src)) continue;
|
||||
if (!$this->isRegex($src))
|
||||
continue;
|
||||
$isFilter = true;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_values(array_diff($config['proxy-groups'][$k]['proxies'], [$src]));
|
||||
if ($this->isMatch($src, $dst)) {
|
||||
array_push($config['proxy-groups'][$k]['proxies'], $dst);
|
||||
}
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
|
||||
}
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function($group) {
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function ($group) {
|
||||
return $group['proxies'];
|
||||
});
|
||||
$config['proxy-groups'] = array_values($config['proxy-groups']);
|
||||
@@ -102,10 +116,10 @@ class ClashMeta
|
||||
array_unshift($config['rules'], "DOMAIN,{$subsDomain},DIRECT");
|
||||
}
|
||||
// Force the nodes ip to be a direct rule
|
||||
collect($this->servers)->pluck('host')->map(function($host){
|
||||
collect($this->servers)->pluck('host')->map(function ($host) {
|
||||
$host = trim($host);
|
||||
return filter_var($host, FILTER_VALIDATE_IP) ? [$host] : Helper::getIpByDomainName($host);
|
||||
})->flatten()->unique()->each(function($nodeIP) use ( &$config ) {
|
||||
})->flatten()->unique()->each(function ($nodeIP) use (&$config) {
|
||||
array_unshift($config['rules'], "IP-CIDR,{$nodeIP}/32,DIRECT,no-resolve");
|
||||
});
|
||||
|
||||
@@ -119,144 +133,114 @@ class ClashMeta
|
||||
$array['type'] = 'ss';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['cipher'] = $server['cipher'];
|
||||
$array['password'] = $password;
|
||||
$array['cipher'] = data_get($server['protocol_settings'], 'cipher');
|
||||
$array['password'] = data_get($server, 'password', $password);
|
||||
$array['udp'] = true;
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'vmess';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['uuid'] = $uuid;
|
||||
$array['alterId'] = 0;
|
||||
$array['cipher'] = 'auto';
|
||||
$array['udp'] = true;
|
||||
$protocol_settings = data_get($server, 'protocol_settings', []);
|
||||
$array = [
|
||||
'name' => $server['name'],
|
||||
'type' => 'vmess',
|
||||
'server' => $server['host'],
|
||||
'port' => $server['port'],
|
||||
'uuid' => $uuid,
|
||||
'alterId' => 0,
|
||||
'cipher' => 'auto',
|
||||
'udp' => true
|
||||
];
|
||||
|
||||
if ($server['tls']) {
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
$array['tls'] = true;
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$array['servername'] = $tlsSettings['serverName'];
|
||||
}
|
||||
$array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'tls_settings.allow_insecure', false);
|
||||
$array['servername'] = data_get($protocol_settings, 'tls_settings.server_name');
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $array['network'] = $tcpSettings['header']['type'];
|
||||
|
||||
if (isset($tcpSettings['header']['request']['headers'])){
|
||||
$headers = $$tcpSettings['header']['request']['headers'];
|
||||
$array['http-opts']['headers'] = $headers;
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$array['http-opts']['path'] = $paths;
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['network'] = 'ws';
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
$array['ws-opts'] = [];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['ws-opts']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||
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']];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['network'] = 'grpc';
|
||||
if ($server['networkSettings']) {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
$array['grpc-opts'] = [];
|
||||
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = data_get($protocol_settings, 'network_settings.header.type', 'tcp');
|
||||
if (data_get($protocol_settings, 'network_settings.header.type', 'none') !== 'none') {
|
||||
$array['http-opts'] = [
|
||||
'headers' => data_get($protocol_settings, 'network_settings.header.request.headers'),
|
||||
'path' => \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']))
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['ws-opts']['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['grpc-opts']['grpc-service-name'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildVless($password, $server){
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'vless';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['uuid'] = $password;
|
||||
$array['alterId'] = 0;
|
||||
$array['cipher'] = 'auto';
|
||||
$array['udp'] = true;
|
||||
public static function buildVless($password, $server)
|
||||
{
|
||||
$protocol_settings = data_get($server, 'protocol_settings', []);
|
||||
$array = [
|
||||
'name' => $server['name'],
|
||||
'type' => 'vless',
|
||||
'server' => $server['host'],
|
||||
'port' => $server['port'],
|
||||
'uuid' => $password,
|
||||
'alterId' => 0,
|
||||
'cipher' => 'auto',
|
||||
'udp' => true,
|
||||
'flow' => data_get($protocol_settings, 'flow'),
|
||||
'tls' => false
|
||||
];
|
||||
|
||||
// XTLS流控算法
|
||||
if($server['flow']) ($array['flow'] = $server['flow']);
|
||||
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1: //开启TLS
|
||||
$array['tls'] = true;
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure']))
|
||||
$array['skip-cert-verify'] = ($tlsSettings['allow_insecure'] ? true : false);
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$array['servername'] = $tlsSettings['server_name'];
|
||||
}
|
||||
break;
|
||||
case 2: //开启reality
|
||||
$array['tls'] = true;
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if (!empty($tls_settings['allowInsecure'])) $array['skip-cert-verify'] = (bool)$tls_settings['allowInsecure'];
|
||||
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$array['servername'] = $tls_settings['server_name'];
|
||||
$array['reality-opts'] = [
|
||||
'public-key' => $tls_settings['public_key'],
|
||||
'short-id' => $tls_settings['short_id']
|
||||
];
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$array['client-fingerprint'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
switch (data_get($protocol_settings, 'tls')) {
|
||||
case 1:
|
||||
$array['tls'] = true;
|
||||
$array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'tls_settings.allow_insecure', false);
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['servername'] = $serverName;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
$array['tls'] = true;
|
||||
$array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'reality_settings.allow_insecure', false);
|
||||
$array['servername'] = data_get($protocol_settings, 'reality_settings.server_name');
|
||||
$array['reality-opts'] = [
|
||||
'public-key' => data_get($protocol_settings, 'reality_settings.public_key'),
|
||||
'short-id' => data_get($protocol_settings, 'reality_settings.short_id')
|
||||
];
|
||||
$array['client-fingerprint'] = Helper::getRandFingerprint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['network'] = 'ws';
|
||||
if ($server['network_settings']) {
|
||||
$wsSettings = $server['network_settings'];
|
||||
$array['ws-opts'] = [];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['ws-opts']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||
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']];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['network'] = 'grpc';
|
||||
if ($server['network_settings']) {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
$array['grpc-opts'] = [];
|
||||
if (isset($grpcSettings['serviceName'])) {
|
||||
$array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
|
||||
};
|
||||
}
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['ws-opts']['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['grpc-opts']['grpc-service-name'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return $array;
|
||||
@@ -264,66 +248,80 @@ class ClashMeta
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$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'] = ($server['allow_insecure'] ? true : false);
|
||||
// trojan-go配置
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
$array['network'] = $server['network'];
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $server['networkSettings']['serviceName'];
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$array['ws-opts']['path'] = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$array['ws-opts']['headers']['Host'] = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
}
|
||||
};
|
||||
$protocol_settings = data_get($server, 'protocol_settings', []);
|
||||
$array = [
|
||||
'name' => $server['name'],
|
||||
'type' => 'trojan',
|
||||
'server' => $server['host'],
|
||||
'port' => $server['port'],
|
||||
'password' => $password,
|
||||
'udp' => true,
|
||||
'skip-cert-verify' => (bool) data_get($protocol_settings, 'allow_insecure', false)
|
||||
];
|
||||
if ($serverName = data_get($protocol_settings, 'server_name')) {
|
||||
$array['sni'] = $serverName;
|
||||
}
|
||||
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = 'tcp';
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['ws-opts']['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['grpc-opts']['grpc-service-name'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
$array['network'] = 'tcp';
|
||||
break;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildHysteria($password, $server, $user)
|
||||
{
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
if($server['server_name']) $array['sni'] = $server['server_name'];
|
||||
$array['up'] = $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'];
|
||||
$array['down'] = $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'];
|
||||
$array['skip-cert-verify'] = $server['insecure'] ? true : false;
|
||||
switch($server['version']){
|
||||
case 1:
|
||||
$protocol_settings = data_get($server, 'protocol_settings', []);
|
||||
$array = [
|
||||
'name' => $server['name'],
|
||||
'server' => $server['host'],
|
||||
'port' => $server['port'],
|
||||
'sni' => data_get($protocol_settings, 'tls.server_name'),
|
||||
'up' => data_get($protocol_settings, 'bandwidth.up'),
|
||||
'down' => data_get($protocol_settings, 'bandwidth.down'),
|
||||
'skip-cert-verify' => (bool) data_get($protocol_settings, 'tls.allow_insecure', false),
|
||||
];
|
||||
if (isset($server['ports'])) {
|
||||
$array['ports'] = $server['ports'];
|
||||
}
|
||||
switch (data_get($protocol_settings, 'version')) {
|
||||
case 1:
|
||||
$array['type'] = 'hysteria';
|
||||
// 判断是否开启动态端口
|
||||
if(isset($server['ports'])) $array['ports'] = $server['ports'];
|
||||
$array['auth_str'] = $password;
|
||||
$array['protocol'] = 'udp';
|
||||
if($server['is_obfs']) $array['obfs'] = $server['server_key'];
|
||||
$array['protocol'] = 'udp'; // 支持 udp/wechat-video/faketcp
|
||||
if (data_get($protocol_settings, 'obfs.open')) {
|
||||
$array['obfs'] = data_get($protocol_settings, 'obfs.password');
|
||||
}
|
||||
$array['fast-open'] = true;
|
||||
$array['disable_mtu_discovery'] = true; //禁止路径最大传输单元发现
|
||||
$array['alpn'] = [ServerHysteria::$alpnMap[$server['alpn']]];
|
||||
$array['disable_mtu_discovery'] = true;
|
||||
break;
|
||||
case 2:
|
||||
case 2:
|
||||
$array['type'] = 'hysteria2';
|
||||
$array['password'] = $password;
|
||||
if($server['is_obfs']) {
|
||||
$array['obfs'] = 'salamander';
|
||||
$array['obfs-password'] = $server['server_key'];
|
||||
if (data_get($protocol_settings, 'obfs.open')) {
|
||||
$array['obfs'] = data_get($protocol_settings, 'obfs.type');
|
||||
$array['obfs-password'] = data_get($protocol_settings, 'obfs.password');
|
||||
}
|
||||
if(isset($server['ports'])) $array['ports'] = $server['ports'];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
@@ -334,6 +332,9 @@ class ClashMeta
|
||||
|
||||
private function isRegex($exp)
|
||||
{
|
||||
return @preg_match($exp, null) !== false;
|
||||
if (empty($exp)) {
|
||||
return false;
|
||||
}
|
||||
return @preg_match($exp, '') !== false;
|
||||
}
|
||||
}
|
||||
|
||||
+127
-84
@@ -3,11 +3,12 @@
|
||||
namespace App\Protocols;
|
||||
|
||||
|
||||
use App\Contracts\ProtocolInterface;
|
||||
use App\Utils\Helper;
|
||||
|
||||
class General
|
||||
class General implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'general';
|
||||
public $flags = ['general', 'v2rayn', 'v2rayng', 'passwall', 'ssrplus', 'sagernet'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -17,6 +18,11 @@ class General
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -45,62 +51,66 @@ class General
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$name = rawurlencode($server['name']);
|
||||
$password = data_get($server, 'password', $password);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
base64_encode("{$protocol_settings['cipher']}:{$password}")
|
||||
);
|
||||
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"v" => "2",
|
||||
"ps" => $server['name'],
|
||||
"add" => $server['host'],
|
||||
"port" => (string)$server['port'],
|
||||
"port" => (string) $server['port'],
|
||||
"id" => $uuid,
|
||||
"aid" => '0',
|
||||
"net" => $server['network'],
|
||||
"net" => $server['protocol_settings']['network'],
|
||||
"type" => "none",
|
||||
"host" => "",
|
||||
"path" => "",
|
||||
"tls" => $server['tls'] ? "tls" : "",
|
||||
"tls" => $protocol_settings['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = $tlsSettings['serverName'];
|
||||
}
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$config['sni'] = $serverName;
|
||||
}
|
||||
if ((string)$server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $config['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$config['path'] = $paths[array_rand($paths)];
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$config['host'] = $hosts[array_rand($hosts)];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||
|
||||
switch ($protocol_settings['network']) {
|
||||
case 'tcp':
|
||||
if (data_get($protocol_settings, 'network_settings.header.type', 'none') !== 'none') {
|
||||
$config['type'] = data_get($protocol_settings, 'network_settings.header.type', 'http');
|
||||
$config['path'] = \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']));
|
||||
$config['host'] = data_get($protocol_settings, 'network_settings.headers.Host') ? \Arr::random(data_get($protocol_settings, 'network_settings.headers.Host'), ['/']) : null;
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$config['type'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$config['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$config['host'] = $host;
|
||||
break;
|
||||
case 'grpc':
|
||||
$config['type'] = 'grpc';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$config['path'] = $path;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server){
|
||||
public static function buildVless($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$host = $server['host']; //节点地址
|
||||
$port = $server['port']; //节点端口
|
||||
$name = $server['name']; //节点名称
|
||||
@@ -109,48 +119,57 @@ class General
|
||||
'mode' => 'multi', //grpc传输模式
|
||||
'security' => '', //传输层安全 tls/reality
|
||||
'encryption' => 'none', //加密方式
|
||||
'type' => $server['network'], //传输协议
|
||||
'type' => $server['protocol_settings']['network'], //传输协议
|
||||
'flow' => $protocol_settings['flow'] ? $protocol_settings['flow'] : null,
|
||||
];
|
||||
// 判断是否开启XTLS
|
||||
if($server['flow']) ($config['flow'] = $server['flow']);
|
||||
// 如果开启TLS
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['sni'] = $tlsSettings['server_name'];
|
||||
$config['security'] = "tls";
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['servername'] = $tls_settings['server_name'];
|
||||
$config['spx'] = "/";
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
// 处理TLS
|
||||
switch ($server['protocol_settings']['tls']) {
|
||||
case 1:
|
||||
$config['security'] = "tls";
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$config['sni'] = $serverName;
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$config['pbk'] = data_get($protocol_settings, 'reality_settings.public_key');
|
||||
$config['sid'] = data_get($protocol_settings, 'reality_settings.short_id');
|
||||
$config['sni'] = data_get($protocol_settings, 'reality_settings.server_name');
|
||||
$config['servername'] = data_get($protocol_settings, 'reality_settings.server_name');
|
||||
$config['spx'] = "/";
|
||||
$config['fp'] = Helper::getRandFingerprint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// 如果传输协议为ws
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['network_settings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
// 传输协议为grpc
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = $grpcSettings['serviceName'];
|
||||
// 处理传输协议
|
||||
switch ($server['protocol_settings']['network']) {
|
||||
case 'ws':
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$config['path'] = $path;
|
||||
if ($wsHost = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$config['host'] = $wsHost;
|
||||
break;
|
||||
case 'grpc':
|
||||
if ($path = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$config['path'] = $path;
|
||||
break;
|
||||
case 'kcp':
|
||||
if ($path = data_get($protocol_settings, 'network_settings.seed'))
|
||||
$config['path'] = $path;
|
||||
$config['type'] = data_get($protocol_settings, 'network_settings.header.type', 'none');
|
||||
break;
|
||||
case 'httpupgrade':
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$config['path'] = $path;
|
||||
$config['host'] = data_get($protocol_settings, 'network_settings.host', $server['host']);
|
||||
break;
|
||||
case 'xhttp':
|
||||
$config['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
$config['host'] = data_get($protocol_settings, 'network_settings.host', $server['host']);
|
||||
$config['mode'] = data_get($protocol_settings, 'network_settings.mode', 'auto');
|
||||
$config['extra'] = json_encode(data_get($protocol_settings, 'network_settings.extra'));
|
||||
break;
|
||||
}
|
||||
|
||||
$user = $uuid . '@' . $host . ':' . $port;
|
||||
@@ -162,12 +181,32 @@ class General
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$name = rawurlencode($server['name']);
|
||||
$query = http_build_query([
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
]);
|
||||
$array = [];
|
||||
$array['allowInsecure'] = $protocol_settings['allow_insecure'];
|
||||
if ($serverName = data_get($protocol_settings, 'server_name')) {
|
||||
$array['peer'] = $serverName;
|
||||
$array['sni'] = $serverName;
|
||||
}
|
||||
switch ($server['protocol_settings']['network']) {
|
||||
case 'ws':
|
||||
$array['type'] = 'ws';
|
||||
if ($path = data_get($protocol_settings, 'network_settings.path'))
|
||||
$array['path'] = $path;
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host'))
|
||||
$array['host'] = $host;
|
||||
break;
|
||||
case 'grpc':
|
||||
// Follow V2rayN family standards
|
||||
$array['type'] = 'grpc';
|
||||
if ($serviceName = data_get($protocol_settings, 'network_settings.serviceName'))
|
||||
$array['serviceName'] = $serviceName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$query = http_build_query($array);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
@@ -175,23 +214,27 @@ class General
|
||||
|
||||
public static function buildHysteria($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$params = [];
|
||||
// Return empty if version is not 2
|
||||
if ($server['version'] !== 2) {
|
||||
if ($server['protocol_settings']['version'] !== 2) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($server['server_name']) {
|
||||
$params['sni'] = $server['server_name'];
|
||||
if ($serverName = data_get($protocol_settings, 'tls.server_name')) {
|
||||
$params['sni'] = $serverName;
|
||||
$params['security'] = 'tls';
|
||||
}
|
||||
|
||||
if ($server['is_obfs']) {
|
||||
if (data_get($protocol_settings, 'obfs.open')) {
|
||||
$params['obfs'] = 'salamander';
|
||||
$params['obfs-password'] = $server['server_key'];
|
||||
$params['obfs-password'] = data_get($protocol_settings, 'obfs.password');
|
||||
}
|
||||
if (isset($server['ports'])) {
|
||||
$params['mport'] = $server['ports'];
|
||||
}
|
||||
|
||||
$params['insecure'] = $server['insecure'] ? 1 : 0;
|
||||
$params['insecure'] = data_get($protocol_settings, 'tls.allow_insecure');
|
||||
|
||||
$query = http_build_query($params);
|
||||
$name = rawurlencode($server['name']);
|
||||
|
||||
+116
-49
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
class Loon
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Loon implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'loon';
|
||||
public $flags = ['loon'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -14,6 +16,11 @@ class Loon
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -22,8 +29,9 @@ class Loon
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], [
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item['protocol_settings'], 'cipher'), [
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
@@ -43,17 +51,18 @@ class Loon
|
||||
}
|
||||
}
|
||||
return response($uri, 200)
|
||||
->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']}");
|
||||
}
|
||||
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$cipher = data_get($server['protocol_settings'], 'cipher');
|
||||
$config = [
|
||||
"{$server['name']}=Shadowsocks",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"{$server['cipher']}",
|
||||
"{$cipher}",
|
||||
"{$password}",
|
||||
'fast-open=false',
|
||||
'udp=true'
|
||||
@@ -66,6 +75,7 @@ class Loon
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=vmess",
|
||||
"{$server['host']}",
|
||||
@@ -77,43 +87,44 @@ class Loon
|
||||
"alterId=0"
|
||||
];
|
||||
|
||||
if ($server['network'] === 'tcp') {
|
||||
array_push($config, 'transport=tcp');
|
||||
if ($server['networkSettings']) {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type']) && !empty($tcpSettings['header']['type']))
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
if (data_get($protocol_settings, 'network') === 'tcp')
|
||||
$config[] = 'over-tls=true';
|
||||
if (data_get($protocol_settings, 'tls_settings')) {
|
||||
$tls_settings = data_get($protocol_settings, 'tls_settings');
|
||||
$config[] = 'skip-cert-verify=' . ($tls_settings['allow_insecure'] ? 'true' : 'false');
|
||||
if (data_get($tls_settings, 'server_name'))
|
||||
$config[] = "tls-name={$tls_settings['server_name']}";
|
||||
}
|
||||
}
|
||||
|
||||
switch (data_get($server['protocol_settings'], 'network')) {
|
||||
case 'tcp':
|
||||
$config[] = 'transport=tcp';
|
||||
$tcpSettings = data_get($protocol_settings, 'network_settings');
|
||||
if (data_get($tcpSettings, 'header.type'))
|
||||
$config = str_replace('transport=tcp', "transport={$tcpSettings['header']['type']}", $config);
|
||||
if (isset($tcpSettings['header']['request']['path'][0]) && !empty($tcpSettings['header']['request']['path'][0]))
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$path = array_rand(array_rand($paths));
|
||||
array_push($config, "path={$path}");
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$host = $hosts[array_rand($hosts)];
|
||||
array_push($config, "host={$host}");
|
||||
if (data_get($tcpSettings, key: 'header.request.path')) {
|
||||
$paths = data_get($tcpSettings, key: 'header.request.path');
|
||||
$path = $paths[array_rand($paths)];
|
||||
$config[] = "path={$path}";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($server['tls']) {
|
||||
if ($server['network'] === 'tcp')
|
||||
array_push($config, 'over-tls=true');
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
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, "tls-name={$tlsSettings['serverName']}");
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
array_push($config, 'transport=ws');
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
array_push($config, "path={$wsSettings['path']}");
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
array_push($config, "host={$wsSettings['headers']['Host']}");
|
||||
}
|
||||
if (data_get($tcpSettings, key: 'header.request.headers.Host')) {
|
||||
$hosts = data_get($tcpSettings, key: 'header.request.headers.Host');
|
||||
$host = $hosts[array_rand($hosts)];
|
||||
$config[] = "host={$host}";
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$config[] = 'transport=ws';
|
||||
$wsSettings = data_get($protocol_settings, 'network_settings');
|
||||
if (data_get($wsSettings, key: 'path'))
|
||||
$config[] = "path={$wsSettings['path']}";
|
||||
if (data_get($wsSettings, key: 'headers.Host'))
|
||||
$config[] = "host={$wsSettings['headers']['Host']}";
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
$uri = implode(',', $config);
|
||||
@@ -123,17 +134,18 @@ class Loon
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=trojan",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"{$password}",
|
||||
$server['server_name'] ? "tls-name={$server['server_name']}" : "",
|
||||
data_get($protocol_settings, 'server_name') ? "tls-name={$protocol_settings['server_name']}" : "",
|
||||
'fast-open=false',
|
||||
'udp=true'
|
||||
];
|
||||
if (!empty($server['allow_insecure'])) {
|
||||
array_push($config, $server['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||
if (!empty($protocol_settings['allow_insecure'])) {
|
||||
$config[] = data_get($protocol_settings, 'allow_insecure') ? 'skip-cert-verify=true' : 'skip-cert-verify=false';
|
||||
}
|
||||
$config = array_filter($config);
|
||||
$uri = implode(',', $config);
|
||||
@@ -141,20 +153,75 @@ class Loon
|
||||
return $uri;
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=vless",
|
||||
$server['host'],
|
||||
$server['port'],
|
||||
$uuid,
|
||||
'fast-open=false',
|
||||
'udp=true',
|
||||
'alterId=0'
|
||||
];
|
||||
switch ((int) data_get($protocol_settings, 'tls')) {
|
||||
case 1:
|
||||
$config[] = 'over-tls=true';
|
||||
$tlsSettings = data_get($protocol_settings, 'tls_settings', []);
|
||||
if ($tlsSettings) {
|
||||
$config[] = 'skip-cert-verify=' . (data_get($tlsSettings, 'allow_insecure') ? 'true' : 'false');
|
||||
if ($serverName = data_get($tlsSettings, 'server_name')) {
|
||||
$config[] = "tls-name={$serverName}";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
return '';
|
||||
}
|
||||
$network_settings = data_get($protocol_settings, 'network_settings', []);
|
||||
switch ((string) data_get($network_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$config[] = 'transport=tcp';
|
||||
if ($headerType = data_get($network_settings, 'header.type')) {
|
||||
$config = collect($config)->map(function ($item) use ($headerType) {
|
||||
return $item === 'transport=tcp' ? "transport={$headerType}" : $item;
|
||||
})->toArray();
|
||||
}
|
||||
if ($paths = data_get($network_settings, 'header.request.path')) {
|
||||
$config[] = 'path=' . $paths[array_rand($paths)];
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$config[] = 'transport=ws';
|
||||
if ($path = data_get($network_settings, 'path')) {
|
||||
$config[] = "path={$path}";
|
||||
}
|
||||
|
||||
if ($host = data_get($network_settings, 'headers.Host')) {
|
||||
$config[] = "host={$host}";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return implode(',', $config) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildHysteria($password, $server, $user)
|
||||
{
|
||||
if ($server['version'] !== 2){
|
||||
return ;
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
if ($protocol_settings['version'] != 2) {
|
||||
return;
|
||||
}
|
||||
$config = [
|
||||
"{$server['name']}=Hysteria2",
|
||||
$server['host'],
|
||||
$server['port'],
|
||||
$password,
|
||||
$server['server_name'] ? "sni={$server['server_name']}" : "(null)"
|
||||
$protocol_settings['tls']['server_name'] ? "sni={$protocol_settings['tls']['server_name']}" : "(null)"
|
||||
];
|
||||
if ($server['insecure']) $config[] = "skip-cert-verify=true";
|
||||
$config[] = "download-bandwidth=" . ($user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps']);
|
||||
if (data_get($protocol_settings, 'tls.allow_insecure'))
|
||||
$config[] = "skip-cert-verify=true";
|
||||
$config[] = "download-bandwidth=" . data_get($protocol_settings, 'bandwidth.download_bandwidth');
|
||||
$config[] = "udp=true";
|
||||
$config = array_filter($config);
|
||||
$uri = implode(',', $config);
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
|
||||
class Passwall
|
||||
{
|
||||
public $flag = 'passwall';
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
public function __construct($user, $servers)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
$user = $this->user;
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'vmess') {
|
||||
$uri .= self::buildVmess($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
$uri .= self::buildVless($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$uri .= self::buildShadowsocks($item['password'], $item);
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
$uri .= self::buildTrojan($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
$uri .= General::buildHysteria($user['uuid'], $item);
|
||||
}
|
||||
}
|
||||
return base64_encode($uri);
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
);
|
||||
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"v" => "2",
|
||||
"ps" => $server['name'],
|
||||
"add" => $server['host'],
|
||||
"port" => (string)$server['port'],
|
||||
"id" => $uuid,
|
||||
"aid" => '0',
|
||||
"net" => $server['network'],
|
||||
"type" => "none",
|
||||
"host" => "",
|
||||
"path" => "",
|
||||
"tls" => $server['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $config['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$config['path'] = $paths[array_rand($paths)];
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$config['host'] = $hosts[array_rand($hosts)];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server){
|
||||
$host = $server['host']; //节点地址
|
||||
$port = $server['port']; //节点端口
|
||||
$name = $server['name']; //节点名称
|
||||
|
||||
$config = [
|
||||
'mode' => 'multi', //grpc传输模式
|
||||
'security' => '', //传输层安全 tls/reality
|
||||
'encryption' => 'none', //加密方式
|
||||
'type' => $server['network'], //传输协议
|
||||
];
|
||||
// 判断是否开启XTLS
|
||||
if($server['flow']) ($config['flow'] = $server['flow']);
|
||||
// 如果开启TLS
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['sni'] = $tlsSettings['server_name'];
|
||||
$config['security'] = "tls";
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['servername'] = $tls_settings['server_name'];
|
||||
$config['spx'] = "/";
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果传输协议为ws
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['network_settings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
// 传输协议为grpc
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
|
||||
$user = $uuid . '@' . $host . ':' . $port;
|
||||
$query = http_build_query($config);
|
||||
$fragment = urlencode($name);
|
||||
$link = sprintf("vless://%s?%s#%s\r\n", $user, $query, $fragment);
|
||||
return $link;
|
||||
}
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$query = http_build_query([
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
]);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class QuantumultX
|
||||
class QuantumultX implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'quantumult%20x';
|
||||
public $flags = ['quantumult%20x'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -15,6 +16,11 @@ class QuantumultX
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -32,14 +38,16 @@ class QuantumultX
|
||||
}
|
||||
}
|
||||
return response(base64_encode($uri), 200)
|
||||
->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']}");
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$password = data_get($server, 'password', $password);
|
||||
$config = [
|
||||
"shadowsocks={$server['host']}:{$server['port']}",
|
||||
"method={$server['cipher']}",
|
||||
"method={$protocol_settings['cipher']}",
|
||||
"password={$password}",
|
||||
'fast-open=true',
|
||||
'udp-relay=true',
|
||||
@@ -53,6 +61,7 @@ class QuantumultX
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"vmess={$server['host']}:{$server['port']}",
|
||||
'method=chacha20-poly1305',
|
||||
@@ -62,28 +71,26 @@ class QuantumultX
|
||||
"tag={$server['name']}"
|
||||
];
|
||||
|
||||
if ($server['tls']) {
|
||||
if ($server['network'] === 'tcp')
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
if (data_get($protocol_settings, 'network') === 'tcp')
|
||||
array_push($config, 'obfs=over-tls');
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
array_push($config, 'tls-verification=' . ($tlsSettings['allowInsecure'] ? 'false' : 'true'));
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$host = $tlsSettings['serverName'];
|
||||
if (data_get($protocol_settings, 'tls_settings')) {
|
||||
if (data_get($protocol_settings, 'tls_settings.allow_insecure'))
|
||||
array_push($config, 'tls-verification=' . ($protocol_settings['tls_settings']['allow_insecure'] ? 'false' : 'true'));
|
||||
if (data_get($protocol_settings, 'tls_settings.server_name'))
|
||||
$host = data_get($protocol_settings, 'tls_settings.server_name');
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
if ($server['tls'])
|
||||
if (data_get($protocol_settings, 'network') === 'ws') {
|
||||
if (data_get($protocol_settings, 'tls'))
|
||||
array_push($config, 'obfs=wss');
|
||||
else
|
||||
array_push($config, 'obfs=ws');
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
array_push($config, "obfs-uri={$wsSettings['path']}");
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']) && !isset($host))
|
||||
$host = $wsSettings['headers']['Host'];
|
||||
if (data_get($protocol_settings, 'network_settings')) {
|
||||
if (data_get($protocol_settings, 'network_settings.path'))
|
||||
array_push($config, "obfs-uri={$protocol_settings['network_settings']['path']}");
|
||||
if (data_get($protocol_settings, 'network_settings.headers.Host') && !isset($host))
|
||||
$host = data_get($protocol_settings, 'network_settings.headers.Host');
|
||||
}
|
||||
}
|
||||
if (isset($host)) {
|
||||
@@ -97,13 +104,14 @@ class QuantumultX
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"trojan={$server['host']}:{$server['port']}",
|
||||
"password={$password}",
|
||||
'over-tls=true',
|
||||
$server['server_name'] ? "tls-host={$server['server_name']}" : "",
|
||||
$protocol_settings['server_name'] ? "tls-host={$protocol_settings['server_name']}" : "",
|
||||
// Tips: allowInsecure=false = tls-verification=true
|
||||
$server['allow_insecure'] ? 'tls-verification=false' : 'tls-verification=true',
|
||||
$protocol_settings['allow_insecure'] ? 'tls-verification=false' : 'tls-verification=true',
|
||||
'fast-open=true',
|
||||
'udp-relay=true',
|
||||
"tag={$server['name']}"
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
|
||||
class SSRPlus
|
||||
{
|
||||
public $flag = 'ssrplus';
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
public function __construct($user, $servers)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
$user = $this->user;
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'vmess') {
|
||||
$uri .= self::buildVmess($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
$uri .= self::buildVless($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$uri .= self::buildShadowsocks($item['password'], $item);
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
$uri .= self::buildTrojan($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
$uri .= General::buildHysteria($user['uuid'], $item);
|
||||
}
|
||||
}
|
||||
return base64_encode($uri);
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
);
|
||||
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"v" => "2",
|
||||
"ps" => $server['name'],
|
||||
"add" => $server['host'],
|
||||
"port" => (string)$server['port'],
|
||||
"id" => $uuid,
|
||||
"aid" => '0',
|
||||
"net" => $server['network'],
|
||||
"type" => "none",
|
||||
"host" => "",
|
||||
"path" => "",
|
||||
"tls" => $server['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server){
|
||||
$host = $server['host']; //节点地址
|
||||
$port = $server['port']; //节点端口
|
||||
$name = $server['name']; //节点名称
|
||||
|
||||
$config = [
|
||||
'mode' => 'multi', //grpc传输模式
|
||||
'security' => '', //传输层安全 tls/reality
|
||||
'encryption' => 'none', //加密方式
|
||||
'type' => $server['network'], //传输协议
|
||||
];
|
||||
// 判断是否开启XTLS
|
||||
if($server['flow']) ($config['flow'] = $server['flow']);
|
||||
// 如果开启TLS
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['sni'] = $tlsSettings['server_name'];
|
||||
$config['security'] = "tls";
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['servername'] = $tls_settings['server_name'];
|
||||
$config['spx'] = "/";
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果传输协议为ws
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
// 传输协议为grpc
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
|
||||
$user = $uuid . '@' . $host . ':' . $port;
|
||||
$query = http_build_query($config);
|
||||
$fragment = urlencode($name);
|
||||
$link = sprintf("vless://%s?%s#%s\r\n", $user, $query, $fragment);
|
||||
return $link;
|
||||
}
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$query = http_build_query([
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
]);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
class SagerNet
|
||||
{
|
||||
public $flag = 'sagernet';
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
public function __construct($user, $servers)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
$user = $this->user;
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'vmess') {
|
||||
$uri .= self::buildVmess($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$uri .= self::buildShadowsocks($item['password'], $item);
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
$uri .= self::buildTrojan($user['uuid'], $item);
|
||||
}
|
||||
}
|
||||
return base64_encode($uri);
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($uuid, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$uuid}")
|
||||
);
|
||||
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildShadowsocksSIP008($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"id" => $server['id'],
|
||||
"remarks" => $server['name'],
|
||||
"server" => $server['host'],
|
||||
"server_port" => $server['port'],
|
||||
"password" => $uuid,
|
||||
"method" => $server['cipher']
|
||||
];
|
||||
return $config;
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"encryption" => "none",
|
||||
"type" => urlencode($server['network']),
|
||||
"security" => $server['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = urlencode($tlsSettings['serverName']);
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $config['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])) $config['path'] = $tcpSettings['header']['request']['path'][0];
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = urlencode($wsSettings['headers']['Host']);
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = urlencode($grpcSettings['serviceName']);
|
||||
}
|
||||
return "vmess://" . $uuid . "@" . $server['host'] . ":" . $server['port'] . "?" . http_build_query($config) . "#" . urlencode($server['name']) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildTrojan($uuid, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$query = http_build_query([
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
]);
|
||||
$uri = "trojan://{$uuid}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
}
|
||||
}
|
||||
+127
-148
@@ -4,10 +4,11 @@ namespace App\Protocols;
|
||||
|
||||
use App\Models\ServerHysteria;
|
||||
use App\Utils\Helper;
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Shadowrocket
|
||||
class Shadowrocket implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'shadowrocket';
|
||||
public $flags = ['shadowrocket'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -17,6 +18,11 @@ class Shadowrocket
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -24,9 +30,9 @@ class Shadowrocket
|
||||
|
||||
$uri = '';
|
||||
//display remaining traffic and expire date
|
||||
$upload = round($user['u'] / (1024*1024*1024), 2);
|
||||
$download = round($user['d'] / (1024*1024*1024), 2);
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
|
||||
$upload = round($user['u'] / (1024 * 1024 * 1024), 2);
|
||||
$download = round($user['d'] / (1024 * 1024 * 1024), 2);
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024 * 1024 * 1024), 2);
|
||||
$expiredDate = date('Y-m-d', $user['expired_at']);
|
||||
$uri .= "STATUS=🚀↑:{$upload}GB,↓:{$download}GB,TOT:{$totalTraffic}GB💡Expires:{$expiredDate}\r\n";
|
||||
foreach ($servers as $item) {
|
||||
@@ -52,68 +58,62 @@ class Shadowrocket
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$name = rawurlencode($server['name']);
|
||||
$password = data_get($server, 'password', $password);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
base64_encode("{$protocol_settings['cipher']}:{$password}")
|
||||
);
|
||||
$uri = "ss://{$str}@{$server['host']}:{$server['port']}";
|
||||
if ($server['obfs'] == 'http') {
|
||||
$uri .= "?plugin=obfs-local;obfs=http;obfs-host={$server['obfs-host']};obfs-uri={$server['obfs-path']}";
|
||||
if ($protocol_settings['obfs'] == 'http') {
|
||||
$obfs_host = data_get($protocol_settings, 'obfs_settings.obfs-host');
|
||||
$obfs_path = data_get($protocol_settings, 'obfs_settings.obfs-path');
|
||||
$uri .= "?plugin=obfs-local;obfs=http;obfs-host={$obfs_host};obfs-uri={$obfs_path}";
|
||||
}
|
||||
return $uri."#{$name}\r\n";
|
||||
return $uri . "#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$userinfo = base64_encode('auto:' . $uuid . '@' . $server['host'] . ':' . $server['port']);
|
||||
$config = [
|
||||
'tfo' => 1,
|
||||
'remark' => $server['name'],
|
||||
'alterId' => 0
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($protocol_settings['tls']) {
|
||||
$config['tls'] = 1;
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
$config['allowInsecure'] = (int)$tlsSettings['allowInsecure'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['peer'] = $tlsSettings['serverName'];
|
||||
if (data_get($protocol_settings, 'tls_settings')) {
|
||||
if (data_get($protocol_settings, 'tls_settings.allow_insecure') && !empty(data_get($protocol_settings, 'tls_settings.allow_insecure')))
|
||||
$config['allowInsecure'] = (int) data_get($protocol_settings, 'tls_settings.allow_insecure');
|
||||
if (data_get($protocol_settings, 'tls_settings.server_name') && !empty(data_get($protocol_settings, 'tls_settings.server_name')))
|
||||
$config['peer'] = data_get($protocol_settings, 'tls_settings.server_name');
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
if ($server['networkSettings']) {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type']) && !empty($tcpSettings['header']['type']))
|
||||
$config['obfs'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0]) && !empty($tcpSettings['header']['request']['path'][0]))
|
||||
$config['path'] = $tcpSettings['header']['request']['path'][0];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$config['obfs'] = "websocket";
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
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'];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$config['obfs'] = "grpc";
|
||||
if ($server['networkSettings']) {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName']) && !empty($grpcSettings['serviceName']))
|
||||
$config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
if (isset($tlsSettings)) {
|
||||
$config['host'] = $tlsSettings['serverName'];
|
||||
} else {
|
||||
$config['host'] = $server['host'];
|
||||
}
|
||||
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
if (data_get($protocol_settings, 'network_settings.header.type', 'none') !== 'none') {
|
||||
$config['obfs'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
$config['path'] = \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']));
|
||||
$config['obfsParam'] = \Arr::random(data_get($protocol_settings, 'network_settings.header.request.headers.Host', ['www.example.com']));
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$config['obfs'] = "websocket";
|
||||
$config['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host')) {
|
||||
$config['obfsParam'] = $host;
|
||||
}
|
||||
break;
|
||||
case 'grpc':
|
||||
$config['obfs'] = "grpc";
|
||||
$config['path'] = data_get($protocol_settings, 'network_settings.serviceName');
|
||||
$config['host'] = data_get($protocol_settings, 'tls_settings.server_name') ?? $server['host'];
|
||||
break;
|
||||
}
|
||||
$query = http_build_query($config, '', '&', PHP_QUERY_RFC3986);
|
||||
$uri = "vmess://{$userinfo}?{$query}";
|
||||
@@ -123,6 +123,7 @@ class Shadowrocket
|
||||
|
||||
public static function buildVless($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$userinfo = base64_encode('auto:' . $uuid . '@' . $server['host'] . ':' . $server['port']);
|
||||
$config = [
|
||||
'tfo' => 1,
|
||||
@@ -131,82 +132,59 @@ class Shadowrocket
|
||||
];
|
||||
|
||||
// 判断是否开启xtls
|
||||
if(isset($server['flow']) && !blank($server['flow'])){
|
||||
if (data_get($protocol_settings, 'flow')) {
|
||||
$xtlsMap = [
|
||||
'none' => 0,
|
||||
'xtls-rprx-direct' => 1,
|
||||
'xtls-rprx-vision' => 2
|
||||
];
|
||||
// 判断 flow 的值是否在 xtlsMap 中存在
|
||||
if (array_key_exists($server['flow'], $xtlsMap)) {
|
||||
if (array_key_exists(data_get($protocol_settings, 'flow'), $xtlsMap)) {
|
||||
$config['tls'] = 1;
|
||||
$config['xtls'] = $xtlsMap[$server['flow']];
|
||||
$config['xtls'] = $xtlsMap[data_get($protocol_settings, 'flow')];
|
||||
}
|
||||
}
|
||||
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
$config['tls'] = 1;
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
$config['allowInsecure'] = (int)$tlsSettings['allowInsecure'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['peer'] = $tlsSettings['server_name'];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
$config['tls'] = 1;
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
if ($server['network_settings']) {
|
||||
$tcpSettings = $server['network_settings'];
|
||||
if (isset($tcpSettings['header']['type']) && !empty($tcpSettings['header']['type']))
|
||||
$config['obfs'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0]) && !empty($tcpSettings['header']['request']['path'][0]))
|
||||
$config['path'] = $tcpSettings['header']['request']['path'][0];
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$config['obfsParam'] = $hosts[array_rand($hosts)];
|
||||
switch (data_get($protocol_settings, 'tls')) {
|
||||
case 1:
|
||||
$config['tls'] = 1;
|
||||
$config['allowInsecure'] = (int) data_get($protocol_settings, 'tls_settings.allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$config['peer'] = $serverName;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
$config['tls'] = 1;
|
||||
$config['sni'] = data_get($protocol_settings, 'reality_settings.server_name');
|
||||
$config['pbk'] = data_get($protocol_settings, 'reality_settings.public_key');
|
||||
$config['sid'] = data_get($protocol_settings, 'reality_settings.short_id');
|
||||
$config['fp'] = Helper::getRandFingerprint();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$config['obfs'] = "websocket";
|
||||
if ($server['network_settings']) {
|
||||
$wsSettings = $server['network_settings'];
|
||||
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'];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$config['obfs'] = "grpc";
|
||||
if ($server['network_settings']) {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName']) && !empty($grpcSettings['serviceName']))
|
||||
$config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
if (isset($tlsSettings)) {
|
||||
$config['host'] = $tlsSettings['server_name'];
|
||||
} else {
|
||||
$config['host'] = $server['host'];
|
||||
}
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
if (data_get($protocol_settings, 'network_settings.header.type', 'none') !== 'none') {
|
||||
$config['obfs'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
$config['path'] = \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']));
|
||||
$config['obfsParam'] = \Arr::random(data_get($protocol_settings, 'network_settings.header.request.headers.Host', ['www.example.com']));
|
||||
}
|
||||
break;
|
||||
case 'ws':
|
||||
$config['obfs'] = "websocket";
|
||||
if (data_get($protocol_settings, 'network_settings.path')) {
|
||||
$config['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
}
|
||||
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host')) {
|
||||
$config['obfsParam'] = $host;
|
||||
}
|
||||
break;
|
||||
case 'grpc':
|
||||
$config['obfs'] = "grpc";
|
||||
$config['path'] = data_get($protocol_settings, 'network_settings.serviceName');
|
||||
$config['host'] = data_get($protocol_settings, 'tls_settings.server_name') ?? $server['host'];
|
||||
break;
|
||||
}
|
||||
|
||||
$query = http_build_query($config, '', '&', PHP_QUERY_RFC3986);
|
||||
@@ -217,31 +195,23 @@ class Shadowrocket
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$name = rawurlencode($server['name']);
|
||||
$params = [
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name']
|
||||
];
|
||||
// trojan-go配置
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) {
|
||||
$params['allowInsecure'] = data_get($protocol_settings, 'allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'server_name')) {
|
||||
$params['peer'] = $serverName;
|
||||
}
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'grpc':
|
||||
$params['obfs'] = 'grpc';
|
||||
$params['path'] = $server['networkSettings']['serviceName'];
|
||||
}
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
$path = '';
|
||||
$host = '';
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$path = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$host = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
$params['path'] = data_get($protocol_settings, 'network_settings.serviceName');
|
||||
break;
|
||||
case 'ws':
|
||||
$host = data_get($protocol_settings, 'network_settings.headers.Host');
|
||||
$path = data_get($protocol_settings, 'network_settings.path');
|
||||
$params['plugin'] = "obfs-local;obfs=websocket;obfs-host={$host};obfs-uri={$path}";
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
$query = http_build_query($params);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}&tfo=1#{$name}";
|
||||
$uri .= "\r\n";
|
||||
@@ -250,36 +220,45 @@ class Shadowrocket
|
||||
|
||||
public static function buildHysteria($password, $server)
|
||||
{
|
||||
switch($server['version']){
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
switch (data_get($protocol_settings, 'version')) {
|
||||
case 1:
|
||||
$params = [
|
||||
"auth" => $password,
|
||||
"upmbps" => $server['up_mbps'],
|
||||
"downmbps" => $server['down_mbps'],
|
||||
"upmbps" => data_get($protocol_settings, 'bandwidth.up'),
|
||||
"downmbps" => data_get($protocol_settings, 'bandwidth.down'),
|
||||
"protocol" => 'udp',
|
||||
"peer" => $server['server_name'],
|
||||
"fastopen" => 1,
|
||||
"alpn" => ServerHysteria::$alpnMap[$server['alpn']]
|
||||
];
|
||||
if($server['is_obfs']){
|
||||
$params["obfs"] = "xplus";
|
||||
$params["obfsParam"] =$server['server_key'];
|
||||
if ($serverName = data_get($protocol_settings, 'tls.server_name')) {
|
||||
$params['peer'] = $serverName;
|
||||
}
|
||||
if($server['insecure']) $params['insecure'] = $server['insecure'];
|
||||
if(isset($server['ports'])) $params['mport'] = $server['ports'];
|
||||
if (data_get($protocol_settings, 'obfs.open')) {
|
||||
$params["obfs"] = "xplus";
|
||||
$params["obfsParam"] = data_get($protocol_settings, 'obfs_settings.password');
|
||||
}
|
||||
$params['insecure'] = data_get($protocol_settings, 'tls.allow_insecure');
|
||||
if (isset($server['ports']))
|
||||
$params['mport'] = $server['ports'];
|
||||
$query = http_build_query($params);
|
||||
$uri = "hysteria://{$server['host']}:{$server['port']}?{$query}#{$server['name']}";
|
||||
$uri .= "\r\n";
|
||||
break;
|
||||
case 2:
|
||||
$params = [
|
||||
"peer" => $server['server_name'],
|
||||
"obfs" => 'none',
|
||||
"fastopen" => 1
|
||||
];
|
||||
if($server['is_obfs']) $params['obfs-password'] = $server['server_key'];
|
||||
if($server['insecure']) $params['insecure'] = $server['insecure'];
|
||||
if(isset($server['ports'])) $params['mport'] = $server['ports'];
|
||||
if ($serverName = data_get($protocol_settings, 'tls.server_name')) {
|
||||
$params['peer'] = $serverName;
|
||||
}
|
||||
if (data_get($protocol_settings, 'obfs.open')) {
|
||||
$params['obfs'] = data_get($protocol_settings, 'obfs.type');
|
||||
$params['obfs-password'] = data_get($protocol_settings, 'obfs.password');
|
||||
}
|
||||
$params['insecure'] = data_get($protocol_settings, 'tls.allow_insecure');
|
||||
if (isset($server['ports']))
|
||||
$params['mport'] = $server['ports'];
|
||||
$query = http_build_query($params);
|
||||
$uri = "hysteria2://{$password}@{$server['host']}:{$server['port']}?{$query}#{$server['name']}";
|
||||
$uri .= "\r\n";
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
class Shadowsocks
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Shadowsocks implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'shadowsocks';
|
||||
public $flags = ['shadowsocks'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -14,6 +16,11 @@ class Shadowsocks
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -29,8 +36,9 @@ class Shadowsocks
|
||||
$bytesRemaining = $user['transfer_enable'] - $bytesUsed;
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], ['aes-128-gcm', 'aes-256-gcm', 'aes-192-gcm', 'chacha20-ietf-poly1305'])
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item, 'protocol_settings.cipher'), ['aes-128-gcm', 'aes-256-gcm', 'aes-192-gcm', 'chacha20-ietf-poly1305'])
|
||||
) {
|
||||
array_push($configs, self::SIP008($item, $user));
|
||||
}
|
||||
@@ -41,7 +49,7 @@ class Shadowsocks
|
||||
$subs['bytes_remaining'] = $bytesRemaining;
|
||||
$subs['servers'] = array_merge($subs['servers'] ? $subs['servers'] : [], $configs);
|
||||
|
||||
return json_encode($subs, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
|
||||
return json_encode($subs, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
public static function SIP008($server, $user)
|
||||
@@ -52,7 +60,7 @@ class Shadowsocks
|
||||
"server" => $server['host'],
|
||||
"server_port" => $server['port'],
|
||||
"password" => $user['uuid'],
|
||||
"method" => $server['cipher']
|
||||
"method" => data_get($server, 'protocol_settings.cipher')
|
||||
];
|
||||
return $config;
|
||||
}
|
||||
|
||||
+179
-182
@@ -2,10 +2,11 @@
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Utils\Helper;
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class SingBox
|
||||
class SingBox implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'sing-box,hiddify';
|
||||
public $flags = ['sing-box', 'hiddify'];
|
||||
private $servers;
|
||||
private $user;
|
||||
private $config;
|
||||
@@ -16,6 +17,11 @@ class SingBox
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$appName = admin_setting('app_name', 'XBoard');
|
||||
@@ -26,7 +32,7 @@ class SingBox
|
||||
|
||||
return response()
|
||||
->json($this->config)
|
||||
->header('profile-title', 'base64:'. base64_encode($appName))
|
||||
->header('profile-title', 'base64:' . base64_encode($appName))
|
||||
->header('subscription-userinfo', "upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}")
|
||||
->header('profile-update-interval', '24');
|
||||
}
|
||||
@@ -45,6 +51,7 @@ class SingBox
|
||||
$outbounds = $this->config['outbounds'];
|
||||
$proxies = [];
|
||||
foreach ($this->servers as $item) {
|
||||
$protocol_settings = $item['protocol_settings'];
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$ssConfig = $this->buildShadowsocks($item['password'], $item);
|
||||
$proxies[] = $ssConfig;
|
||||
@@ -57,12 +64,14 @@ class SingBox
|
||||
$vmessConfig = $this->buildVmess($this->user['uuid'], $item);
|
||||
$proxies[] = $vmessConfig;
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
if ($item['type'] === 'vless'
|
||||
&& in_array(data_get($protocol_settings, 'network'), ['tcp', 'ws', 'grpc', 'http', 'quic', 'httpupgrade'])
|
||||
) {
|
||||
$vlessConfig = $this->buildVless($this->user['uuid'], $item);
|
||||
$proxies[] = $vlessConfig;
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
$hysteriaConfig = $this->buildHysteria($this->user['uuid'], $item, $this->user);
|
||||
$hysteriaConfig = $this->buildHysteria($this->user['uuid'], $item);
|
||||
$proxies[] = $hysteriaConfig;
|
||||
}
|
||||
}
|
||||
@@ -80,11 +89,12 @@ class SingBox
|
||||
/**
|
||||
* Build rule
|
||||
*/
|
||||
protected function buildRule(){
|
||||
protected function buildRule()
|
||||
{
|
||||
$rules = $this->config['route']['rules'];
|
||||
// Force the nodes ip to be a direct rule
|
||||
array_unshift($rules, [
|
||||
'ip_cidr' => collect($this->servers)->pluck('host')->map(function($host){
|
||||
'ip_cidr' => collect($this->servers)->pluck('host')->map(function ($host) {
|
||||
return filter_var($host, FILTER_VALIDATE_IP) ? [$host] : Helper::getIpByDomainName($host);
|
||||
})->flatten()->unique()->values(),
|
||||
'outbound' => 'direct',
|
||||
@@ -99,8 +109,8 @@ class SingBox
|
||||
$array['type'] = 'shadowsocks';
|
||||
$array['server'] = $server['host'];
|
||||
$array['server_port'] = $server['port'];
|
||||
$array['method'] = $server['cipher'];
|
||||
$array['password'] = $password;
|
||||
$array['method'] = data_get($server, 'protocol_settings.cipher');
|
||||
$array['password'] = data_get($server, 'password', $password);
|
||||
|
||||
return $array;
|
||||
}
|
||||
@@ -108,136 +118,124 @@ class SingBox
|
||||
|
||||
protected function buildVmess($uuid, $server)
|
||||
{
|
||||
$array = [];
|
||||
$array['tag'] = $server['name'];
|
||||
$array['type'] = 'vmess';
|
||||
$array['server'] = $server['host'];
|
||||
$array['server_port'] = $server['port'];
|
||||
$array['uuid'] = $uuid;
|
||||
$array['security'] = 'auto';
|
||||
$array['alter_id'] = 0;
|
||||
$array['transport'] = [];
|
||||
|
||||
if ($server['tls']) {
|
||||
$tlsConfig = [];
|
||||
$tlsConfig['enabled'] = true;
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'] ?? [];
|
||||
$tlsConfig['insecure'] = $tlsSettings['allowInsecure'] ? true : false;
|
||||
$tlsConfig['server_name'] = $tlsSettings['serverName'] ?? null;
|
||||
}
|
||||
$array['tls'] = $tlsConfig;
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http')
|
||||
$array['transport']['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])) {
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$array['transport']['path'] = $paths[array_rand($paths)];
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])) {
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$array['transport']['host'] = $hosts;
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['transport']['type'] = 'ws';
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['transport']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['transport']['headers'] = ['Host' => array($wsSettings['headers']['Host'])];
|
||||
$array['transport']['max_early_data'] = 2048;
|
||||
$array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol';
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['transport']['type'] = 'grpc';
|
||||
if ($server['networkSettings']) {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName']))
|
||||
$array['transport']['service_name'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [
|
||||
'tag' => $server['name'],
|
||||
'type' => 'vmess',
|
||||
'server' => $server['host'],
|
||||
'server_port' => $server['port'],
|
||||
'uuid' => $uuid,
|
||||
'security' => 'auto',
|
||||
'alter_id' => 0,
|
||||
'transport' => [],
|
||||
'tls' => $protocol_settings['tls'] ? [
|
||||
'enabled' => true,
|
||||
'insecure' => (bool) data_get($protocol_settings, 'tls_settings.allow_insecure'),
|
||||
] : null
|
||||
];
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['tls']['server_name'] = $serverName;
|
||||
}
|
||||
|
||||
$transport = match ($protocol_settings['network']) {
|
||||
'tcp' => [
|
||||
'type' => 'http',
|
||||
'path' => \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']))
|
||||
],
|
||||
'ws' => [
|
||||
'type' => 'ws',
|
||||
'path' => data_get($protocol_settings, 'network_settings.path'),
|
||||
'headers' => ($host = data_get($protocol_settings, 'network_settings.headers.Host')) ? ['Host' => $host] : null,
|
||||
'max_early_data' => 2048,
|
||||
'early_data_header_name' => 'Sec-WebSocket-Protocol'
|
||||
],
|
||||
'grpc' => [
|
||||
'type' => 'grpc',
|
||||
'service_name' => data_get($protocol_settings, 'network_settings.serviceName')
|
||||
],
|
||||
default => null
|
||||
};
|
||||
|
||||
if ($transport) {
|
||||
$array['transport'] = array_filter($transport, fn($value) => !is_null($value));
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
protected function buildVless($password, $server)
|
||||
{
|
||||
$protocol_settings = data_get($server, 'protocol_settings', []);
|
||||
$array = [
|
||||
"type" => "vless",
|
||||
"tag" => $server['name'],
|
||||
"server" => $server['host'],
|
||||
"server_port" => $server['port'],
|
||||
"uuid" => $password,
|
||||
"packet_encoding" => "xudp"
|
||||
"packet_encoding" => "xudp",
|
||||
'flow' => data_get($protocol_settings, 'flow', ''),
|
||||
];
|
||||
|
||||
$tlsSettings = $server['tls_settings'] ?? [];
|
||||
if ($protocol_settings['tls']) {
|
||||
$tlsConfig = [
|
||||
'enabled' => true,
|
||||
'insecure' => (bool) data_get($protocol_settings, 'tls_settings.allow_insecure'),
|
||||
'utls' => [
|
||||
'enabled' => true,
|
||||
'fingerprint' => Helper::getRandFingerprint()
|
||||
]
|
||||
];
|
||||
|
||||
if ($server['tls']) {
|
||||
$tlsConfig = [];
|
||||
$tlsConfig['enabled'] = true;
|
||||
$array['flow'] = !empty($server['flow']) ? $server['flow'] : "";
|
||||
$tlsSettings = $server['tls_settings'] ?? [];
|
||||
if ($server['tls_settings']) {
|
||||
$tlsConfig['insecure'] = isset($tlsSettings['allow_insecure']) && $tlsSettings['allow_insecure'] == 1 ? true : false;
|
||||
$tlsConfig['server_name'] = $tlsSettings['server_name'] ?? null;
|
||||
if ($server['tls'] == 2) {
|
||||
switch ($protocol_settings['tls']) {
|
||||
case 1:
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$tlsConfig['server_name'] = $serverName;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
$tlsConfig['server_name'] = data_get($protocol_settings, 'reality_settings.server_name');
|
||||
$tlsConfig['reality'] = [
|
||||
'enabled' => true,
|
||||
'public_key' => $tlsSettings['public_key'],
|
||||
'short_id' => $tlsSettings['short_id']
|
||||
'public_key' => data_get($protocol_settings, 'reality_settings.public_key'),
|
||||
'short_id' => data_get($protocol_settings, 'reality_settings.short_id')
|
||||
];
|
||||
}
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq'];
|
||||
$tlsConfig['utls'] = [
|
||||
"enabled" => true,
|
||||
"fingerprint" => $fingerprints[array_rand($fingerprints)]
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
$array['tls'] = $tlsConfig;
|
||||
}
|
||||
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['network_settings'];
|
||||
if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http')
|
||||
$array['transport']['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path']))
|
||||
$array['transport']['path'] = $tcpSettings['header']['request']['path'];
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['transport']['type'] = 'ws';
|
||||
if ($server['network_settings']) {
|
||||
$wsSettings = $server['network_settings'];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['transport']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['transport']['headers'] = ['Host' => array($wsSettings['headers']['Host'])];
|
||||
$array['transport']['max_early_data'] = 2048;
|
||||
$array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol';
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['transport']['type'] = 'grpc';
|
||||
if ($server['network_settings']) {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName']))
|
||||
$array['transport']['service_name'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'h2') {
|
||||
$array['transport']['type'] = 'http';
|
||||
if ($server['network_settings']) {
|
||||
$h2Settings = $server['network_settings'];
|
||||
if (isset($h2Settings['host']))
|
||||
$array['transport']['host'] = array($h2Settings['host']);
|
||||
if (isset($h2Settings['path']))
|
||||
$array['transport']['path'] = $h2Settings['path'];
|
||||
}
|
||||
$transport = match ($protocol_settings['network']) {
|
||||
'tcp' => data_get($protocol_settings, 'network_settings.header.type') == 'http' ? [
|
||||
'type' => 'http',
|
||||
'path' => \Arr::random(data_get($protocol_settings, 'network_settings.header.request.path', ['/']))
|
||||
] : null,
|
||||
'ws' => array_filter([
|
||||
'type' => 'ws',
|
||||
'path' => data_get($protocol_settings, 'network_settings.path'),
|
||||
'headers' => ($host = data_get($protocol_settings, 'network_settings.headers.Host')) ? ['Host' => $host] : null,
|
||||
'max_early_data' => 2048,
|
||||
'early_data_header_name' => 'Sec-WebSocket-Protocol'
|
||||
], fn($value) => !is_null($value)),
|
||||
'grpc' => [
|
||||
'type' => 'grpc',
|
||||
'service_name' => data_get($protocol_settings, 'network_settings.serviceName')
|
||||
],
|
||||
'h2' => [
|
||||
'type' => 'http',
|
||||
'host' => data_get($protocol_settings, 'network_settings.host'),
|
||||
'path' => data_get($protocol_settings, 'network_settings.path')
|
||||
],
|
||||
'httpupgrade' => [
|
||||
'type' => 'httpupgrade',
|
||||
'path' => data_get($protocol_settings, 'network_settings.path'),
|
||||
'host' => data_get($protocol_settings, 'network_settings.host', $server['host']),
|
||||
'headers' => data_get($protocol_settings, 'network_settings.headers')
|
||||
],
|
||||
default => null
|
||||
};
|
||||
|
||||
if ($transport) {
|
||||
$array['transport'] = array_filter($transport, fn($value) => !is_null($value));
|
||||
}
|
||||
|
||||
return $array;
|
||||
@@ -245,80 +243,79 @@ class SingBox
|
||||
|
||||
protected function buildTrojan($password, $server)
|
||||
{
|
||||
$array = [];
|
||||
$array['tag'] = $server['name'];
|
||||
$array['type'] = 'trojan';
|
||||
$array['server'] = $server['host'];
|
||||
$array['server_port'] = $server['port'];
|
||||
$array['password'] = $password;
|
||||
|
||||
$array['tls'] = [
|
||||
'enabled' => true,
|
||||
'insecure' => $server['allow_insecure'] ? true : false,
|
||||
'server_name' => $server['server_name']
|
||||
];
|
||||
|
||||
if (isset($server['network']) && in_array($server['network'], ["grpc", "ws"])) {
|
||||
$array['transport']['type'] = $server['network'];
|
||||
// grpc配置
|
||||
if ($server['network'] === "grpc" && isset($server['network_settings']['serviceName'])) {
|
||||
$array['transport']['service_name'] = $server['network_settings']['serviceName'];
|
||||
}
|
||||
// ws配置
|
||||
if ($server['network'] === "ws") {
|
||||
if (isset($server['network_settings']['path'])) {
|
||||
$array['transport']['path'] = $server['network_settings']['path'];
|
||||
}
|
||||
if (isset($server['network_settings']['headers']['Host'])) {
|
||||
$array['transport']['headers'] = ['Host' => array($server['network_settings']['headers']['Host'])];
|
||||
}
|
||||
$array['transport']['max_early_data'] = 2048;
|
||||
$array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol';
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
protected function buildHysteria($password, $server, $user)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [
|
||||
'tag' => $server['name'],
|
||||
'type' => 'trojan',
|
||||
'server' => $server['host'],
|
||||
'server_port' => $server['port'],
|
||||
'password' => $password,
|
||||
'tls' => [
|
||||
'enabled' => true,
|
||||
'insecure' => $server['insecure'] ? true : false,
|
||||
'server_name' => $server['server_name']
|
||||
'insecure' => (bool) data_get($protocol_settings, 'allow_insecure', false),
|
||||
]
|
||||
];
|
||||
|
||||
if (is_null($server['version']) || $server['version'] == 1) {
|
||||
$array['auth_str'] = $password;
|
||||
$array['tag'] = $server['name'];
|
||||
$array['type'] = 'hysteria';
|
||||
$array['up_mbps'] = $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'];
|
||||
$array['down_mbps'] = $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'];
|
||||
if ($server['is_obfs']) {
|
||||
$array['obfs'] = $server['server_key'];
|
||||
}
|
||||
|
||||
$array['disable_mtu_discovery'] = true;
|
||||
|
||||
} elseif ($server['version'] == 2) {
|
||||
$array['password'] = $password;
|
||||
$array['tag'] = $server['name'];
|
||||
$array['type'] = 'hysteria2';
|
||||
$array['password'] = $password;
|
||||
$array['up_mbps'] = $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'];
|
||||
$array['down_mbps'] = $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'];
|
||||
|
||||
if ($server['is_obfs']) {
|
||||
$array['obfs']['type'] = 'salamander';
|
||||
$array['obfs']['password'] = $server['server_key'];
|
||||
}
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['tls']['server_name'] = $serverName;
|
||||
}
|
||||
|
||||
$transport = match (data_get($protocol_settings, 'network')) {
|
||||
'grpc' => [
|
||||
'type' => 'grpc',
|
||||
'service_name' => data_get($protocol_settings, 'network_settings.serviceName')
|
||||
],
|
||||
'ws' => [
|
||||
'type' => 'ws',
|
||||
'path' => data_get($protocol_settings, 'network_settings.path'),
|
||||
'headers' => data_get($protocol_settings, 'network_settings.headers.Host') ? ['Host' => [data_get($protocol_settings, 'network_settings.headers.Host')]] : null,
|
||||
'max_early_data' => 2048,
|
||||
'early_data_header_name' => 'Sec-WebSocket-Protocol'
|
||||
],
|
||||
default => null
|
||||
};
|
||||
$array['transport'] = $transport;
|
||||
return $array;
|
||||
}
|
||||
|
||||
protected function buildHysteria($password, $server): array
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$baseConfig = [
|
||||
'server' => $server['host'],
|
||||
'server_port' => $server['port'],
|
||||
'tag' => $server['name'],
|
||||
'tls' => [
|
||||
'enabled' => true,
|
||||
'insecure' => (bool) $protocol_settings['tls']['allow_insecure'],
|
||||
]
|
||||
];
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$baseConfig['tls']['server_name'] = $serverName;
|
||||
}
|
||||
$speedConfig = [
|
||||
'up_mbps' => $protocol_settings['bandwidth']['up'],
|
||||
'down_mbps' => $protocol_settings['bandwidth']['down'],
|
||||
];
|
||||
$versionConfig = match (data_get($protocol_settings, 'version', 1)) {
|
||||
2 => [
|
||||
'type' => 'hysteria2',
|
||||
'password' => $password,
|
||||
'obfs' => $protocol_settings['obfs']['open'] ? [
|
||||
'type' => $protocol_settings['obfs']['type'],
|
||||
'password' => $protocol_settings['obfs']['password']
|
||||
] : null,
|
||||
],
|
||||
default => [
|
||||
'type' => 'hysteria',
|
||||
'auth_str' => $password,
|
||||
'obfs' => $protocol_settings['obfs']['password'],
|
||||
'disable_mtu_discovery' => true,
|
||||
]
|
||||
};
|
||||
|
||||
return array_merge(
|
||||
$baseConfig,
|
||||
$speedConfig,
|
||||
$versionConfig
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+117
-137
@@ -4,10 +4,11 @@ namespace App\Protocols;
|
||||
|
||||
use App\Models\ServerHysteria;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Stash
|
||||
class Stash implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'stash';
|
||||
public $flags = ['stash'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -17,6 +18,11 @@ class Stash
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -37,8 +43,9 @@ class Stash
|
||||
$proxies = [];
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], [
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item, 'protocol_settings.cipher'), [
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
@@ -52,10 +59,15 @@ class Stash
|
||||
array_push($proxy, self::buildVmess($user['uuid'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
}
|
||||
// if ($item['type'] === 'vless') {
|
||||
// array_push($proxy, self::buildVless($user['uuid'], $item));
|
||||
// array_push($proxies, $item['name']);
|
||||
// }
|
||||
if (
|
||||
$item['type'] === 'vless'
|
||||
&& in_array(data_get($item['protocol_settings'], 'network'), ['tcp', 'ws', 'grpc', 'http', 'h2'])
|
||||
&& in_array(data_get($item['protocol_settings'], 'tls'), [1, 0])
|
||||
&& in_array(data_get($item['protocol_settings'], 'flow'), ['xtls-rprx-origin', 'xtls-rprx-direct', 'xtls-rprx-splice'])
|
||||
) {
|
||||
array_push($proxy, self::buildVless($user['uuid'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
array_push($proxy, self::buildHysteria($user['uuid'], $item));
|
||||
array_push($proxies, $item['name']);
|
||||
@@ -68,23 +80,27 @@ class Stash
|
||||
|
||||
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
|
||||
foreach ($config['proxy-groups'] as $k => $v) {
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies'])) $config['proxy-groups'][$k]['proxies'] = [];
|
||||
if (!is_array($config['proxy-groups'][$k]['proxies']))
|
||||
$config['proxy-groups'][$k]['proxies'] = [];
|
||||
$isFilter = false;
|
||||
foreach ($config['proxy-groups'][$k]['proxies'] as $src) {
|
||||
foreach ($proxies as $dst) {
|
||||
if (!$this->isRegex($src)) continue;
|
||||
if (!$this->isRegex($src))
|
||||
continue;
|
||||
$isFilter = true;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_values(array_diff($config['proxy-groups'][$k]['proxies'], [$src]));
|
||||
if ($this->isMatch($src, $dst)) {
|
||||
array_push($config['proxy-groups'][$k]['proxies'], $dst);
|
||||
}
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
}
|
||||
if ($isFilter) continue;
|
||||
if ($isFilter)
|
||||
continue;
|
||||
$config['proxy-groups'][$k]['proxies'] = array_merge($config['proxy-groups'][$k]['proxies'], $proxies);
|
||||
}
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function($group) {
|
||||
$config['proxy-groups'] = array_filter($config['proxy-groups'], function ($group) {
|
||||
return $group['proxies'];
|
||||
});
|
||||
$config['proxy-groups'] = array_values($config['proxy-groups']);
|
||||
@@ -104,12 +120,13 @@ class Stash
|
||||
|
||||
public static function buildShadowsocks($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'ss';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['cipher'] = $server['cipher'];
|
||||
$array['cipher'] = data_get($protocol_settings, 'cipher');
|
||||
$array['password'] = $uuid;
|
||||
$array['udp'] = true;
|
||||
return $array;
|
||||
@@ -117,6 +134,7 @@ class Stash
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'vmess';
|
||||
@@ -127,122 +145,81 @@ class Stash
|
||||
$array['cipher'] = 'auto';
|
||||
$array['udp'] = true;
|
||||
|
||||
if ($server['tls']) {
|
||||
$array['tls'] = true;
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
|
||||
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$array['servername'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $array['network'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])) $array['http-opts']['path'] = $tcpSettings['header']['request']['path'][0];
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['network'] = 'ws';
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
$array['ws-opts'] = [];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['ws-opts']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||
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']];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['network'] = 'grpc';
|
||||
if ($server['networkSettings']) {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
$array['grpc-opts'] = [];
|
||||
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
$array['tls'] = data_get($protocol_settings, 'tls');
|
||||
$array['skip-cert-verify'] = data_get($protocol_settings, 'tls_settings.allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['servername'] = $serverName;
|
||||
}
|
||||
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
$array['http-opts']['path'] = data_get($protocol_settings, 'network_settings.header.request.path', ['/'])[0];
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
$array['ws-opts']['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host')) {
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
}
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
$array['grpc-opts'] = [];
|
||||
$array['grpc-opts']['grpc-service-name'] = data_get($protocol_settings, 'network_settings.serviceName');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'vless';
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['uuid'] = $uuid;
|
||||
$array['flow'] = !empty($server['flow']) ? $server['flow']: "";
|
||||
$array['flow'] = data_get($protocol_settings, 'flow');
|
||||
$array['udp'] = true;
|
||||
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$array['client-fingerprint'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
$array['client-fingerprint'] = $fingerprints[rand(0, count($fingerprints) - 1)];
|
||||
|
||||
if ($server['tls']) {
|
||||
$array['tls'] = true;
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$array['servername'] = $tlsSettings['server_name'];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!isset($server['network_settings'])) break;
|
||||
$networkSettings = $server['network_settings'];
|
||||
if (isset($networkSettings['reality-opts'])){
|
||||
$realitySettings = $networkSettings['reality-opts'];
|
||||
$array['reality-opts'] = [];
|
||||
$array['reality-opts']['public-key'] = $realitySettings['public-key'];
|
||||
$array['reality-opts']['short-id'] = $realitySettings['short-id'];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http') {
|
||||
$array['network'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'])){
|
||||
$array['http-opts']['headers']['Host'] = $tcpSettings['header']['request']['headers']['Host'];
|
||||
switch (data_get($protocol_settings, 'tls')) {
|
||||
case 1:
|
||||
$array['tls'] = true;
|
||||
$array['skip-cert-verify'] = data_get($protocol_settings, 'tls_settings.allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'tls_settings.server_name')) {
|
||||
$array['servername'] = $serverName;
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$array['http-opts']['path'] = $paths[array_rand($paths)];
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($server['network'] === 'ws') {
|
||||
$array['network'] = 'ws';
|
||||
if ($server['network_settings']) {
|
||||
$wsSettings = $server['network_settings'];
|
||||
$array['ws-opts'] = [];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
$array['ws-opts']['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
|
||||
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']];
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'grpc') {
|
||||
$array['network'] = 'grpc';
|
||||
if ($server['network_settings']) {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
$array['grpc-opts'] = [];
|
||||
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
$array['http-opts']['path'] = data_get($protocol_settings, 'network_settings.header.request.path', ['/'])[0];
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
$array['ws-opts']['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
if ($host = data_get($protocol_settings, 'network_settings.headers.Host')) {
|
||||
$array['ws-opts']['headers'] = ['Host' => $host];
|
||||
}
|
||||
break;
|
||||
case 'grpc':
|
||||
$array['network'] = 'grpc';
|
||||
$array['grpc-opts']['grpc-service-name'] = data_get($protocol_settings, 'network_settings.serviceName');
|
||||
break;
|
||||
// case 'h2':
|
||||
// $array['network'] = 'h2';
|
||||
// $array['h2-opts']['host'] = data_get($protocol_settings, 'network_settings.host');
|
||||
// $array['h2-opts']['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
// break;
|
||||
}
|
||||
|
||||
return $array;
|
||||
@@ -250,6 +227,7 @@ class Stash
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array = [];
|
||||
$array['name'] = $server['name'];
|
||||
$array['type'] = 'trojan';
|
||||
@@ -257,49 +235,48 @@ class Stash
|
||||
$array['port'] = $server['port'];
|
||||
$array['password'] = $password;
|
||||
$array['udp'] = true;
|
||||
// trojan-go配置
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
$array['network'] = $server['network'];
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $server['networkSettings']['serviceName'];
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$array['ws-opts']['path'] = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$array['ws-opts']['headers']['Host'] = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!empty($server['server_name'])) $array['sni'] = $server['server_name'];
|
||||
if (!empty($server['allow_insecure'])) $array['skip-cert-verify'] = ($server['allow_insecure'] ? true : false);
|
||||
switch (data_get($protocol_settings, 'network')) {
|
||||
case 'tcp':
|
||||
$array['network'] = data_get($protocol_settings, 'network_settings.header.type');
|
||||
$array['http-opts']['path'] = data_get($protocol_settings, 'network_settings.header.request.path', ['/'])[0];
|
||||
break;
|
||||
case 'ws':
|
||||
$array['network'] = 'ws';
|
||||
$array['ws-opts']['path'] = data_get($protocol_settings, 'network_settings.path');
|
||||
$array['ws-opts']['headers'] = data_get($protocol_settings, 'network_settings.headers.Host') ? ['Host' => data_get($protocol_settings, 'network_settings.headers.Host')] : null;
|
||||
break;
|
||||
}
|
||||
if ($serverName = data_get($protocol_settings, 'server_name')) {
|
||||
$array['sni'] = $serverName;
|
||||
}
|
||||
$array['skip-cert-verify'] = data_get($protocol_settings, 'allow_insecure');
|
||||
return $array;
|
||||
}
|
||||
|
||||
public static function buildHysteria($password, $server)
|
||||
{
|
||||
$array = [];
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$array['name'] = $server['name'];
|
||||
$array['server'] = $server['host'];
|
||||
$array['port'] = $server['port'];
|
||||
$array['up-speed'] = $server['up_mbps'];
|
||||
$array['down-speed'] = $server['down_mbps'];
|
||||
$array['skip-cert-verify'] = $server['insecure'];
|
||||
$array['sni'] = $server['server_name']??'';
|
||||
switch($server['version']){
|
||||
$array['up-speed'] = data_get($protocol_settings, 'bandwidth.up');
|
||||
$array['down-speed'] = data_get($protocol_settings, 'bandwidth.down');
|
||||
$array['skip-cert-verify'] = data_get($protocol_settings, 'tls.allow_insecure');
|
||||
if ($serverName = data_get($protocol_settings, 'tls.server_name')) {
|
||||
$array['sni'] = $serverName;
|
||||
}
|
||||
switch (data_get($protocol_settings, 'version')) {
|
||||
case 1:
|
||||
$array['type'] = 'hysteria';
|
||||
$array['auth-str'] = $password;
|
||||
$array['protocol'] = 'udp';
|
||||
$array['obfs'] = $server['server_key'];
|
||||
$array['alpn'] = [ServerHysteria::$alpnMap[$server['alpn']]];
|
||||
$array['obfs'] = data_get($protocol_settings, 'obfs.open') ? data_get($protocol_settings, 'obfs.type') : null;
|
||||
break;
|
||||
case 2:
|
||||
$array['type'] = 'hysteria2';
|
||||
$array['auth'] = $password;
|
||||
$array['fast-open'] = true;
|
||||
if(isset($server['ports'])) $array['ports'] = $server['ports'];
|
||||
$array['ports'] = data_get($protocol_settings, 'ports');
|
||||
break;
|
||||
}
|
||||
return $array;
|
||||
@@ -308,7 +285,10 @@ class Stash
|
||||
|
||||
private function isRegex($exp)
|
||||
{
|
||||
return @preg_match($exp, null) !== false;
|
||||
if (empty($exp)) {
|
||||
return false;
|
||||
}
|
||||
return @preg_match($exp, '') !== false;
|
||||
}
|
||||
|
||||
private function isMatch($exp, $str)
|
||||
|
||||
+28
-18
@@ -3,10 +3,11 @@
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Utils\Helper;
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Surfboard
|
||||
class Surfboard implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'surfboard';
|
||||
public $flags = ['surfboard'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -16,6 +17,11 @@ class Surfboard
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -27,8 +33,9 @@ class Surfboard
|
||||
$proxyGroup = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], [
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item, 'protocol_settings.cipher'), [
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
@@ -71,27 +78,28 @@ class Surfboard
|
||||
$config = str_replace('$proxies', $proxies, $config);
|
||||
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
||||
|
||||
$upload = round($user['u'] / (1024*1024*1024), 2);
|
||||
$download = round($user['d'] / (1024*1024*1024), 2);
|
||||
$upload = round($user['u'] / (1024 * 1024 * 1024), 2);
|
||||
$download = round($user['d'] / (1024 * 1024 * 1024), 2);
|
||||
$useTraffic = $upload + $download;
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024 * 1024 * 1024), 2);
|
||||
$unusedTraffic = $totalTraffic - $useTraffic;
|
||||
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
|
||||
$subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量:{$download}GB\\n剩余流量: { $unusedTraffic }GB\\n套餐流量:{$totalTraffic}GB\\n到期时间:{$expireDate}";
|
||||
$config = str_replace('$subscribe_info', $subscribeInfo, $config);
|
||||
|
||||
return response($config, 200)
|
||||
->header('content-disposition', "attachment;filename*=UTF-8''".rawurlencode($appName).".conf");
|
||||
->header('content-disposition', "attachment;filename*=UTF-8''" . rawurlencode($appName) . ".conf");
|
||||
}
|
||||
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=ss",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"encrypt-method={$server['cipher']}",
|
||||
"encrypt-method={$protocol_settings['cipher']}",
|
||||
"password={$password}",
|
||||
'tfo=true',
|
||||
'udp-relay=true'
|
||||
@@ -104,6 +112,7 @@ class Surfboard
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=vmess",
|
||||
"{$server['host']}",
|
||||
@@ -114,20 +123,20 @@ class Surfboard
|
||||
'udp-relay=true'
|
||||
];
|
||||
|
||||
if ($server['tls']) {
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
array_push($config, 'tls=true');
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (data_get($protocol_settings, 'tls_settings')) {
|
||||
$tlsSettings = data_get($protocol_settings, 'tls_settings');
|
||||
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 (data_get($protocol_settings, 'network_settings.network') === 'ws') {
|
||||
array_push($config, 'ws=true');
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (data_get($protocol_settings, 'network_settings')) {
|
||||
$wsSettings = data_get($protocol_settings, 'network_settings');
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
array_push($config, "ws-path={$wsSettings['path']}");
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
@@ -142,17 +151,18 @@ class Surfboard
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=trojan",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"password={$password}",
|
||||
$server['server_name'] ? "sni={$server['server_name']}" : "",
|
||||
$protocol_settings['server_name'] ? "sni={$protocol_settings['server_name']}" : "",
|
||||
'tfo=true',
|
||||
'udp-relay=true'
|
||||
];
|
||||
if (!empty($server['allow_insecure'])) {
|
||||
array_push($config, $server['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||
if (!empty($protocol_settings['allow_insecure'])) {
|
||||
array_push($config, $protocol_settings['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||
}
|
||||
$config = array_filter($config);
|
||||
$uri = implode(',', $config);
|
||||
|
||||
+42
-38
@@ -3,10 +3,11 @@
|
||||
namespace App\Protocols;
|
||||
|
||||
use App\Utils\Helper;
|
||||
use App\Contracts\ProtocolInterface;
|
||||
|
||||
class Surge
|
||||
class Surge implements ProtocolInterface
|
||||
{
|
||||
public $flag = 'surge';
|
||||
public $flags = ['surge'];
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
@@ -16,6 +17,11 @@ class Surge
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function getFlags(): array
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
@@ -27,35 +33,28 @@ class Surge
|
||||
$proxyGroup = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'shadowsocks'
|
||||
&& in_array($item['cipher'], [
|
||||
if (
|
||||
$item['type'] === 'shadowsocks'
|
||||
&& in_array(data_get($item, 'protocol_settings.cipher'), [
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
'chacha20-ietf-poly1305'
|
||||
])
|
||||
) {
|
||||
// [Proxy]
|
||||
$proxies .= self::buildShadowsocks($item['password'], $item);
|
||||
// [Proxy Group]
|
||||
$proxyGroup .= $item['name'] . ', ';
|
||||
}
|
||||
if ($item['type'] === 'vmess') {
|
||||
// [Proxy]
|
||||
$proxies .= self::buildVmess($user['uuid'], $item);
|
||||
// [Proxy Group]
|
||||
$proxyGroup .= $item['name'] . ', ';
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
// [Proxy]
|
||||
$proxies .= self::buildTrojan($user['uuid'], $item);
|
||||
// [Proxy Group]
|
||||
$proxyGroup .= $item['name'] . ', ';
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
// [Proxy]
|
||||
$proxies .= self::buildHysteria($user['uuid'], $item);
|
||||
// [Proxy Group]
|
||||
$proxyGroup .= $item['name'] . ', ';
|
||||
}
|
||||
}
|
||||
@@ -77,27 +76,28 @@ class Surge
|
||||
$config = str_replace('$proxies', $proxies, $config);
|
||||
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
|
||||
|
||||
$upload = round($user['u'] / (1024*1024*1024), 2);
|
||||
$download = round($user['d'] / (1024*1024*1024), 2);
|
||||
$upload = round($user['u'] / (1024 * 1024 * 1024), 2);
|
||||
$download = round($user['d'] / (1024 * 1024 * 1024), 2);
|
||||
$useTraffic = $upload + $download;
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
|
||||
$totalTraffic = round($user['transfer_enable'] / (1024 * 1024 * 1024), 2);
|
||||
$unusedTraffic = $totalTraffic - $useTraffic;
|
||||
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
|
||||
$subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量:{$download}GB\\n剩余流量:{ $unusedTraffic }GB\\n套餐流量:{$totalTraffic}GB\\n到期时间:{$expireDate}";
|
||||
$config = str_replace('$subscribe_info', $subscribeInfo, $config);
|
||||
|
||||
return response($config, 200)
|
||||
->header('content-disposition', "attachment;filename*=UTF-8''".rawurlencode($appName).".conf");
|
||||
->header('content-disposition', "attachment;filename*=UTF-8''" . rawurlencode($appName) . ".conf");
|
||||
}
|
||||
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=ss",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"encrypt-method={$server['cipher']}",
|
||||
"encrypt-method={$protocol_settings['cipher']}",
|
||||
"password={$password}",
|
||||
'tfo=true',
|
||||
'udp-relay=true'
|
||||
@@ -110,6 +110,7 @@ class Surge
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=vmess",
|
||||
"{$server['host']}",
|
||||
@@ -120,23 +121,23 @@ class Surge
|
||||
'udp-relay=true'
|
||||
];
|
||||
|
||||
if ($server['tls']) {
|
||||
if (data_get($protocol_settings, 'tls')) {
|
||||
array_push($config, 'tls=true');
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
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 (data_get($protocol_settings, 'tls_settings')) {
|
||||
$tlsSettings = data_get($protocol_settings, 'tls_settings');
|
||||
if (data_get($tlsSettings, 'allow_insecure'))
|
||||
array_push($config, 'skip-cert-verify=' . ($tlsSettings['allow_insecure'] ? 'true' : 'false'));
|
||||
if (data_get($tlsSettings, 'server_name'))
|
||||
array_push($config, "sni={$tlsSettings['server_name']}");
|
||||
}
|
||||
}
|
||||
if ($server['network'] === 'ws') {
|
||||
if (data_get($protocol_settings, 'network_settings.network') === 'ws') {
|
||||
array_push($config, 'ws=true');
|
||||
if ($server['networkSettings']) {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
|
||||
if (data_get($protocol_settings, 'network_settings')) {
|
||||
$wsSettings = data_get($protocol_settings, 'network_settings');
|
||||
if (data_get($wsSettings, 'path'))
|
||||
array_push($config, "ws-path={$wsSettings['path']}");
|
||||
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
|
||||
if (data_get($wsSettings, 'headers.Host'))
|
||||
array_push($config, "ws-headers=Host:{$wsSettings['headers']['Host']}");
|
||||
}
|
||||
}
|
||||
@@ -148,17 +149,18 @@ class Surge
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
$config = [
|
||||
"{$server['name']}=trojan",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"password={$password}",
|
||||
$server['server_name'] ? "sni={$server['server_name']}" : "",
|
||||
$protocol_settings['server_name'] ? "sni={$protocol_settings['server_name']}" : "",
|
||||
'tfo=true',
|
||||
'udp-relay=true'
|
||||
];
|
||||
if (!empty($server['allow_insecure'])) {
|
||||
array_push($config, $server['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||
if (!empty($protocol_settings['allow_insecure'])) {
|
||||
array_push($config, $protocol_settings['allow_insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false');
|
||||
}
|
||||
$config = array_filter($config);
|
||||
$uri = implode(',', $config);
|
||||
@@ -169,20 +171,22 @@ class Surge
|
||||
//参考文档: https://manual.nssurge.com/policy/proxy.html
|
||||
public static function buildHysteria($password, $server)
|
||||
{
|
||||
if($server['version'] != 2) return '';
|
||||
$protocol_settings = $server['protocol_settings'];
|
||||
if ($protocol_settings['version'] != 2)
|
||||
return '';
|
||||
$config = [
|
||||
"{$server['name']}=hysteria2",
|
||||
"{$server['host']}",
|
||||
"{$server['port']}",
|
||||
"password={$password}",
|
||||
"download-bandwidth={$server['up_mbps']}",
|
||||
$server['server_name'] ? "sni={$server['server_name']}" : "",
|
||||
"download-bandwidth={$protocol_settings['bandwidth']['up']}",
|
||||
$protocol_settings['tls']['server_name'] ? "sni={$protocol_settings['tls']['server_name']}" : "",
|
||||
// 'tfo=true',
|
||||
'udp-relay=true'
|
||||
];
|
||||
if ($server['insecure']) {
|
||||
$config[] = $server['insecure'] ? 'skip-cert-verify=true' : 'skip-cert-verify=false';
|
||||
}
|
||||
if (data_get($protocol_settings, 'tls.allow_insecure')) {
|
||||
$config[] = data_get($protocol_settings, 'tls.allow_insecure') ? 'skip-cert-verify=true' : 'skip-cert-verify=false';
|
||||
}
|
||||
$config = array_filter($config);
|
||||
$uri = implode(',', $config);
|
||||
$uri .= "\r\n";
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
|
||||
use App\Utils\Helper;
|
||||
|
||||
class V2rayN
|
||||
{
|
||||
public $flag = 'v2rayn';
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
public function __construct($user, $servers)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
$user = $this->user;
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'vmess') {
|
||||
$uri .= self::buildVmess($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
$uri .= self::buildVless($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$uri .= self::buildShadowsocks($item['password'], $item);
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
$uri .= self::buildTrojan($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
$uri .= General::buildHysteria($user['uuid'], $item);
|
||||
}
|
||||
|
||||
}
|
||||
return base64_encode($uri);
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
);
|
||||
return "ss://{$str}@{$server['host']}:{$server['port']}#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"v" => "2",
|
||||
"ps" => $server['name'],
|
||||
"add" => $server['host'],
|
||||
"port" => (string)$server['port'],
|
||||
"id" => $uuid,
|
||||
"aid" => '0',
|
||||
"net" => $server['network'],
|
||||
"type" => "none",
|
||||
"host" => "",
|
||||
"path" => "",
|
||||
"tls" => $server['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $config['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$config['path'] = $paths[array_rand($paths)];
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$config['host'] = $hosts[array_rand($hosts)];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server){
|
||||
$host = $server['host']; //节点地址
|
||||
$port = $server['port']; //节点端口
|
||||
$name = $server['name']; //节点名称
|
||||
|
||||
$config = [
|
||||
'mode' => 'multi', //grpc传输模式
|
||||
'security' => '', //传输层安全 tls/reality
|
||||
'encryption' => 'none', //加密方式
|
||||
'type' => $server['network'], //传输协议
|
||||
];
|
||||
// 判断是否开启XTLS
|
||||
if($server['flow']) ($config['flow'] = $server['flow']);
|
||||
// 如果开启TLS
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['sni'] = $tlsSettings['server_name'];
|
||||
$config['security'] = "tls";
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['servername'] = $tls_settings['server_name'];
|
||||
$config['spx'] = "/";
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[array_rand($fingerprints)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果传输协议为ws
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['network_settings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
// 传输协议为grpc
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
|
||||
$user = $uuid . '@' . $host . ':' . $port;
|
||||
$query = http_build_query($config);
|
||||
$fragment = urlencode($name);
|
||||
$link = sprintf("vless://%s?%s#%s\r\n", $user, $query, $fragment);
|
||||
return $link;
|
||||
}
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$params = [
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
];
|
||||
// 判断是否是grpc与ws协议
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
$params['type'] = $server['network'];
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) {
|
||||
$params['serviceName'] = $server['networkSettings']['serviceName'];
|
||||
};
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$params['path'] = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$params['host'] = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$query = http_build_query($params);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Protocols;
|
||||
|
||||
|
||||
class V2rayNG
|
||||
{
|
||||
public $flag = 'v2rayng';
|
||||
private $servers;
|
||||
private $user;
|
||||
|
||||
public function __construct($user, $servers)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->servers;
|
||||
$user = $this->user;
|
||||
$uri = '';
|
||||
|
||||
foreach ($servers as $item) {
|
||||
if ($item['type'] === 'vmess') {
|
||||
$uri .= self::buildVmess($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'shadowsocks') {
|
||||
$uri .= self::buildShadowsocks($item['password'], $item);
|
||||
}
|
||||
if ($item['type'] === 'trojan') {
|
||||
$uri .= self::buildTrojan($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'vless') {
|
||||
$uri .= self::buildVless($user['uuid'], $item);
|
||||
}
|
||||
if ($item['type'] === 'hysteria') {
|
||||
$uri .= General::buildHysteria($user['uuid'], $item);
|
||||
}
|
||||
}
|
||||
return base64_encode($uri);
|
||||
}
|
||||
|
||||
public static function buildShadowsocks($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$str = str_replace(
|
||||
['+', '/', '='],
|
||||
['-', '_', ''],
|
||||
base64_encode("{$server['cipher']}:{$password}")
|
||||
);
|
||||
$uri = "ss://{$str}@{$server['host']}:{$server['port']}";
|
||||
if ($server['obfs'] == 'http') {
|
||||
$uri .= "?plugin=obfs-local;obfs=http;obfs-host={$server['obfs-host']};path={$server['obfs-path']}";
|
||||
}
|
||||
return $uri."#{$name}\r\n";
|
||||
}
|
||||
|
||||
public static function buildVmess($uuid, $server)
|
||||
{
|
||||
$config = [
|
||||
"v" => "2",
|
||||
"ps" => $server['name'],
|
||||
"add" => $server['host'],
|
||||
"port" => (string)$server['port'],
|
||||
"id" => $uuid,
|
||||
"aid" => '0',
|
||||
"net" => $server['network'],
|
||||
"type" => "none",
|
||||
"host" => "",
|
||||
"path" => "",
|
||||
"tls" => $server['tls'] ? "tls" : "",
|
||||
];
|
||||
if ($server['tls']) {
|
||||
if ($server['tlsSettings']) {
|
||||
$tlsSettings = $server['tlsSettings'];
|
||||
if (isset($tlsSettings['serverName']) && !empty($tlsSettings['serverName']))
|
||||
$config['sni'] = $tlsSettings['serverName'];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'tcp') {
|
||||
$tcpSettings = $server['networkSettings'];
|
||||
if (isset($tcpSettings['header']['type'])) $config['type'] = $tcpSettings['header']['type'];
|
||||
if (isset($tcpSettings['header']['request']['path'][0])){
|
||||
$paths = $tcpSettings['header']['request']['path'];
|
||||
$config['path'] = $paths[array_rand($paths)];
|
||||
}
|
||||
if (isset($tcpSettings['header']['request']['headers']['Host'][0])){
|
||||
$hosts = $tcpSettings['header']['request']['headers']['Host'];
|
||||
$config['host'] = $hosts[array_rand($hosts)];
|
||||
}
|
||||
}
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['networkSettings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['networkSettings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['path'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
return "vmess://" . base64_encode(json_encode($config)) . "\r\n";
|
||||
}
|
||||
|
||||
public static function buildVless($uuid, $server){
|
||||
$host = $server['host']; //节点地址
|
||||
$port = $server['port']; //节点端口
|
||||
$name = $server['name']; //节点名称
|
||||
|
||||
$config = [
|
||||
'mode' => 'multi', //grpc传输模式
|
||||
'security' => '', //传输层安全 tls/reality
|
||||
'encryption' => 'none', //加密方式
|
||||
'type' => $server['network'], //传输协议
|
||||
];
|
||||
// 判断是否开启XTLS
|
||||
if($server['flow']) ($config['flow'] = $server['flow']);
|
||||
// 如果开启TLS
|
||||
if ($server['tls']) {
|
||||
switch($server['tls']){
|
||||
case 1:
|
||||
if ($server['tls_settings']) {
|
||||
$tlsSettings = $server['tls_settings'];
|
||||
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
|
||||
$config['sni'] = $tlsSettings['server_name'];
|
||||
$config['security'] = "tls";
|
||||
}
|
||||
break;
|
||||
case 2: //reality
|
||||
$config['security'] = "reality";
|
||||
$tls_settings = $server['tls_settings'];
|
||||
if(($tls_settings['public_key'] ?? null)
|
||||
&& ($tls_settings['short_id'] ?? null)
|
||||
&& ($tls_settings['server_name'] ?? null)){
|
||||
$config['pbk'] = $tls_settings['public_key'];
|
||||
$config['sid'] = $tls_settings['short_id'];
|
||||
$config['sni'] = $tls_settings['server_name'];
|
||||
$config['servername'] = $tls_settings['server_name'];
|
||||
$config['spx'] = "/";
|
||||
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
|
||||
$config['fp'] = $fingerprints[rand(0,count($fingerprints) - 1)];
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果传输协议为ws
|
||||
if ((string)$server['network'] === 'ws') {
|
||||
$wsSettings = $server['network_settings'];
|
||||
if (isset($wsSettings['path'])) $config['path'] = $wsSettings['path'];
|
||||
if (isset($wsSettings['headers']['Host'])) $config['host'] = $wsSettings['headers']['Host'];
|
||||
}
|
||||
// 传输协议为grpc
|
||||
if ((string)$server['network'] === 'grpc') {
|
||||
$grpcSettings = $server['network_settings'];
|
||||
if (isset($grpcSettings['serviceName'])) $config['serviceName'] = $grpcSettings['serviceName'];
|
||||
}
|
||||
|
||||
$user = $uuid . '@' . $host . ':' . $port;
|
||||
$query = http_build_query($config);
|
||||
$fragment = urlencode($name);
|
||||
$link = sprintf("vless://%s?%s#%s\r\n", $user, $query, $fragment);
|
||||
return $link;
|
||||
}
|
||||
|
||||
public static function buildTrojan($password, $server)
|
||||
{
|
||||
$name = rawurlencode($server['name']);
|
||||
$params = [
|
||||
'allowInsecure' => $server['allow_insecure'],
|
||||
'peer' => $server['server_name'],
|
||||
'sni' => $server['server_name']
|
||||
];
|
||||
// 判断是否是grpc与ws协议
|
||||
if(in_array($server['network'], ["grpc", "ws"])){
|
||||
$params['type'] = $server['network'];
|
||||
// grpc配置
|
||||
if($server['network'] === "grpc" && isset($server['networkSettings']['serviceName'])) {
|
||||
$params['serviceName'] = $server['networkSettings']['serviceName'];
|
||||
};
|
||||
// ws配置
|
||||
if($server['network'] === "ws") {
|
||||
if(isset($server['networkSettings']['path'])) {
|
||||
$params['path'] = $server['networkSettings']['path'];
|
||||
}
|
||||
if(isset($server['networkSettings']['headers']['Host'])){
|
||||
$params['host'] = $server['networkSettings']['headers']['Host'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$query = http_build_query($params);
|
||||
$uri = "trojan://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}";
|
||||
$uri .= "\r\n";
|
||||
return $uri;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user