build-sgmodule-always-realip.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import path from 'node:path';
  2. import { task } from './trace';
  3. import { compareAndWriteFile } from './lib/create-file';
  4. import { DIRECTS, LANS } from '../Source/non_ip/direct';
  5. import * as yaml from 'yaml';
  6. import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR } from './constants/dir';
  7. import { appendArrayInPlace } from './lib/append-array-in-place';
  8. const HOSTNAMES = [
  9. // Network Detection, Captive Portal
  10. '*.msftncsi.com',
  11. '*.msftconnecttest.com',
  12. 'network-test.debian.org',
  13. 'detectportal.firefox.com',
  14. // Handle SNAT conversation properly
  15. '*.srv.nintendo.net',
  16. '*.stun.playstation.net',
  17. 'xbox.*.microsoft.com',
  18. '*.xboxlive.com',
  19. '*.turn.twilio.com',
  20. '*.stun.twilio.com',
  21. // 'stun.syncthing.net',
  22. 'stun.*',
  23. 'controlplane.tailscale.com',
  24. // NTP
  25. 'time.*.com', 'time.*.gov, time.*.edu.cn, time.*.apple.com', 'time?.*.com', 'ntp.*.com', 'ntp?.*.com', '*.time.edu.cn', '*.ntp.org.cn', '*.pool.ntp.org', 'time*.cloud.tencent.com', 'ntp?.aliyun.com',
  26. // QQ Login
  27. 'localhost.ptlogin2.qq.com',
  28. 'localhost.sec.qq.com',
  29. 'localhost.work.weixin.qq.com',
  30. // Microsoft Auto Discovery
  31. '*PDC._msDCS*',
  32. '*DC._msDCS*',
  33. '*GC._msDCS*',
  34. // Misc,
  35. '*.battlenet.com.cn',
  36. '*.blzstatic.cn',
  37. '*.battlenet.com'
  38. ];
  39. export const buildAlwaysRealIPModule = task(require.main === module, __filename)(async (span) => {
  40. // Intranet, Router Setup, and mant more
  41. const dataset = [Object.entries(DIRECTS), Object.entries(LANS)];
  42. const surge = dataset.flatMap(data => data.flatMap(([, { domains }]) => domains.flatMap((domain) => {
  43. switch (domain[0]) {
  44. case '+':
  45. return [`*.${domain.slice(1)}`];
  46. case '$':
  47. return [domain.slice(1)];
  48. default:
  49. return [domain, `*.${domain}`];
  50. }
  51. })));
  52. return Promise.all([
  53. compareAndWriteFile(
  54. span,
  55. [
  56. '#!name=[Sukka] Always Real IP Plus',
  57. `#!desc=Last Updated: ${new Date().toISOString()}`,
  58. '',
  59. '[General]',
  60. `always-real-ip = %APPEND% ${HOSTNAMES.concat(surge).join(', ')}`
  61. ],
  62. path.resolve(OUTPUT_MODULES_DIR, 'sukka_common_always_realip.sgmodule')
  63. ),
  64. compareAndWriteFile(
  65. span,
  66. yaml.stringify(
  67. {
  68. dns: {
  69. 'fake-ip-filter': appendArrayInPlace(
  70. /** clash */
  71. dataset.flatMap(data => data.flatMap(([, { domains }]) => domains.map((domain) => `+.${domain}`))),
  72. HOSTNAMES
  73. )
  74. }
  75. },
  76. { version: '1.1' }
  77. ).split('\n'),
  78. path.join(OUTPUT_INTERNAL_DIR, 'clash_fake_ip_filter.yaml')
  79. )
  80. ]);
  81. });