alroyso 7 月之前
父節點
當前提交
b84e6088dd

+ 103 - 0
app/Components/Client/SingBoxBuildProxy.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace App\Components\Client;
+
+/*
+ * 本文件依据Clash文件编辑
+ * https://github.com/Dreamacro/clash/tree/master/adapters/outbound
+ *
+ */
+
+class SingBoxBuildProxy
+{
+    public static function buildShadowsocks($server)
+    {
+        return [
+            'tag' => $server['name'],
+            'type' => 'shadowsocks',
+            'server' => $server['host'],
+            'server_port' => $server['port'],
+            'password' => $server['passwd'],
+            'method' => $server['method'],
+
+        ];
+    }
+
+    public static function buildVmess($server)
+    {
+        $array = [
+            'tag' => $server['name'],
+            'type' => 'vmess',
+            'server' => $server['host'],
+            'server_port' => $server['port'],
+            'uuid' => $server['uuid'],
+            'alter_id' => $server['v2_alter_id'],
+            'security' => $server['method'],
+        ];
+
+        if ($server['v2_tls']) {
+            $array['tls'] = true;
+            $array['insecure'] = !empty($server['sni']);
+            if (! empty($server['sni'])) {
+                 $array['server_name'] = $server['sni'];
+            } else if(!empty($server['v2_host'])){
+                $array['server_name'] = $server['v2_host'];
+            }
+
+        }
+        $array['network'] = $server['v2_net'];
+
+        if ($server['v2_net'] === 'ws') {
+            $array['transport']['path'] = $server['v2_path'];
+            $array['transport']['headers'] = ['Host' => $server['v2_host']];
+        }
+
+        return $array;
+    }
+
+
+    public static function buildVless($server)
+    {
+        $array = [
+            'tag' => $server['name'],
+            'type' => 'vless',
+            'server' => $server['host'],
+            'server_port' => $server['port'],
+            'uuid' => $server['uuid'],
+            //'alter_id' => $server['v2_alter_id'],
+            'flow' => 'xtls-rprx-vision',
+            "packet_encoding" => "xudp"
+            //'server_name' => $server['v2_sni'],
+//            'tls' => ['enabled' => true,"server_name"=>$server['v2_host']],
+        ];
+        //'reality-opts' => $server['v2_sni'],
+        $tlsConfig = [];
+        $tlsConfig['enabled'] = true;
+        if (!empty($server['v2_sni'])) {
+            $tlsConfig['server_name'] = $server['v2_sni'];
+        } else if(!empty($server['v2_host'])){
+            $tlsConfig['server_name'] = $server['v2_host'];
+        }
+
+        $tlsConfig['reality'] = ["enabled"=>true,'public_key' => $server['vless_pulkey']];
+        $tlsConfig['utls'] = ['enabled' => true,'fingerprint'=> 'chrome'];
+        $array['tls'] = $tlsConfig;
+        return $array;
+    }
+    public static function buildTrojan($server)
+    {
+        $array = [
+            'tag' => $server['name'],
+            'type' => 'trojan',
+            'server' => $server['host'],
+            'server_port' => $server['port'],
+            'password' => $server['passwd'],
+        ];
+
+        if (! empty($server['sni'])) {
+            $array['server_name'] = $server['sni'];
+        }
+
+        return $array;
+    }
+}

+ 178 - 0
app/Components/Protocols/SingBox.php

@@ -0,0 +1,178 @@
+<?php
+
+namespace App\Components\Protocols;
+
+use App\Components\Client\SingBoxBuildProxy;
+use App\Models\User;
+use File;
+
+class SingBox
+{
+   function NewSingBox(User $user,$server)
+   {
+       $defaultConfig = base_path().'/resources/rules/default.sing-box.json';
+       $customConfig = base_path().'/resources/rules/custom.sing-box.json';
+
+       if (File::exists($customConfig)) {
+           $configContent = file_get_contents($customConfig);
+           $config = json_decode($configContent, true);
+       } else {
+           $configContent = file_get_contents($defaultConfig);
+           $config = json_decode($configContent, true);
+       }
+       $outbounds = $config['outbounds'];
+       $proxies = [];
+       foreach ($server as $item) {
+           if ($item['type'] === 'shadowsocks') {
+               $ssConfig = SingBoxBuildProxy::buildShadowsocks( $item);
+               $proxies[] = $ssConfig;
+           }
+           if ($item['type'] === 'trojan') {
+               $trojanConfig =  SingBoxBuildProxy::buildTrojan($item);
+               $proxies[] = $trojanConfig;
+           }
+           if ($item['type'] === 'v2ray') {
+               if ($item['vless'] == 1){
+                   $vlessConfig =  SingBoxBuildProxy::buildVless($item);
+                   $proxies[] = $vlessConfig;
+               } else {
+                   $vmess = SingBoxBuildProxy::buildVmess($item);
+                   $proxies[] = $vmess;
+               }
+
+           }
+
+       }
+       return $this->updateConfigWithProxies($user,$config, $proxies);
+   }
+
+    function  updateConfigWithProxies(User $user,$config, $proxies) {
+
+         $uri = "到期时间:{$user->expired_at}";
+        // 定义地区及其对应的正则表达式
+        $regions = [
+            "hk" => '/香港/',
+            "us" => '/美国/',
+            "tw" => '/台湾/',
+            "jp" => '/日本/',
+
+        ];
+
+        $usedTags = [];
+        $regionTags = [];
+
+//        $upload = flowAutoShow($user->u);
+//        $download = flowAutoShow($user->d);
+//        $totalTraffic = flowAutoShow($user->transfer_enable);
+
+        $userConfig=  [
+            'tag' => $uri,
+            'type' => 'shadowsocks',
+            'server' => "dudu02.ddnsguru.com",
+            'server_port' => 13223,
+            'password' => "2yYbPmksa221233",
+            'method' => "aes-128-gcm",
+        ];
+
+        // 先创建 "proxy" 组并添加到配置的最前面
+        $proxyOutbound = $this->buildOutbound("proxy", "selector", "hk", []);
+        array_unshift($config['outbounds'], $proxyOutbound);
+
+        // 创建每个地区的代理组
+        foreach ($regions as $regionTag => $pattern) {
+            $tags = $this->buildTags($proxies, $pattern);
+            $this->updateOrAddOutbound($config['outbounds'], $this->buildOutbound($regionTag, "selector", "", $tags));
+            $usedTags = array_merge($usedTags, $tags);
+            $regionTags[] = $regionTag;
+        }
+
+        // 创建 "其他" 代理组
+        $allTags = array_column($proxies, 'tag');
+        $otherTags = array_diff($allTags, $usedTags);
+        $this->updateOrAddOutbound($config['outbounds'], $this->buildOutbound("other", "selector", "", $otherTags));
+        $regionTags[] = "other";
+        $this->updateOrAddOutbound($config['outbounds'],$this->buildOutbound("dns", "selector", "", $this->buildTags($proxies,"")));
+
+//        $this->updateOrAddOutbound($config['outbounds'],$this->buildOutbound("用户中心", "selector", "", [$uri]));
+        $this->updateOrAddOutbound($config['outbounds'], $userConfig);
+
+        $usedCus = array_merge($regionTags, [$uri]);
+        // 更新 "proxy" 组,包含所有地区和其他代理组的 tag
+        $config['outbounds'][0]['outbounds'] = $usedCus;
+        //$config['outbounds'][0]['outbounds'] = ;
+        // 将所有 $proxies 加入到 $config['outbounds']
+        foreach ($proxies as $proxy) {
+            $this->updateOrAddOutbound($config['outbounds'], $proxy);
+        }
+
+
+
+        // 返回更新后的配置 JSON 字符串
+        return json_encode($config, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+    }
+
+
+    function buildOutbound($tag, $type, $default, $outbounds) {
+       if ($type === "urltest")
+       {
+           return [
+               "tag" => $tag,
+               "type" => $type,
+               "outbounds" => array_values($outbounds)
+           ];
+       }
+        return [
+            "tag" => $tag,
+            "type" => $type,
+            "default" => $default ,
+            "outbounds" => array_values($outbounds)
+        ];
+    }
+
+    function updateOrAddOutbound(&$outbounds, $newOutbound) {
+        $found = false;
+        foreach ($outbounds as &$outbound) {
+            if ($outbound['tag'] == $newOutbound['tag']) {
+                $outbound = $newOutbound;
+                $found = true;
+                break;
+            }
+        }
+        if (!$found) {
+            $outbounds[] = $newOutbound;
+        }
+    }
+
+    function buildTags($proxies, $pattern = '') {
+        if (empty($pattern)) {
+            // 如果没有提供正则表达式模式,返回所有代理的 tag 列表
+            return array_column($proxies, 'tag');
+        }
+
+        // 使用正则表达式筛选代理
+        $filteredProxies = array_filter($proxies, function($proxy) use ($pattern) {
+            return preg_match($pattern, $proxy['tag']);
+        });
+
+        // 提取代理的 tag 列表
+        return array_column($filteredProxies, 'tag');
+    }
+
+
+    function buildTtype($proxies, $pattern = '') {
+        if (empty($pattern)) {
+            // 如果没有提供正则表达式模式,返回所有代理的 tag 列表
+            return array_column($proxies, 'type');
+        }
+
+        // 使用正则表达式筛选代理
+        $filteredProxies = array_filter($proxies, function($proxy) use ($pattern) {
+            return $pattern == $proxy['type'];
+        });
+
+
+        // 提取代理的 tag 列表
+        return array_column($filteredProxies, 'tag');
+    }
+
+}

+ 12 - 0
app/Http/Controllers/ClientController.php

@@ -4,9 +4,11 @@ namespace App\Http\Controllers;
 
 use App\Components\Client\Clash;
 use App\Components\Client\QuantumultX;
+
 use App\Components\Client\Surfboard;
 use App\Components\Client\Surge;
 use App\Components\Client\URLSchemes;
+use App\Components\Protocols\SingBox;
 use App\Models\User;
 use File;
 use Symfony\Component\Yaml\Yaml;
@@ -37,9 +39,16 @@ class ClientController extends Controller
         if (strpos($target, 'meet') !== false) {
             return $this->clash_meet($servers);
         }
+
+
+        if (strpos($target, 'sing') !== false) {
+            return (new SingBox)->NewSingBox($user,$servers);
+        }
 //            if (strpos($target, 'shadowsocks') !== false) {
 //                exit($this->shaodowsocksSIP008($servers));
 //            }
+
+
         return $this->origin($servers);
     }
 
@@ -103,6 +112,9 @@ class ClientController extends Controller
 
         return $encode ? base64_encode($uri) : $uri;
     }
+
+
+
     private function clash_meet($servers)
     {
         $defaultConfig = base_path().'/resources/rules/default.clash.yaml';

+ 10 - 3
app/Http/Controllers/DownloadControllers.php

@@ -27,6 +27,12 @@ class DownloadControllers extends Controller
             $totalTransfer = $user->transfer_enable;
             $usedTransfer = $user->usedTraffic();
             $unusedTraffic = $totalTransfer - $usedTransfer > 0 ? $totalTransfer - $usedTransfer : 0;
+
+            $upload = flowAutoShow($user->u);
+            $download = flowAutoShow($user->d);
+            $totalTraffic = flowAutoShow($user->transfer_enable);
+            $uri = " STATUS=📤:{$upload}📥:{$download}⏳:{$totalTraffic}📅:{$user->expired_at}\r\n";
+
             $expireTime = $user->expired_at;
             $profile= auth()->user()->profile();
             $data = [];
@@ -40,7 +46,7 @@ class DownloadControllers extends Controller
             if (Node::whereType(3)->whereStatus(1)->exists()) {
                 $data[] = 'trojan';
             }
-
+            //https://vip.dynew2024.top/s/tI2WtgPi?target=sing
             $subscribe = auth()->user()->subscribe;
             // $subscribe_link = route('sub', $subscribe->code);
             $subscribe_link = sysConfig('subscribe_domain') . "/s/" . $subscribe->code;
@@ -50,6 +56,7 @@ class DownloadControllers extends Controller
             $subscribe_linkD = "https://naizi1124.xn--3iq226gfdb94q.com" . "/s/" . $subscribe->code . "?target=meet";
             $subscribe_linkF = "https://107.148.72.132" . "/s/" . $subscribe->code . "?target=meet";
             $subscribe_linkG = "https://naizi1124.xn--3iq226gfdb94q.com" . "/s/" . $subscribe->code . "?target=clash";
+            $subscribe_linkH = "https://naizi1124.xn--3iq226gfdb94q.com" . "/s/" . $subscribe->code . "?target=sing";
 //            $subarr = ["A"=>"","B"=>""];
 
             return view('down.dowload', [
@@ -70,8 +77,8 @@ class DownloadControllers extends Controller
                    "wx"                 => Article::whereId(10)->first(),
                     "ios"                 => Article::whereId(7)->first(),
                     "sp"                 => Article::whereId(13)->first(),
-
-
+                //sing-box://import-remote-profile?url=urlEncodedURL#urlEncodedName
+                "singBox"                   => 'sing-box://import-remote-profile?url=' . urlencode($subscribe_linkH).'#'.sysConfig('website_name'),
                 'subUrl'                  => sysConfig('subscribe_domain') . "/s/" . $subscribe->code,
                 'sub'                     => $data,
                 'paying_user'             => auth()->user()->activePayingUser(), // 付费用户判断

+ 15 - 0
public/test/decrypt_redirect.php

@@ -0,0 +1,15 @@
+<?php
+// 引入解密函数
+require 'encrypt_functions.php';
+
+// 获取加密链接
+if (isset($_GET['link'])) {
+    $encryptedLink = $_GET['link'];
+    $link = decryptLink(urldecode($encryptedLink));
+
+    // 跳转到解密后的链接
+    header("Location: $link");
+    exit();
+} else {
+    echo "No link provided.";
+}

+ 21 - 0
public/test/encrypt_functions.php

@@ -0,0 +1,21 @@
+<?php
+
+function encryptLink($url) {
+    $key = 'secret_key'; // 加密密钥
+    $data = base64_encode($url);
+    $encrypted = '';
+    for ($i = 0; $i < strlen($data); $i++) {
+        $encrypted .= chr(ord($data[$i]) ^ ord($key[$i % strlen($key)]));
+    }
+    return base64_encode($encrypted);
+}
+
+function decryptLink($encrypted) {
+    $key = 'secret_key'; // 加密密钥
+    $data = base64_decode($encrypted);
+    $decrypted = '';
+    for ($i = 0; $i < strlen($data); $i++) {
+        $decrypted .= chr(ord($data[$i]) ^ ord($key[$i % strlen($key)]));
+    }
+    return base64_decode($decrypted);
+}

+ 21 - 0
public/test/random_redirect.php

@@ -0,0 +1,21 @@
+<?php
+// 引入解密函数
+require 'encrypt_functions.php';
+
+// 定义域名链接数组
+$links = [
+    'A' => 'https://www.google.com/',
+    'B' => 'https://www.baidu.com',
+    'C' => 'https://user.vipfive.xyz',
+    'D' => 'https://example-d.com'
+];
+
+// 随机获取一个链接
+$randomLink = $links[array_rand($links)];
+
+// 加密链接
+$encryptedLink = encryptLink($randomLink);
+
+// 跳转到加密后的链接页面
+header("Location: decrypt_redirect.php?link=" . urlencode($encryptedLink));
+exit();

+ 1 - 0
public/test/test.txt

@@ -0,0 +1 @@
+ssss

+ 149 - 0
resources/rules/default.sing-box.json

@@ -0,0 +1,149 @@
+{
+    "log": {
+        "disabled": false,
+        "level": "error",
+        "timestamp": true
+    },
+    "dns": {
+        "servers": [
+            {
+                "tag": "default-dns",
+                "address": "223.5.5.5",
+                "detour": "direct"
+            },
+            {
+                "tag": "system-dns",
+                "address": "local",
+                "detour": "direct"
+            },
+            {
+                "tag": "block-dns",
+                "address": "rcode://name_error"
+            },
+            {
+                "tag": "google",
+                "address": "https://dns.google/dns-query",
+                "address_resolver": "default-dns",
+                "address_strategy": "ipv4_only",
+                "strategy": "ipv4_only",
+                "client_subnet": "1.0.1.0"
+            }
+        ],
+        "rules": [
+            {
+                "outbound": "any",
+                "server": "default-dns"
+            },
+            {
+                "query_type": "HTTPS",
+                "server": "block-dns"
+            },
+            {
+                "clash_mode": "direct",
+                "server": "default-dns"
+            },
+            {
+                "clash_mode": "global",
+                "server": "google"
+            },
+            {
+                "rule_set": "geosite-cn",
+                "server": "default-dns"
+            }
+        ],
+        "strategy": "ipv4_only",
+        "disable_cache": false,
+        "disable_expire": false,
+        "independent_cache": false,
+        "final": "google"
+    },
+    "experimental": {
+        "cache_file": {
+            "enabled": true,
+            "path": "cache.db",
+            "cache_id": "cache_db",
+            "store_fakeip": true
+        }
+    },
+    "inbounds": [
+        {
+            "auto_route": true,
+            "domain_strategy": "prefer_ipv4",
+            "endpoint_independent_nat": true,
+            "inet4_address": "172.19.0.1/30",
+
+            "mtu": 9000,
+            "sniff": true,
+            "sniff_override_destination": true,
+            "stack": "system",
+            "strict_route": true,
+            "type": "tun"
+        },
+        {
+            "domain_strategy": "prefer_ipv4",
+            "listen": "127.0.0.1",
+            "listen_port": 2333,
+            "sniff": true,
+            "sniff_override_destination": true,
+            "tag": "socks-in",
+            "type": "socks",
+            "users": []
+        },
+        {
+            "domain_strategy": "prefer_ipv4",
+            "listen": "127.0.0.1",
+            "listen_port": 2334,
+            "sniff": true,
+            "sniff_override_destination": true,
+            "tag": "mixed-in",
+            "type": "mixed",
+            "users": []
+        }
+    ],
+    "outbounds": [
+        { "tag": "direct", "type": "direct" },
+        { "tag": "block", "type": "block" },
+        { "tag": "dns-out", "type": "dns" }
+    ],
+    "route": {
+        "auto_detect_interface": true,
+        "rules": [
+            {
+                "outbound": "dns-out",
+                "protocol": "dns"
+            },
+            {
+                "clash_mode": "direct",
+                "outbound": "direct"
+            },
+            {
+                "clash_mode": "global",
+                "outbound": "proxy"
+            },
+            {
+                "ip_is_private": true,
+                "outbound": "direct"
+            },
+            {
+                "rule_set": ["geosite-cn", "geoip-cn"],
+                "outbound": "direct"
+            }
+        ],
+        "rule_set": [
+            {
+                "tag": "geosite-cn",
+                "type": "remote",
+                "format": "binary",
+                "url": "https://ewr1.vultrobjects.com/down/new-bucket-60f273fc/geosite-cn.srs",
+                "download_detour": "direct"
+            },
+            {
+                "tag": "geoip-cn",
+                "type": "remote",
+                "format": "binary",
+                "url": "https://ewr1.vultrobjects.com/down/new-bucket-60f273fc/geoip-cn.srs",
+                "download_detour": "direct"
+            }
+        ]
+    }
+}