LinkController.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controllers;
  4. use App\Models\Link;
  5. use App\Models\Node;
  6. use App\Models\UserSubscribeLog;
  7. use Psr\Http\Message\ResponseInterface;
  8. use Slim\Http\Request;
  9. use Slim\Http\Response;
  10. /**
  11. * LinkController
  12. */
  13. final class LinkController extends BaseController
  14. {
  15. public static function getContent(Request $request, Response $response, array $args): ResponseInterface
  16. {
  17. if (! $_ENV['Subscribe']) {
  18. return $response->withJson([
  19. 'ret' => 0,
  20. ]);
  21. }
  22. $token = $args['token'];
  23. $params = $request->getQueryParams();
  24. $Elink = Link::where('token', $token)->first();
  25. if ($Elink === null) {
  26. return $response->withJson([
  27. 'ret' => 0,
  28. ]);
  29. }
  30. $user = $Elink->getUser();
  31. if ($user === null) {
  32. return $response->withJson([
  33. 'ret' => 0,
  34. ]);
  35. }
  36. $sub_info = [];
  37. if (isset($params['clash']) && $params['clash'] === '1') {
  38. $sub_type = 'clash';
  39. $sub_info = SubController::getClash($user);
  40. }
  41. if (isset($params['sip002']) && $params['sip002'] === '1') {
  42. $sub_type = 'sip002';
  43. $sub_info = self::getSIP002($user);
  44. }
  45. if (isset($params['sub'])) {
  46. switch ($params['sub']) {
  47. case '2':
  48. $sub_type = 'ss';
  49. $sub_info = self::getSS($user);
  50. break;
  51. case '3':
  52. $sub_type = 'v2ray';
  53. $sub_info = self::getV2Ray($user);
  54. break;
  55. case '4':
  56. $sub_type = 'trojan';
  57. $sub_info = self::getTrojan($user);
  58. break;
  59. default:
  60. $sub_type = 'ss';
  61. $sub_info = self::getSS($user);
  62. break;
  63. }
  64. }
  65. // 记录订阅日志
  66. if ($_ENV['subscribeLog'] === true) {
  67. UserSubscribeLog::addSubscribeLog($user, $sub_type, $request->getHeaderLine('User-Agent'));
  68. }
  69. $sub_details = ' upload=' . $user->u
  70. . '; download=' . $user->d
  71. . '; total=' . $user->transfer_enable
  72. . '; expire=' . strtotime($user->class_expire);
  73. return $response->withHeader('Subscription-Userinfo', $sub_details)->write(
  74. $sub_info
  75. );
  76. }
  77. // 传统 SS 订阅
  78. public static function getSS($user): string
  79. {
  80. $links = '';
  81. //篩選出用戶能連接的節點
  82. $nodes_raw = Node::where('type', 1)
  83. ->where('node_class', '<=', $user->class)
  84. ->whereIn('node_group', [0, $user->group])
  85. ->where(static function ($query): void {
  86. $query->where('node_bandwidth_limit', '=', 0)->orWhereRaw('node_bandwidth < node_bandwidth_limit');
  87. })
  88. ->get();
  89. foreach ($nodes_raw as $node_raw) {
  90. $node_custom_config = \json_decode($node_raw->custom_config, true);
  91. //檢查是否配置“前端/订阅中下发的服务器地址”
  92. if (! \array_key_exists('server_user', $node_custom_config)) {
  93. $server = $node_raw->server;
  94. } else {
  95. $server = $node_custom_config['server_user'];
  96. }
  97. switch ($node_raw->sort) {
  98. case '0':
  99. $links .= \base64_encode($user->method . ':' . $user->passwd . '@' . $server . ':' . $user->port) . '#' .
  100. $node_raw->name . PHP_EOL;
  101. break;
  102. }
  103. }
  104. return $links;
  105. }
  106. // SIP002 SS 订阅
  107. public static function getSIP002($user): void
  108. {
  109. }
  110. public static function getV2Ray($user): string
  111. {
  112. $links = '';
  113. //篩選出用戶能連接的節點
  114. $nodes_raw = Node::where('type', 1)
  115. ->where('node_class', '<=', $user->class)
  116. ->whereIn('node_group', [0, $user->group])
  117. ->where(static function ($query): void {
  118. $query->where('node_bandwidth_limit', '=', 0)->orWhereRaw('node_bandwidth < node_bandwidth_limit');
  119. })
  120. ->get();
  121. foreach ($nodes_raw as $node_raw) {
  122. $node_custom_config = \json_decode($node_raw->custom_config, true);
  123. //檢查是否配置“前端/订阅中下发的服务器地址”
  124. if (! \array_key_exists('server_user', $node_custom_config)) {
  125. $server = $node_raw->server;
  126. } else {
  127. $server = $node_custom_config['server_user'];
  128. }
  129. switch ($node_raw->sort) {
  130. case '11':
  131. $v2_port = $node_custom_config['v2_port'] ?? ($node_custom_config['offset_port_user'] ?? ($node_custom_config['offset_port_node'] ?? 443));
  132. //默認值有問題的請懂 V2 怎麽用的人來改一改。
  133. $alter_id = $node_custom_config['alter_id'] ?? '0';
  134. $security = $node_custom_config['security'] ?? 'none';
  135. $network = $node_custom_config['network'] ?? '';
  136. $header = $node_custom_config['header'] ?? ['type' => 'none'];
  137. $header_type = $header['type'] ?? '';
  138. $host = $node_custom_config['host'] ?? '';
  139. $path = $node_custom_config['path'] ?? '/';
  140. $enable_vless = $node_custom_config['enable_vless'] ?? '0';
  141. $v2rayn_array = [
  142. 'v' => '2',
  143. 'ps' => $node_raw->name,
  144. 'add' => $server,
  145. 'port' => $v2_port,
  146. 'id' => $user->uuid,
  147. 'aid' => $alter_id,
  148. 'net' => $network,
  149. 'type' => $header_type,
  150. 'host' => $host,
  151. 'path' => $path,
  152. 'tls' => $security,
  153. ];
  154. if ($enable_vless === '1' || $enable_vless === 1) {
  155. $links .= 'vless://' . \base64_encode(\json_encode($v2rayn_array)) . PHP_EOL;
  156. break;
  157. }
  158. $links .= 'vmess://' . \base64_encode(\json_encode($v2rayn_array)) . PHP_EOL;
  159. break;
  160. }
  161. }
  162. return $links;
  163. }
  164. public static function getTrojan($user): string
  165. {
  166. $links = '';
  167. //篩選出用戶能連接的節點
  168. $nodes_raw = Node::where('type', 1)
  169. ->where('node_class', '<=', $user->class)
  170. ->whereIn('node_group', [0, $user->group])
  171. ->where(static function ($query): void {
  172. $query->where('node_bandwidth_limit', '=', 0)->orWhereRaw('node_bandwidth < node_bandwidth_limit');
  173. })
  174. ->get();
  175. foreach ($nodes_raw as $node_raw) {
  176. $node_custom_config = \json_decode($node_raw->custom_config, true);
  177. //檢查是否配置“前端/订阅中下发的服务器地址”
  178. if (! \array_key_exists('server_user', $node_custom_config)) {
  179. $server = $node_raw->server;
  180. } else {
  181. $server = $node_custom_config['server_user'];
  182. }
  183. switch ($node_raw->sort) {
  184. case '14':
  185. $trojan_port = $node_custom_config['trojan_port'] ?? ($node_custom_config['offset_port_user'] ?? ($node_custom_config['offset_port_node'] ?? 443));
  186. $host = $node_custom_config['host'] ?? '';
  187. $allow_insecure = $node_custom_config['allow_insecure'] ?? '0';
  188. $security = $node_custom_config['security'] ?? \array_key_exists('enable_xtls', $node_custom_config) && $node_custom_config['enable_xtls'] === '1' ? 'xtls' : 'tls';
  189. $mux = $node_custom_config['mux'] ?? '';
  190. $transport = $node_custom_config['transport'] ?? \array_key_exists('grpc', $node_custom_config) && $node_custom_config['grpc'] === '1' ? 'grpc' : 'tcp';
  191. $transport_plugin = $node_custom_config['transport_plugin'] ?? '';
  192. $transport_method = $node_custom_config['transport_method'] ?? '';
  193. $servicename = $node_custom_config['servicename'] ?? '';
  194. $path = $node_custom_config['path'] ?? '';
  195. $links .= 'trojan://' . $user->uuid . '@' . $server . ':' . $trojan_port . '?peer=' . $host . '&sni=' . $host .
  196. '&obfs=' . $transport_plugin . '&path=' . $path . '&mux=' . $mux . '&allowInsecure=' . $allow_insecure .
  197. '&obfsParam=' . $transport_method . '&type=' . $transport . '&security=' . $security . '&serviceName=' . $servicename . '#' .
  198. $node_raw->name . PHP_EOL;
  199. break;
  200. }
  201. }
  202. return $links;
  203. }
  204. public static function getTraditionalSub($user)
  205. {
  206. $userid = $user->id;
  207. $token = Link::where('userid', $userid)->first();
  208. return $_ENV['subUrl'] . '/link/' . $token->token;
  209. }
  210. }