"; if ($i <= 0) { // continue; } if ($i >= 100) { // continue; } $aPoolSingbox = $this->singbox_row($aPoolV2ray); if (!$aPoolSingbox) continue; //测试用 t($aPoolV2ray); t($aPoolSingbox); echo "======================================================="; } exit; } public function singbox_row($aPoolV2ray) { $aNode = $aPoolV2ray; if (isset($aPoolV2ray['protocolType'])) { $aPoolV2ray['protocolType'] = $this->removeUtf8Bom($aPoolV2ray['protocolType']); } $sProtocol = $aPoolV2ray['protocolType'] ?? ''; if (isset($aPoolV2ray["config"]) && !is_array($aPoolV2ray["config"])) { $aPoolV2ray["config"] = rawurldecode($aPoolV2ray["config"]); } $sModTo = 'mod_to_'.$sProtocol; if (!method_exists($this, $sModTo)) { return false; // 没做对应处理的直接排除 } $aNode = $this->$sModTo($aPoolV2ray); return $aNode; } private function mod_to_socks__($aV2ray) { $sConfig = $aV2ray["config"] ?? ''; $aTmp = explode("@", $sConfig, 2); $sPwd = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $sPwd = $this->tomBase64Decode($sPwd); $aTmp = explode(":", $sPwd, 2); $sUser = $aTmp[0] ?? ''; $sPwd = $aTmp[1] ?? ''; $aTmp = explode(":", $sConfig, 2); $sAddr = $aTmp[0] ?? ''; $iPort = $aTmp[1] ?? ''; $aNode = [ "type" => "socks", "tag" => $aV2ray['country'] ?? '', "server"=> $sAddr, "server_port" => (int) $iPort, "username" => $sUser, "password" => $sPwd ]; $aV2ray["config"] = $aNode; return $aV2ray; } private function mod_to_trojan($aV2ray) { $sConfig = $aV2ray["config"] ?? ''; $aTmp = explode("@", $sConfig, 2); $sPwd = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $aTmp = explode("?", $sConfig, 2); $sAddrFull = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $aTmp = explode(":", $sAddrFull, 2); $sAddr = $aTmp[0] ?? ''; $iPort = $aTmp[1] ?? ''; $aNode = [ "type" => "trojan", "tag" => $aV2ray['country'] ?? '', "server"=> $sAddr, "server_port" => (int) $iPort, "password" => $sPwd ]; $aCustomYuan = explode("&", $sConfig); $aCustom = []; foreach ($aCustomYuan as $sRow) { $aRow = explode("=", $sRow, 2); $k = $aRow[0] ?? ''; $v = $aRow[1] ?? ''; $aCustom[$k] = $v; } $aTls = []; // 层1的tls $aUtls = []; // 层2的utls if (isset($aCustom["sni"])) { // 写层1的tls $aTls["server_name"] = $this->parseServerName($aCustom["sni"], $aCustom["sni"]); } if (isset($aCustom["host"])) { // 写层1的tls -- host覆盖sni=host优先 $aTls["server_name"] = $this->parseServerName($aCustom["host"], $aCustom["host"]); } if (isset($aCustom["alpn"])) { // 写层1的tls $aTls["alpn"] = explode(",", $aCustom["alpn"]); } if (isset($aCustom["allowInsecure"])) { // 写层1的tls $aTls["insecure"] = (bool) $aCustom["allowInsecure"]; } if (isset($aCustom["fp"])) { // 写层2的utls $aUtls["fingerprint"] = $aCustom["fp"]; } if (!empty($aUtls)) { // 层2的utls并入tls $aUtls["enabled"] = true; $aTls["utls"] = $aUtls; } if (!empty($aTls)) { // 层1的tlstls并入node $aTls["enabled"] = true; $aNode["tls"] = $aTls; } $aTransport = []; if ($aCustom["type"] == "ws" && isset($aTls["server_name"])) { $aTransport["headers"]["Host"] = $aTls["server_name"]; } // if (isset($aCustom["type"]) && $aCustom["type"] != "tcp" && $aCustom["type"] != "none" && $aCustom["type"] != "raw") { // $aTransport["type"] = $aCustom["type"]; // if ($aCustom["type"] == "ws" && isset($aTls["server_name"])) { // $aTransport["headers"]["Host"] = $aTls["server_name"]; // } // } if (isset($aCustom["path"])) { $aTransport["path"] = rawurldecode($aCustom["path"]); } if (!empty($aTransport)) { if (isset($aCustom["type"]) && $aCustom["type"] != "none" && $aCustom["type"] != "raw") { $aTransport["type"] = $aCustom["type"]; } // if (empty($aTransport["type"])) { // $aTransport["type"] = "tcp"; // } $aNode["transport"] = $aTransport; } $aV2ray["config"] = $aNode; return $aV2ray; } private function mod_to_hysteria2($aV2ray) { $sConfig = $aV2ray["config"] ?? ''; $aTmp = explode("@", $sConfig, 2); $sPwd = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $aTmp = explode("?", $sConfig, 2); $sAddrFull = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $aTmp = explode(":", $sAddrFull, 2); $sAddr = $aTmp[0] ?? ''; $iPort = $aTmp[1] ?? ''; $cCustom = explode("&", $sConfig); $aCustom = []; foreach ($cCustom as $sCustom) { $aTmp = explode("=", $sCustom); $k = $aTmp[0] ?? ''; $v = $aTmp[1] ?? ''; $aCustom[$k] = $v; } $aNode = [ "type" => "hysteria2", "tag" => $aV2ray['country'] ?? '', "server"=> $sAddr, "server_port" => (int) $iPort, "password" => $sPwd ]; $aTls = []; if (isset($aCustom['sni'])) { $aTls['server_name'] = $this->parseServerName($aCustom['sni'], $aCustom['sni']); } if (isset($aCustom['insecure'])) { $aTls['insecure'] = (bool) $aCustom['insecure'] ?? 0; } if (!empty($aTls)) { $aTls['enabled'] = true; $aNode["tls"] = $aTls; } $aObfs = []; if (isset($aCustom["obfs"])) { $aObfs["type"] = $aCustom["obfs"]; } if (isset($aCustom["obfs-password"])) { $aObfs["password"] = $aCustom["obfs-password"]; } if (!empty($aObfs)) { $aNode["obfs"] = $aObfs; } $aV2ray["config"] = $aNode; return $aV2ray; } private function mod_to_ss($aV2ray) { $sConfig = $aV2ray["config"] ?? ''; $aTmp = explode("@", $sConfig, 2); $sPwd = $aTmp[0] ?? ''; $sConfig = $aTmp[1] ?? ''; $sPwd = $this->tomBase64Decode($sPwd); $aTmp = explode(":", $sPwd, 2); $sPwdType = $aTmp[0] ?? ''; $sPwd = $aTmp[1] ?? ''; $aTmp = explode(":", $sConfig, 2); $sAddr = $aTmp[0] ?? ''; $iPort = $aTmp[1] ?? ''; // 推荐的现代化 SS 算法白名单 $aAllowedCiphers = [ '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', '2022-blake3-chacha20-poly1305', 'aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305', ]; if (!in_array($sPwdType, $aAllowedCiphers, true)) { return false; } $aNode = [ "type" => "shadowsocks", "tag" => $aV2ray['country'] ?? '', "server" => $sAddr, "server_port" => (int) $iPort, "method" => $sPwdType, "password" => $sPwd, ]; $aV2ray["config"] = $aNode; return $aV2ray; } private function mod_to_vmess($aV2ray) { $aNode = []; $aConfig = $aV2ray["config"]; $aNode["type"] = "vmess"; $aNode["tag"] = $aV2ray['country'] ?? ''; $aNode["server"] = $aConfig["add"] ?? ''; $aNode["server_port"] = $aConfig["port"] ?? ''; // Cannot access offset of type string on string $aNode["server_port"] = (int) $aNode["server_port"]; $aNode["uuid"] = $aConfig["id"] ?? ''; $aNode["security"] = $aConfig["scy"] ?? 'auto'; $aNode["alter_id"] = $aConfig["aid"] ?? 0; // 猜的 $aNode["alter_id"] = (int) $aNode["alter_id"]; $aTransport = []; if (isset($aConfig["net"]) && $aConfig["net"] != "none" && $aConfig["net"] != "raw") { $aTransport["type"] = $aConfig["net"]; } if (isset($aConfig["path"])) { $aTransport["path"] = rawurldecode($aConfig["path"]); } if (isset($aConfig["host"])) { $aTransport["headers"]["Host"] = $aConfig["host"]; } if (!empty($aTransport)) { if (empty($aTransport["type"])) { $aTransport["type"] = "tcp"; } $aNode["transport"] = $aTransport; } $aTls = []; if (isset($aConfig["tls"])) { if ($aConfig["tls"] == "tls") { $aTls["server_name"] = !empty($aConfig['host']) ? $aConfig['host'] : $aConfig['add']; $aTls["server_name"] = $this->parseServerName($aTls["server_name"], $aTls["server_name"]); } } if (!empty($aTls)) { $aTls["enabled"] = true; $aNode["tls"] = $aTls; } $aV2ray["config"] = $aNode; return $aV2ray; } private function mod_to_vless__($aV2ray) { $sConfig = $aV2ray['config'] ?? ''; $aTmp = explode("@", $sConfig, 2); $sPwd = $aTmp[0] ?? ''; // * $sConfig = $aTmp[1] ?? ''; $aTmp = explode("?", $sConfig, 2); $sAddrFull = $aTmp[0]; $sConfig = $aTmp[1]; $aTmp = explode(":", $sAddrFull, 2); $sAddr = $aTmp[0] ?? ''; // * $sPort = $aTmp[1] ?? ''; // * $aCustomTmp = explode("&", $sConfig); $aCustom = []; foreach ($aCustomTmp as $aCustomRow) { $aTmp = explode("=", $aCustomRow, 2); $k = $aTmp[0] ?? ''; $v = $aTmp[1] ?? ''; $aCustom[$k] = $v; // * } $aNode = [ 'type' => 'vless', 'tag' => $aV2ray['country'] ?? '', 'server' => $sAddr, 'server_port' => (int) $sPort, 'uuid' => $sPwd, ]; if (isset($aCustom["packetEncoding"]) && $aCustom["packetEncoding"] != "none") { $aNode["packet_encoding"] = $aCustom["packetEncoding"]; } if (isset($aCustom["flow"])) { $aNode["flow"] = $aCustom["flow"]; } $aTransport = []; if (isset($aCustom["type"]) && $aCustom["type"] != "raw") { $aTransport["type"] = $aCustom["type"]; } if (isset($aCustom["headerType"]) && $aCustom["headerType"] == "http") { $aTransport["type"] = "http"; // 整个http覆盖默认tcp } if (isset($aCustom["path"])) { $aTransport["path"] = rawurldecode($aCustom["path"]); } if (isset($aCustom["host"])) { $aTransport["headers"]["Host"] = $aCustom["host"]; } if (isset($aCustom["serviceName"])) { $aTransport["service_name"] = $aCustom["serviceName"]; } if (!empty($aTransport)) { if (empty($aTransport["type"])) { $aTransport["type"] = "tcp"; } $aNode["transport"] = $aTransport; } $aTls = []; // 本体 $aUtls = []; // 二层 $aReality = []; // 二层 if (isset($aCustom["fp"])) { // 二层的utls构建 if ($aCustom["fp"] == "random") { $aCustom["fp"] = "chrome"; } $aUtls["fingerprint"] = $aCustom["fp"]; } if (!empty($aUtls)) { // 二层的utls封装进tls $aUtls["enabled"] = true; $aTls["utls"] = $aUtls; } if (isset($aCustom["security"])) { $sSecurity = $aCustom["security"]; if ($sSecurity == "reality") { // 二层的reality构建 if (isset($aCustom["pbk"])) { $aReality["public_key"] = $aCustom["pbk"]; } if (isset($aCustom["sid"])) { $aReality["short_id"] = (string) $aCustom["sid"]; } } } if (!empty($aReality)) { // 二层的reality封建进tls $aReality["enabled"] = true; $aTls["reality"] = $aReality; } if (isset($aCustom["alpn"])) { $sTmp = $aCustom["alpn"] ?? ""; $aTmp = explode(",", $sTmp); $aTls["alpn"] = $aTmp; } if (isset($aCustom["sni"])) { // 本体的tls构建 $aTls["server_name"] = $this->parseServerName($aCustom["sni"], $aCustom["sni"]); } if (isset($aCustom["encryption"]) && $aCustom["encryption"] != "none") { // 本体的tls构建 $aTls["encryption"] = $aCustom["encryption"]; } if (!empty($aTls)) { // 本体的tls封装进node $aTls["enabled"] = true; $aNode["tls"] = $aTls; } $aV2ray["config"] = $aNode; return $aV2ray; } private function tomBase64Decode(mixed $xInput): string { // 1. 防御性类型检查 if (!is_string($xInput) || $xInput === '') { return (string) $xInput; } // 2. 开启严格模式解码 $sDecoded = base64_decode($xInput, true); if ($sDecoded === false) { return $xInput; } // 3. 反向验证:确保它不是像 humanity 这种恰好能被解码的纯普通文本 if (base64_encode($sDecoded) !== $xInput) { return $xInput; } // 4. 核心:校验解码后的数据是否为合法 UTF-8 文本,且不包含不可打印控制字符(\x00-\x08, \x0B-\x0C, \x0E-\x1F) $bIsValidUtf8 = mb_check_encoding($sDecoded, 'UTF-8'); $bHasControlChars = (bool) preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', $sDecoded); if ($bIsValidUtf8 && !$bHasControlChars) { return $sDecoded; // 解码出来是合法的正常文本(包含中文、英文、数字等) } // 解码出来包含真正的二进制控制符(乱码),说明输入原本就是纯字符串,返回原值 return rawurldecode($xInput); } public function test_allXieyi($cPoolV2ray) { $aXieyi = []; foreach ($cPoolV2ray as $aV2ray) { $sXieyi = $aV2ray["protocolType"]; $sXieyi = $this->removeUtf8Bom($sXieyi); $iXieyi = $aXieyi[$sXieyi] ?? 0; $iXieyi++; $aXieyi[$sXieyi] = $iXieyi; } return $aXieyi; } private function removeUtf8Bom(string $sInput): string { if (str_starts_with($sInput, "\xEF\xBB\xBF")) { return substr($sInput, 3); } return $sInput; } private function parseServerName(string $sSni, string $sFallbackServer): string { $sSni = trim($sSni); $sSni = rawurldecode($sSni); if (empty($sSni)) { return $sFallbackServer; } // 针对包含 http:// 或 https:// 的情况进行解析 if (preg_match('#^https?://#i', $sSni)) { $aUrl = parse_url($sSni); $sSni = $aUrl['host'] ?? ''; } // 剔除可能残余的路径与端口号 (例如 domain.com/path 或 domain.com:8080) if (str_contains($sSni, '/')) { $sSni = explode('/', $sSni)[0]; } if (str_contains($sSni, ':')) { $sSni = explode(':', $sSni)[0]; } // 若提取后仍为空,回退到节点自身的 server 字段 return !empty($sSni) ? $sSni : $sFallbackServer; } }