ClashMeta.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. namespace App\Utils\Clients\Formatters;
  3. use App\Utils\Library\Templates\Formatter;
  4. class ClashMeta implements Formatter
  5. {
  6. // https://wiki.metacubex.one/config/proxies/
  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-ctr', 'aes-192-ctr', 'aes-256-ctr', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb', 'aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm', 'aes-128-ccm', 'aes-192-ccm', 'aes-256-ccm', 'aes-128-gcm-siv', 'aes-256-gcm-siv', 'chacha20-ietf', 'chacha20', 'xchacha20', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305', 'chacha8-ietf-poly1305', 'xchacha8-ietf-poly1305', '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', '2022-blake3-chacha20-poly1305', 'lea-128-gcm', 'lea-192-gcm', 'lea-256-gcm', 'rabbit128-poly1305', 'aegis-128l', 'aegis-256', 'aez-384', 'deoxys-ii-256-128', 'rc4-md5', 'none'];
  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-ctr', 'aes-192-ctr', 'aes-256-ctr', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb', 'rc4-md5', 'chacha20', 'chacha20-ietf', '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. 'protocol' => $server['protocol'],
  54. 'obfs-param' => $server['obfs_param'] ?? '',
  55. 'protocol-param' => $server['protocol_param'] ?? '',
  56. 'udp' => $server['udp'],
  57. ];
  58. }
  59. public static function buildVmess(array $server): ?array
  60. {
  61. $supportedMethods = ['auto', 'none', 'zero', 'aes-128-gcm', 'chacha20-poly1305'];
  62. $supportedNetworks = ['ws', 'h2', 'http', 'grpc', 'tcp'];
  63. if (! in_array($server['method'], $supportedMethods, true) || ($server['v2_net'] && ! in_array($server['v2_net'], $supportedNetworks, true))) {
  64. return null;
  65. }
  66. $array = [
  67. 'name' => $server['name'],
  68. 'type' => 'vmess',
  69. 'server' => $server['host'],
  70. 'port' => $server['port'],
  71. 'uuid' => $server['uuid'],
  72. 'alterId' => $server['v2_alter_id'],
  73. 'cipher' => $server['method'],
  74. 'udp' => $server['udp'],
  75. ];
  76. if (isset($server['v2_tls']) && $server['v2_tls']) {
  77. $array['tls'] = true;
  78. $array['servername'] = $server['v2_host'];
  79. }
  80. $array['network'] = $server['v2_net'];
  81. if (isset($server['v2_net']) && $server['v2_net'] === 'ws') {
  82. $array['ws-opts'] = [];
  83. $array['ws-opts']['path'] = $server['v2_path'];
  84. if ($server['v2_host']) {
  85. $array['ws-opts']['headers'] = ['Host' => $server['v2_host']];
  86. }
  87. $array['ws-path'] = $server['v2_path'];
  88. if ($server['v2_host']) {
  89. $array['ws-headers'] = ['Host' => $server['v2_host']];
  90. }
  91. }
  92. return $array;
  93. }
  94. public static function buildTrojan(array $server): array
  95. {
  96. $array = [
  97. 'name' => $server['name'],
  98. 'type' => 'trojan',
  99. 'server' => $server['host'],
  100. 'port' => $server['port'],
  101. 'password' => $server['passwd'],
  102. 'udp' => $server['udp'],
  103. ];
  104. if (isset($server['sni'])) {
  105. $array['sni'] = $server['sni'];
  106. }
  107. if (isset($server['allow_insecure'])) {
  108. $array['skip-cert-verify'] = $server['allow_insecure'];
  109. }
  110. return $array;
  111. }
  112. public static function buildHysteria2(array $server): array
  113. {
  114. $array = [
  115. 'name' => $server['name'],
  116. 'type' => 'hysteria2',
  117. 'server' => $server['host'],
  118. 'port' => $server['port'],
  119. 'password' => $server['passwd'],
  120. 'udp' => $server['udp'],
  121. 'sni' => $server['host'],
  122. ];
  123. if (isset($server['ports']) && $server['ports']) {
  124. $array['ports'] = $server['ports'];
  125. }
  126. if (isset($server['obfs']) && $server['obfs']) {
  127. $array['obfs'] = $server['obfs'];
  128. $array['obfs-password'] = $server['obfs_param'];
  129. }
  130. if (isset($server['allow_insecure']) && $server['allow_insecure']) {
  131. $array['skip-cert-verify'] = $server['allow_insecure'];
  132. }
  133. return $array;
  134. }
  135. }