diff --git a/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts b/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts index ee68e3c1..6a24cccf 100644 --- a/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts +++ b/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts @@ -1,6 +1,7 @@ // @ts-check import path from 'node:path'; import { DOMESTICS, DOH_BOOTSTRAP, AdGuardHomeDNSMapping } from '../Source/non_ip/domestic'; +import { DOMESTIC_CDN } from '../Source/non_ip/domestic_cdn'; import { DIRECTS, HOSTS, LAN } from '../Source/non_ip/direct'; import type { DNSMapping } from '../Source/non_ip/direct'; import { fetchRemoteTextLines, readFileIntoProcessedArray } from './lib/fetch-text-by-line'; @@ -53,6 +54,17 @@ export function createGetDnsMappingRule(allowWildcard: boolean) { }; } +export const getDomesticCdnDomainsRulesetPromise = once(async () => { + const domesticCdn = await readFileIntoProcessedArray(path.join(SOURCE_DIR, 'non_ip/domestic_cdn.conf')); + const getDnsMappingRuleWithWildcard = createGetDnsMappingRule(true); + + Object.values(DOMESTIC_CDN).forEach(({ domains }) => { + appendArrayInPlace(domesticCdn, domains.flatMap(getDnsMappingRuleWithWildcard)); + }); + + return domesticCdn; +}); + export const getDomesticAndDirectDomainsRulesetPromise = once(async () => { const domestics = await readFileIntoProcessedArray(path.join(SOURCE_DIR, 'non_ip/domestic.conf')); const directs = await readFileIntoProcessedArray(path.resolve(SOURCE_DIR, 'non_ip/direct.conf')); @@ -66,6 +78,9 @@ export const getDomesticAndDirectDomainsRulesetPromise = once(async () => { }); }); + // Keep legacy subscriptions inclusive of the CDN exceptions. + appendArrayInPlace(domestics, await getDomesticCdnDomainsRulesetPromise()); + Object.values(DIRECTS).forEach(({ domains }) => { appendArrayInPlace(directs, domains.flatMap(getDnsMappingRuleWithWildcard)); }); @@ -81,8 +96,16 @@ export const getDomesticAndDirectDomainsRulesetPromise = once(async () => { export const buildDomesticRuleset = task(require.main === module, __filename)(async (span) => { const [domestics, directs, lans] = await getDomesticAndDirectDomainsRulesetPromise(); + const domesticCdn = await getDomesticCdnDomainsRulesetPromise(); - const dataset: Array<[name: string, DNSMapping]> = ([DOH_BOOTSTRAP, DOMESTICS, DIRECTS, LAN, HOSTS] as const).flatMap(Object.entries); + // Preserve existing provider IDs, and namespace CDN providers so the same + // provider can appear in both sources without overwriting its ruleset or DNS policy. + const domesticMappings = Object.entries(DOMESTIC_CDN).reduce>((mappings, [name, mapping]) => { + mappings[`DOMESTIC_CDN_${name}`] = mapping; + return mappings; + }, { ...DOMESTICS }); + + const dataset: Array<[name: string, mapping: DNSMapping]> = ([DOH_BOOTSTRAP, domesticMappings, DIRECTS, LAN, HOSTS] as const).flatMap(Object.entries); return Promise.all([ new RulesetOutput(span, 'domestic', 'non_ip') @@ -94,6 +117,17 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as ) .addFromRuleset(domestics) .write(), + new RulesetOutput(span, 'domestic_cdn', 'non_ip') + .withTitle('Sukka\'s Ruleset - Domestic CDN Domains') + .appendDescription( + SHARED_DESCRIPTION, + '', + 'This file contains CDN domains of domestic services that should use DIRECT both in China and abroad.', + 'Place this ruleset before domestic when routing other domestic traffic back to China.', + 'All entries are also included in the domestic ruleset.' + ) + .addFromRuleset(domesticCdn) + .write(), new RulesetOutput(span, 'direct', 'non_ip') .withTitle('Sukka\'s Ruleset - Direct Rules') .appendDescription( @@ -328,7 +362,7 @@ export const buildDomesticRuleset = task(require.main === module, __filename)(as 'https://doh.pub/dns-query', 'https://dns.alidns.com/dns-query', '[//]udp://10.10.1.1:53', - ...(([DOMESTICS, DIRECTS, LAN, HOSTS] as const).flatMap(Object.values) as DNSMapping[]).flatMap(({ domains, dns: _dns }) => domains.flatMap((domain) => { + ...(([domesticMappings, DIRECTS, LAN, HOSTS] as const).flatMap(Object.values) as DNSMapping[]).flatMap(({ domains, dns: _dns }) => domains.flatMap((domain) => { if (!_dns) { return []; } diff --git a/Build/build-sgmodule-always-realip.ts b/Build/build-sgmodule-always-realip.ts index 5a26f693..9c103c4e 100644 --- a/Build/build-sgmodule-always-realip.ts +++ b/Build/build-sgmodule-always-realip.ts @@ -4,6 +4,7 @@ import { compareAndWriteFile } from './lib/create-file'; import { DIRECTS, LAN } from '../Source/non_ip/direct'; import type { DNSMapping } from '../Source/non_ip/direct'; import { DOMESTICS, DOH_BOOTSTRAP } from '../Source/non_ip/domestic'; +import { DOMESTIC_CDN } from '../Source/non_ip/domestic_cdn'; import * as yaml from 'yaml'; import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR } from './constants/dir'; import { appendArrayInPlace } from 'foxts/append-array-in-place'; @@ -61,7 +62,7 @@ export const buildAlwaysRealIPModule = task(require.main === module, __filename) ]); // Intranet, Router Setup, and mant more - const dataset = [DIRECTS, LAN, DOMESTICS, DOH_BOOTSTRAP].reduce((acc, item) => { + const dataset = [DIRECTS, LAN, DOMESTICS, DOMESTIC_CDN, DOH_BOOTSTRAP].reduce((acc, item) => { Object.values(item).forEach((i: DNSMapping) => { if (i.realip) { acc.push(i); diff --git a/Build/validate-domestic.ts b/Build/validate-domestic.ts index ff8a09d9..d23abcf0 100644 --- a/Build/validate-domestic.ts +++ b/Build/validate-domestic.ts @@ -8,6 +8,7 @@ import { HostnameSmolTrie } from 'hntrie/smol'; import { domainToASCII } from 'node:url'; import tldts from 'tldts-experimental'; import { DOMESTICS } from '../Source/non_ip/domestic'; +import { DOMESTIC_CDN } from '../Source/non_ip/domestic_cdn'; export async function parseDomesticList() { const allChinaDomains = new Set(await parseFelixDnsmasqFromResp(await $$fetch('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/accelerated-domains.china.conf'))); @@ -27,6 +28,10 @@ export async function parseDomesticList() { const callback = (domain: string, includeAllSubdomain: boolean) => resultTrie.whitelist(includeAllSubdomain ? '.' + domain : domain); // await Promise.all([ + await runAgainstSourceFile( + path.resolve(SOURCE_DIR, 'non_ip/domestic_cdn.conf'), + callback + ); await runAgainstSourceFile( path.resolve(SOURCE_DIR, 'non_ip/domestic.conf'), callback @@ -36,7 +41,7 @@ export async function parseDomesticList() { callback ); - Object.values(DOMESTICS).forEach(domestic => { + [DOMESTICS, DOMESTIC_CDN].flatMap(item => Object.values(item)).forEach(domestic => { domestic.domains.forEach(domain => { switch (domain[0]) { case '+': diff --git a/README.md b/README.md index 02216c30..b8039d35 100644 --- a/README.md +++ b/README.md @@ -797,7 +797,65 @@ rules: - RULE-SET,lan_ip,DIRECT ``` -#### Misc +#### 中国大陆常见服务 + +- 人工维护 + +**Surge** + +```ini +# 中国大陆境内:仅需配置 domestic +# Non IP +RULE-SET,https://ruleset.skk.moe/List/non_ip/domestic.conf,DIRECT + +# IP +RULE-SET,https://ruleset.skk.moe/List/ip/domestic.conf,DIRECT +``` + +```ini +# 其余国家和地区:domestic_cdn 优先直连,domestic 使用代理 +# Non IP +RULE-SET,https://ruleset.skk.moe/List/non_ip/domestic_cdn.conf,DIRECT +RULE-SET,https://ruleset.skk.moe/List/non_ip/domestic.conf,Proxy + +# IP +RULE-SET,https://ruleset.skk.moe/List/ip/domestic.conf,Proxy +``` + +**Mihomo** + +在下方 `domestic_non_ip` 等 `rule-providers` 的基础上添加: + +```yaml +rule-providers: + domestic_cdn_non_ip: + type: http + behavior: classical + format: text + interval: 43200 + url: https://ruleset.skk.moe/Clash/non_ip/domestic_cdn.txt + path: ./sukkaw_ruleset/domestic_cdn_non_ip.txt + domestic_ip: + type: http + behavior: classical + format: text + interval: 43200 + url: https://ruleset.skk.moe/Clash/ip/domestic.txt + path: ./sukkaw_ruleset/domestic_ip.txt +rules: + - RULE-SET,domestic_cdn_non_ip,DIRECT + - RULE-SET,domestic_non_ip,Back To China Proxy + - MATCH,DIRECT +``` + + +```yaml +# IP +rules: + - RULE-SET,domestic_ip,[Replace with your policy] +``` + +#### 其他国家和地区常见服务、需直连的服务 - 人工维护 @@ -805,27 +863,15 @@ rules: ```ini # Non IP -RULE-SET,https://ruleset.skk.moe/List/non_ip/domestic.conf,[Replace with your policy] RULE-SET,https://ruleset.skk.moe/List/non_ip/direct.conf,[Replace with your policy] RULE-SET,https://ruleset.skk.moe/List/non_ip/global.conf,[Replace with your policy] ``` -```ini -# IP -RULE-SET,https://ruleset.skk.moe/List/ip/domestic.conf,[Replace with your policy] -``` - **Mihomo** ```yaml rule-providers: domestic_non_ip: - type: http - behavior: classical - format: text - interval: 43200 - url: https://ruleset.skk.moe/Clash/non_ip/domestic.txt - path: ./sukkaw_ruleset/domestic_non_ip.txt direct_non_ip: type: http behavior: classical @@ -840,29 +886,15 @@ rule-providers: interval: 43200 url: https://ruleset.skk.moe/Clash/non_ip/global.txt path: ./sukkaw_ruleset/global_non_ip.txt - domestic_ip: - type: http - behavior: classical - format: text - interval: 43200 - url: https://ruleset.skk.moe/Clash/ip/domestic.txt - path: ./sukkaw_ruleset/domestic_ip.txt ``` ```yaml # Non IP rules: - - RULE-SET,domestic_non_ip,[Replace with your policy] - RULE-SET,direct_non_ip,[Replace with your policy] - RULE-SET,global_non_ip,[Replace with your policy] ``` -```yaml -# IP -rules: - - RULE-SET,domestic_ip,[Replace with your policy] -``` - #### chnroute CIDR - 自动生成 diff --git a/Source/non_ip/domestic.ts b/Source/non_ip/domestic.ts index c0d692e2..ea8de92b 100644 --- a/Source/non_ip/domestic.ts +++ b/Source/non_ip/domestic.ts @@ -188,7 +188,6 @@ export const DOMESTICS: Record = { '+bilivideo.com', '+bilivideo.cn', '+bilivideo.net', - '+hdslb.com', '+biliimg.com', '+biliapi.com', '+biliapi.net', diff --git a/Source/non_ip/domestic_cdn.conf b/Source/non_ip/domestic_cdn.conf new file mode 100644 index 00000000..8e1f633f --- /dev/null +++ b/Source/non_ip/domestic_cdn.conf @@ -0,0 +1,14 @@ +# $ custom_build_script + +# CDN domains of domestic services that should use DIRECT both in China and abroad. +# Match this ruleset before domestic when routing other domestic traffic back to China. +# The build script also includes these rules in the legacy domestic output. + + +# >> Bilibili +# Bilibili CDN +DOMAIN-SUFFIX,hdslb.com + +# >> NetEase +# NetEase Music CDN +DOMAIN-SUFFIX,music.126.net diff --git a/Source/non_ip/domestic_cdn.ts b/Source/non_ip/domestic_cdn.ts new file mode 100644 index 00000000..47e0d552 --- /dev/null +++ b/Source/non_ip/domestic_cdn.ts @@ -0,0 +1,5 @@ +import type { DNSMapping } from './direct'; + +// CDN domains of domestic services that should use DIRECT both in China and abroad. +// These domains are also included in the legacy domestic output by the build script. +export const DOMESTIC_CDN: Record = {};