mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 09:10:35 +08:00
Feat: sukka_local_dns_mapping.sgmodule now uses new rule-set syntax
This commit is contained in:
parent
8d5da9776a
commit
6858cd63b4
@ -10,7 +10,7 @@ import { SHARED_DESCRIPTION } from './constants/description';
|
||||
import { createMemoizedPromise } from './lib/memo-promise';
|
||||
import * as yaml from 'yaml';
|
||||
import { appendArrayInPlace } from './lib/append-array-in-place';
|
||||
import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR, SOURCE_DIR } from './constants/dir';
|
||||
import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR, OUTPUT_MODULES_RULES_DIR, SOURCE_DIR } from './constants/dir';
|
||||
import { RulesetOutput } from './lib/create-file';
|
||||
|
||||
export function createGetDnsMappingRule(allowWildcard: boolean) {
|
||||
@ -78,7 +78,7 @@ export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(a
|
||||
export const buildDomesticRuleset = task(require.main === module, __filename)(async (span) => {
|
||||
const [domestics, directs, lans] = await getDomesticAndDirectDomainsRulesetPromise();
|
||||
|
||||
const dataset: DNSMapping[] = ([DOH_BOOTSTRAP, DOMESTICS, DIRECTS] as const).flatMap(Object.values);
|
||||
const dataset: Array<[name: string, DNSMapping]> = ([DOH_BOOTSTRAP, DOMESTICS, DIRECTS, LAN] as const).flatMap(Object.entries);
|
||||
|
||||
return Promise.all([
|
||||
new RulesetOutput(span, 'domestic', 'non_ip')
|
||||
@ -108,6 +108,41 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as
|
||||
])
|
||||
.addFromRuleset(lans)
|
||||
.write(),
|
||||
|
||||
...dataset.map(([name, { ruleset, domains }]) => {
|
||||
if (!ruleset) {
|
||||
return;
|
||||
}
|
||||
|
||||
const output = new RulesetOutput(span, name.toLowerCase(), 'sukka_local_dns_mapping').withTitle(`Sukka's Ruleset - Local DNS Mapping (${name})`).withDescription([
|
||||
...SHARED_DESCRIPTION,
|
||||
'',
|
||||
'This is an internal rule that is only referenced by sukka_local_dns_mapping.sgmodule',
|
||||
'Do not use this file in your Rule section, all rules are included in non_ip/domestic.conf already.'
|
||||
]);
|
||||
|
||||
domains.forEach((domain) => {
|
||||
switch (domain[0]) {
|
||||
case '$':
|
||||
output.addDomain(domain.slice(1));
|
||||
break;
|
||||
case '+':
|
||||
output.addDomainSuffix(domain.slice(1));
|
||||
break;
|
||||
default:
|
||||
output.addDomainSuffix(domain);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return output.write({
|
||||
surge: true,
|
||||
clash: false,
|
||||
singbox: false,
|
||||
surgeDir: OUTPUT_MODULES_RULES_DIR
|
||||
});
|
||||
}),
|
||||
|
||||
compareAndWriteFile(
|
||||
span,
|
||||
[
|
||||
@ -119,26 +154,31 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as
|
||||
// I use an object to deduplicate the domains
|
||||
// Otherwise I could just construct an array directly
|
||||
dataset.reduce<Record<string, string>>((acc, cur) => {
|
||||
const { domains, dns, hosts } = cur;
|
||||
const ruleset_name = cur[0].toLowerCase();
|
||||
const { domains, dns, hosts, ruleset } = cur[1];
|
||||
|
||||
Object.entries(hosts).forEach(([dns, ips]) => {
|
||||
acc[dns] ||= ips.join(', ');
|
||||
});
|
||||
|
||||
domains.forEach((domain) => {
|
||||
switch (domain[0]) {
|
||||
case '$':
|
||||
acc[domain.slice(1)] ||= `server:${dns}`;
|
||||
break;
|
||||
case '+':
|
||||
acc[`*.${domain.slice(1)}`] ||= `server:${dns}`;
|
||||
break;
|
||||
default:
|
||||
acc[domain] ||= `server:${dns}`;
|
||||
acc[`*.${domain}`] ||= `server:${dns}`;
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (ruleset) {
|
||||
acc[`RULE-SET:https://ruleset.skk.moe/Modules/Rules/sukka_local_dns_mapping/${ruleset_name}.conf`] ||= `server:${dns}`;
|
||||
} else {
|
||||
domains.forEach((domain) => {
|
||||
switch (domain[0]) {
|
||||
case '$':
|
||||
acc[domain.slice(1)] ||= `server:${dns}`;
|
||||
break;
|
||||
case '+':
|
||||
acc[`*.${domain.slice(1)}`] ||= `server:${dns}`;
|
||||
break;
|
||||
default:
|
||||
acc[domain] ||= `server:${dns}`;
|
||||
acc[`*.${domain}`] ||= `server:${dns}`;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
@ -153,7 +193,7 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as
|
||||
dns: { 'nameserver-policy': Record<string, string | string[]> },
|
||||
hosts: Record<string, string>
|
||||
}>((acc, cur) => {
|
||||
const { domains, dns, ...rest } = cur;
|
||||
const { domains, dns, ...rest } = cur[1];
|
||||
domains.forEach((domain) => {
|
||||
let domainWildcard = domain;
|
||||
if (domain[0] === '$') {
|
||||
|
||||
@ -11,5 +11,6 @@ export const OUTPUT_SURGE_DIR = path.join(PUBLIC_DIR, 'List');
|
||||
export const OUTPUT_CLASH_DIR = path.resolve(PUBLIC_DIR, 'Clash');
|
||||
export const OUTPUT_SINGBOX_DIR = path.resolve(PUBLIC_DIR, 'sing-box');
|
||||
export const OUTPUT_MODULES_DIR = path.resolve(PUBLIC_DIR, 'Modules');
|
||||
export const OUTPUT_MODULES_RULES_DIR = path.resolve(OUTPUT_MODULES_DIR, 'Rules');
|
||||
export const OUTPUT_INTERNAL_DIR = path.resolve(PUBLIC_DIR, 'Internal');
|
||||
export const OUTPUT_MOCK_DIR = path.resolve(PUBLIC_DIR, 'Mock');
|
||||
|
||||
@ -34,7 +34,7 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
|
||||
protected destPort = new Set<string>();
|
||||
|
||||
protected otherRules: string[] = [];
|
||||
protected abstract type: 'domainset' | 'non_ip' | 'ip';
|
||||
protected abstract type: 'domainset' | 'non_ip' | 'ip' | (string & {});
|
||||
|
||||
private pendingPromise: Promise<any> | null = null;
|
||||
|
||||
@ -295,13 +295,29 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
|
||||
);
|
||||
}
|
||||
|
||||
write(): Promise<void> {
|
||||
write({
|
||||
surge = true,
|
||||
clash = true,
|
||||
singbox = true,
|
||||
surgeDir = OUTPUT_SURGE_DIR,
|
||||
clashDir = OUTPUT_CLASH_DIR,
|
||||
singboxDir = OUTPUT_SINGBOX_DIR
|
||||
}: {
|
||||
surge?: boolean,
|
||||
clash?: boolean,
|
||||
singbox?: boolean,
|
||||
surgeDir?: string,
|
||||
clashDir?: string,
|
||||
singboxDir?: string
|
||||
} = {}): Promise<void> {
|
||||
return this.done().then(() => this.span.traceChildAsync('write all', async () => {
|
||||
invariant(this.title, 'Missing title');
|
||||
invariant(this.description, 'Missing description');
|
||||
|
||||
const promises = [
|
||||
compareAndWriteFile(
|
||||
const promises: Array<Promise<void>> = [];
|
||||
|
||||
if (surge) {
|
||||
promises.push(compareAndWriteFile(
|
||||
this.span,
|
||||
withBannerArray(
|
||||
this.title,
|
||||
@ -309,9 +325,11 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
|
||||
this.date,
|
||||
this.surge()
|
||||
),
|
||||
path.join(OUTPUT_SURGE_DIR, this.type, this.id + '.conf')
|
||||
),
|
||||
compareAndWriteFile(
|
||||
path.join(surgeDir, this.type, this.id + '.conf')
|
||||
));
|
||||
}
|
||||
if (clash) {
|
||||
promises.push(compareAndWriteFile(
|
||||
this.span,
|
||||
withBannerArray(
|
||||
this.title,
|
||||
@ -319,14 +337,16 @@ export abstract class RuleOutput<TPreprocessed = unknown> {
|
||||
this.date,
|
||||
this.clash()
|
||||
),
|
||||
path.join(OUTPUT_CLASH_DIR, this.type, this.id + '.txt')
|
||||
),
|
||||
compareAndWriteFile(
|
||||
path.join(clashDir, this.type, this.id + '.txt')
|
||||
));
|
||||
}
|
||||
if (singbox) {
|
||||
promises.push(compareAndWriteFile(
|
||||
this.span,
|
||||
this.singbox(),
|
||||
path.join(OUTPUT_SINGBOX_DIR, this.type, this.id + '.json')
|
||||
)
|
||||
];
|
||||
path.join(singboxDir, this.type, this.id + '.json')
|
||||
));
|
||||
}
|
||||
|
||||
if (this.mitmSgmodule) {
|
||||
const sgmodule = this.mitmSgmodule();
|
||||
|
||||
@ -12,7 +12,7 @@ import { isProbablyIpv4, isProbablyIpv6 } from 'foxts/is-probably-ip';
|
||||
type Preprocessed = [domain: string[], domainSuffix: string[], sortedDomainRules: string[]];
|
||||
|
||||
export class RulesetOutput extends RuleOutput<Preprocessed> {
|
||||
constructor(span: Span, id: string, protected type: 'non_ip' | 'ip') {
|
||||
constructor(span: Span, id: string, protected type: 'non_ip' | 'ip' | (string & {})) {
|
||||
super(span, id);
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ export interface DNSMapping {
|
||||
},
|
||||
/** which also disallows wildcard */
|
||||
realip: boolean,
|
||||
/** should convert to ruleset */
|
||||
ruleset: boolean,
|
||||
dns: string,
|
||||
/**
|
||||
* domain[0]
|
||||
@ -20,6 +22,7 @@ export const DIRECTS = {
|
||||
dns: 'system',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: false,
|
||||
domains: [
|
||||
'securelogin.com.cn',
|
||||
'$captive.apple.com',
|
||||
@ -30,6 +33,7 @@ export const DIRECTS = {
|
||||
dns: 'system',
|
||||
hosts: {},
|
||||
realip: true,
|
||||
ruleset: false,
|
||||
domains: [
|
||||
'+m2m',
|
||||
// '+ts.net', // TailScale Magic DNS
|
||||
@ -47,6 +51,7 @@ export const LAN = {
|
||||
dns: 'system',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'+home',
|
||||
// 'zte.home', // ZTE CPE
|
||||
@ -106,6 +111,7 @@ export const LAN = {
|
||||
localhost: ['127.0.0.1']
|
||||
},
|
||||
realip: true,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'+lan',
|
||||
// 'amplifi.lan',
|
||||
|
||||
@ -5,6 +5,7 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
hosts: {},
|
||||
dns: 'quic://dns.alidns.com:853',
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'uc.cn',
|
||||
// 'ucweb.com', // UC International
|
||||
@ -82,13 +83,18 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
'tanx.com',
|
||||
'hellobike.com',
|
||||
'+hichina.com',
|
||||
'+yunos.com'
|
||||
'+yunos.com',
|
||||
|
||||
// Bilibili Aliyun CDN
|
||||
'$upos-sz-mirrorali.bilivideo.com',
|
||||
'$upos-sz-estgoss.bilivideo.com'
|
||||
]
|
||||
},
|
||||
TENCENT: {
|
||||
hosts: {},
|
||||
dns: 'https://doh.pub/dns-query',
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
// 'dns.pub',
|
||||
// 'doh.pub',
|
||||
@ -144,28 +150,11 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
'+codehub.cn'
|
||||
]
|
||||
},
|
||||
BILIBILI_ALI: {
|
||||
dns: 'quic://dns.alidns.com:853',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
domains: [
|
||||
'$upos-sz-mirrorali.bilivideo.com',
|
||||
'$upos-sz-estgoss.bilivideo.com'
|
||||
]
|
||||
},
|
||||
BILIBILI_BD: {
|
||||
dns: '180.76.76.76',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
domains: [
|
||||
'$upos-sz-mirrorbd.bilivideo.com',
|
||||
'$upos-sz-mirrorbos.bilivideo.com'
|
||||
]
|
||||
},
|
||||
BILIBILI: {
|
||||
dns: 'https://doh.pub/dns-query',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
// '$upos-sz-mirrorcoso1.bilivideo.com', // already included in bilivideo.com
|
||||
// '$upos-sz-estgcos.bilivideo.com', // already included in bilivideo.com, tencent cloud cdn
|
||||
@ -196,6 +185,7 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
dns: 'https://doh.pub/dns-query',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'mi.com',
|
||||
'duokan.com',
|
||||
@ -218,6 +208,7 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
dns: '180.184.2.2',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'bytedance.com',
|
||||
'+bytecdn.cn',
|
||||
@ -271,6 +262,7 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
dns: '180.76.76.76',
|
||||
hosts: {},
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'91.com',
|
||||
'hao123.com',
|
||||
@ -295,13 +287,18 @@ export const DOMESTICS: Record<string, DNSMapping> = {
|
||||
'+bdydns.com',
|
||||
'+jomoxc.com', // Baidu PCDN, of sort
|
||||
'+duapp.com',
|
||||
'+antpcdn.com' // Baidu PCDN
|
||||
'+antpcdn.com', // Baidu PCDN
|
||||
|
||||
// Bilibili Baidu CDN
|
||||
'$upos-sz-mirrorbd.bilivideo.com',
|
||||
'$upos-sz-mirrorbos.bilivideo.com'
|
||||
]
|
||||
},
|
||||
QIHOO360: {
|
||||
hosts: {},
|
||||
dns: 'https://doh.360.cn/dns-query',
|
||||
realip: false,
|
||||
ruleset: true,
|
||||
domains: [
|
||||
'+qhimg.com',
|
||||
'+qhimgs.com',
|
||||
@ -350,6 +347,7 @@ export const DOH_BOOTSTRAP: Record<string, DNSMapping> = {
|
||||
'dns.alidns.com': ['223.5.5.5', '223.6.6.6', '2400:3200:baba::1', '2400:3200::1']
|
||||
},
|
||||
realip: false,
|
||||
ruleset: false,
|
||||
dns: 'quic://223.5.5.5:853',
|
||||
domains: [
|
||||
'$dns.alidns.com'
|
||||
@ -362,6 +360,7 @@ export const DOH_BOOTSTRAP: Record<string, DNSMapping> = {
|
||||
// 'dns.pub': ['120.53.53.53', '1.12.12.12']
|
||||
},
|
||||
realip: false,
|
||||
ruleset: false,
|
||||
dns: 'https://1.12.12.12/dns-query',
|
||||
domains: [
|
||||
// '$dot.pub',
|
||||
@ -382,6 +381,7 @@ export const DOH_BOOTSTRAP: Record<string, DNSMapping> = {
|
||||
// dot.360.net CNAME dns.360.net
|
||||
},
|
||||
realip: false,
|
||||
ruleset: false,
|
||||
// Surge only supports UDP 53 or Hosts as the bootstrap server of domain DoH
|
||||
dns: '101.198.198.198', // 'https://101.198.198.198/dns-query', // https://101.198.199.200/dns-query
|
||||
domains: [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user