dns.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { z } from 'zod';
  2. import { PortSchema } from '@/schemas/primitives';
  3. export const DnsQueryStrategySchema = z.enum(['UseIP', 'UseIPv4', 'UseIPv6', 'UseSystem']);
  4. export type DnsQueryStrategy = z.infer<typeof DnsQueryStrategySchema>;
  5. const DnsHostValueSchema = z.union([z.string(), z.array(z.string())]);
  6. export const DnsHostsSchema = z.record(z.string(), DnsHostValueSchema);
  7. export type DnsHosts = z.infer<typeof DnsHostsSchema>;
  8. export function isEncryptedDnsAddress(address: string): boolean {
  9. return /^(https|https\+local|h2c|h2c\+local|quic\+local):\/\//i.test(address);
  10. }
  11. export const DnsServerObjectInnerSchema = z.object({
  12. address: z.string(),
  13. port: PortSchema.optional(),
  14. domains: z.array(z.string()).optional(),
  15. expectedIPs: z.array(z.string()).optional(),
  16. unexpectedIPs: z.array(z.string()).optional(),
  17. skipFallback: z.boolean().optional(),
  18. finalQuery: z.boolean().optional(),
  19. tag: z.string().optional(),
  20. clientIP: z.string().optional(),
  21. queryStrategy: DnsQueryStrategySchema.optional(),
  22. disableCache: z.boolean().optional(),
  23. timeoutMs: z.number().int().min(0).default(4000),
  24. serveStale: z.boolean().optional(),
  25. serveExpiredTTL: z.number().int().min(0).optional(),
  26. });
  27. export const DnsServerObjectSchema = z
  28. .preprocess((val) => {
  29. if (typeof val !== 'object' || val === null || Array.isArray(val)) return val;
  30. const v = val as Record<string, unknown>;
  31. if (v.expectIPs && !v.expectedIPs) {
  32. return { ...v, expectedIPs: v.expectIPs };
  33. }
  34. return val;
  35. }, DnsServerObjectInnerSchema)
  36. .transform((v) => {
  37. if (v.port === undefined && !isEncryptedDnsAddress(v.address)) {
  38. return { ...v, port: 53 };
  39. }
  40. return v;
  41. });
  42. export type DnsServerObject = z.infer<typeof DnsServerObjectSchema>;
  43. export const DnsServerEntrySchema = z.union([z.string(), DnsServerObjectSchema]);
  44. export type DnsServerEntry = z.infer<typeof DnsServerEntrySchema>;
  45. export const DnsObjectSchema = z.object({
  46. tag: z.string().optional(),
  47. hosts: DnsHostsSchema.optional(),
  48. servers: z.array(DnsServerEntrySchema).optional(),
  49. clientIp: z.string().optional(),
  50. queryStrategy: DnsQueryStrategySchema.default('UseIP'),
  51. disableCache: z.boolean().default(false),
  52. disableFallback: z.boolean().default(false),
  53. disableFallbackIfMatch: z.boolean().default(false),
  54. enableParallelQuery: z.boolean().default(false),
  55. useSystemHosts: z.boolean().default(false),
  56. serveStale: z.boolean().default(false),
  57. serveExpiredTTL: z.number().int().min(0).default(0),
  58. });
  59. export type DnsObject = z.infer<typeof DnsObjectSchema>;