Stash.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. namespace App\Utils\Clients\Formatters;
  3. use App\Utils\Library\Templates\Formatter;
  4. class Stash implements Formatter
  5. {
  6. // https://stash.wiki/proxy-protocols/proxy-types
  7. public static function build(array $servers): array
  8. {
  9. $validTypes = ['shadowsocks', 'shadowsocksr', 'vmess', 'trojan', 'hysteria2'];
  10. foreach ($servers as $server) {
  11. if (in_array($server['type'], $validTypes, true)) {
  12. $proxy = call_user_func([self::class, 'build'.ucfirst($server['type'])], $server);
  13. if ($proxy) {
  14. $ids[] = $server['id'];
  15. $proxies[] = $proxy;
  16. }
  17. }
  18. }
  19. return ['ids' => $ids ?? [], 'proxies' => $proxies ?? []];
  20. }
  21. public static function buildShadowsocks(array $server): ?array
  22. {
  23. $supportedMethods = ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb', 'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr', 'rc4-md5', 'chacha20', 'chacha20-ietf', 'xchacha20', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305', '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm'];
  24. if (! in_array($server['method'], $supportedMethods, true)) {
  25. return null;
  26. }
  27. return [
  28. 'name' => $server['name'],
  29. 'type' => 'ss',
  30. 'server' => $server['host'],
  31. 'port' => $server['port'],
  32. 'cipher' => $server['method'],
  33. 'password' => $server['passwd'],
  34. 'udp' => $server['udp'],
  35. ];
  36. }
  37. public static function buildShadowsocksr(array $server): ?array
  38. {
  39. $supportedMethods = ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb', 'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr', 'rc4-md5', 'chacha20', 'chacha20-ietf', 'xchacha20', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305', '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', 'none'];
  40. $supportedObfuscations = ['plain', 'http_simple', 'http_post', 'random_head', 'tls1.2_ticket_auth', 'tls1.2_ticket_fastauth'];
  41. $supportedProtocols = ['origin', 'auth_sha1_v4', 'auth_aes128_md5', 'auth_aes128_sha1', 'auth_chain_a', 'auth_chain_b'];
  42. if (! in_array($server['method'], $supportedMethods, true) || ! in_array($server['obfs'], $supportedObfuscations, true) || ! in_array($server['protocol'], $supportedProtocols, true)) {
  43. return null;
  44. }
  45. return [
  46. 'name' => $server['name'],
  47. 'type' => 'ssr',
  48. 'server' => $server['host'],
  49. 'port' => $server['port'],
  50. 'cipher' => $server['method'],
  51. 'password' => $server['passwd'],
  52. 'obfs' => $server['obfs'],
  53. 'obfs-param' => $server['obfs_param'] ?? '',
  54. 'protocol' => $server['protocol'],
  55. 'protocol-param' => $server['protocol_param'] ?? '',
  56. ];
  57. }
  58. public static function buildVmess(array $server): ?array
  59. {
  60. $supportedMethods = ['auto', 'aes-128-gcm', 'chacha20-poly1305', 'none'];
  61. $supportedNetworks = ['ws', 'h2', 'http', 'grpc'];
  62. if (! in_array($server['method'], $supportedMethods, true) || ($server['v2_net'] && ! in_array($server['v2_net'], $supportedNetworks, true))) {
  63. return null;
  64. }
  65. $array = [
  66. 'name' => $server['name'],
  67. 'type' => 'vmess',
  68. 'server' => $server['host'],
  69. 'port' => $server['port'],
  70. 'uuid' => $server['uuid'],
  71. 'cipher' => $server['method'],
  72. 'alterId' => $server['v2_alter_id'],
  73. 'udp' => $server['udp'] ?? false,
  74. ];
  75. if (isset($server['v2_tls']) && $server['v2_tls']) {
  76. $array['tls'] = true;
  77. $array['servername'] = $server['v2_host'] ?? '';
  78. }
  79. $array['network'] = $server['v2_net'] ?? 'tcp';
  80. if (isset($server['v2_net']) && $server['v2_net'] === 'ws') {
  81. $array['ws-opts'] = [];
  82. $array['ws-opts']['path'] = $server['v2_path'] ?? '/';
  83. if (! empty($server['v2_host'])) {
  84. $array['ws-opts']['headers'] = ['Host' => $server['v2_host']];
  85. }
  86. $array['ws-path'] = $server['v2_path'] ?? '/';
  87. if (! empty($server['v2_host'])) {
  88. $array['ws-headers'] = ['Host' => $server['v2_host']];
  89. }
  90. }
  91. // 添加更多VMess选项
  92. if (! empty($server['v2_alpn'])) {
  93. $array['alpn'] = $server['v2_alpn'];
  94. }
  95. if (isset($server['v2_allow_insecure']) && $server['v2_allow_insecure']) {
  96. $array['skip-cert-verify'] = $server['v2_allow_insecure'];
  97. }
  98. return $array;
  99. }
  100. public static function buildTrojan(array $server): array
  101. {
  102. $array = [
  103. 'name' => $server['name'],
  104. 'type' => 'trojan',
  105. 'server' => $server['host'],
  106. 'port' => $server['port'],
  107. 'password' => $server['passwd'],
  108. 'udp' => $server['udp'],
  109. ];
  110. if (isset($server['allow_insecure'])) {
  111. $array['skip-cert-verify'] = $server['allow_insecure'];
  112. }
  113. return $array;
  114. }
  115. public static function buildHysteria2(array $server): ?array
  116. {
  117. if (isset($server['obfs'])) {
  118. return null;
  119. }
  120. $array = [
  121. 'name' => $server['name'],
  122. 'type' => 'hysteria2',
  123. 'server' => $server['host'],
  124. 'port' => $server['port'],
  125. 'auth' => $server['passwd'],
  126. 'fast-open' => true,
  127. 'udp' => $server['udp'] ?? true,
  128. 'sni' => $server['host'],
  129. ];
  130. if (isset($server['ports'])) {
  131. $array['ports'] = $server['ports'];
  132. }
  133. if (isset($server['allow_insecure'])) {
  134. $array['skip-cert-verify'] = $server['allow_insecure'];
  135. }
  136. // 添加端口跳跃功能
  137. if (isset($server['hop_interval']) && $server['hop_interval']) {
  138. $array['hop-interval'] = $server['hop_interval'];
  139. }
  140. return $array;
  141. }
  142. }