1
0

LinkController.php 10 KB

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