singbox.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { isProbablyIpv4, isProbablyIpv6 } from './is-fast-ip';
  2. const unsupported = Symbol('unsupported');
  3. function toNumberTuple<T extends string>(key: T, value: string): [T, number] | null {
  4. const tmp = Number(value);
  5. return Number.isNaN(tmp) ? null : [key, tmp];
  6. }
  7. // https://sing-box.sagernet.org/configuration/rule-set/source-format/
  8. export const PROCESSOR: Record<string, ((raw: string, type: string, value: string) => [key: keyof SingboxHeadlessRule, value: Required<SingboxHeadlessRule>[keyof SingboxHeadlessRule][number]] | null) | typeof unsupported> = {
  9. 'IP-ASN': unsupported,
  10. 'SRC-IP': (_1, _2, value) => {
  11. if (value.includes('/')) {
  12. return ['source_ip_cidr', value];
  13. }
  14. if (isProbablyIpv4(value)) {
  15. return ['source_ip_cidr', value + '/32'];
  16. }
  17. if (isProbablyIpv6(value)) {
  18. return ['source_ip_cidr', value + '/128'];
  19. }
  20. return null;
  21. },
  22. 'SRC-IP-CIDR': (_1, _2, value) => ['source_ip_cidr', value.endsWith(',no-resolve') ? value.slice(0, -11) : value],
  23. 'SRC-PORT': (_1, _2, value) => toNumberTuple('source_port', value),
  24. 'DST-PORT': (_1, _2, value) => toNumberTuple('port', value),
  25. 'PROCESS-NAME': (_1, _2, value) => ((value.includes('/') || value.includes('\\')) ? ['process_path', value] : ['process_name', value]),
  26. // 'PROCESS-PATH': (_1, _2, value) => ['process_path', value],
  27. 'DEST-PORT': (_1, _2, value) => toNumberTuple('port', value),
  28. 'IN-PORT': (_1, _2, value) => toNumberTuple('source_port', value),
  29. 'URL-REGEX': unsupported,
  30. 'USER-AGENT': unsupported
  31. };
  32. interface SingboxHeadlessRule {
  33. domain?: string[],
  34. domain_suffix?: string[],
  35. domain_keyword?: string[],
  36. domain_regex?: string[],
  37. source_ip_cidr?: string[],
  38. ip_cidr?: string[],
  39. source_port?: number[],
  40. source_port_range?: string[],
  41. port?: number[],
  42. port_range?: string[],
  43. process_name?: string[],
  44. process_path?: string[]
  45. }
  46. export interface SingboxSourceFormat {
  47. version: 2 | number & {},
  48. rules: SingboxHeadlessRule[]
  49. }