'use strict';const require$$0=require('node:path'),fetchTextByLine=require('./fetch-text-by-line.YY5b5610.cjs'),createFile=require('./create-file.loOMbJEN.cjs'),index=require('./index.B8Uk9n3v.cjs'),base=require('./base.C13YY5P3.cjs'),memoPromise=require('./memo-promise.BbOsVeGo.cjs'),require$$8=require('yaml'),fetchRetry=require('./fetch-retry.D06uBUaW.cjs'),ruleset=require('./ruleset.iYH0XOC1.cjs');var buildDomesticDirectLanRulesetDnsMappingModule = {exports: {}};var domestic = {};var hasRequiredDomestic; function requireDomestic () { if (hasRequiredDomestic) return domestic; hasRequiredDomestic = 1; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { AdGuardHomeDNSMapping: function() { return AdGuardHomeDNSMapping; }, DOH_BOOTSTRAP: function() { return DOH_BOOTSTRAP; }, DOMESTICS: function() { return DOMESTICS; } }); const DOMESTICS = { ALIBABA: { hosts: {}, dns: 'quic://dns.alidns.com:853', realip: false, ruleset: true, domains: [ 'uc.cn', // 'ucweb.com', // UC International 'alibaba.com', '+alicdn.com', '+ialicdn.com', '+myalicdn.com', '+alidns.com', '+aliimg.com', 'aliyun.com', '+aliyuncs.com', '+alikunlun.com', '+alikunlun.net', '+cdngslb.com', 'alipay.com', 'alipay.cn', 'alipay.com.cn', '+alipayobjects.com', 'alibaba-inc.com', '+alibabausercontent.com', '+alibabadns.com', 'alibabachengdun.com', 'alicloudccp.com', 'alipan.com', 'aliyundrive.com', 'aliyundrive.net', 'cainiao.com', 'cainiao.com.cn', 'cainiaoyizhan.com', 'guoguo-app.com', 'etao.com', 'yitao.com', '1688.com', 'amap.com', 'gaode.com', 'autonavi.com', 'dingtalk.com', 'mxhichina.com', 'soku.com', 'tb.cn', 'taobao.com', '+taobaocdn.com', '+tbcache.com', 'tmall.com', // 'tmall.hk', 'goofish.com', 'xiami.com', 'xiami.net', '+ykimg.com', 'youku.com', 'tudou.com', '+cibntv.net', 'ele.me', '+elemecdn.com', 'feizhu.com', 'taopiaopiao.com', 'fliggy.com', 'koubei.com', 'mybank.cn', 'mmstat.com', 'uczzd.cn', 'iconfont.cn', 'freshhema.com', 'hemamax.com', 'hemaos.com', 'hemashare.cn', 'shyhhema.com', 'sm.cn', 'npmmirror.com', 'alios.cn', 'wandoujia.com', 'aligames.com', '25pp.com', '+aliapp.org', 'tanx.com', 'hellobike.com', '+hichina.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', // 'dot.pub', '+qcloud.com', '+gtimg.cn', '+gtimg.com', '+gtimg.com.cn', '+gdtimg.com', '+idqqimg.com', '+udqqimg.com', '+igamecj.com', 'myapp.com', '+myqcloud.com', 'dnspod.com', '+qpic.cn', '+qlogo.cn', 'qq.com', 'qq.com.cn', // 'qq.wang', // 'qqmail.cn', // not owned by QQ, is sold on hichina.com '+qqmail.com', 'qzone.com', '+tencent-cloud.net', '+tencent-cloud.com', 'tencent.com', 'tencent.com.cn', 'tencentmusic.com', 'weixinbridge.com', 'weixin.com', // 'wechat.com', exclude `sgshort.wechat.com` 'weiyun.com', 'soso.com', 'sogo.com', 'sogou.com', '+sogoucdn.com', '+roblox.cn', 'robloxdev.cn', 'wegame.com', 'wegame.com.cn', 'wegameplus.com', 'cdn-go.cn', '+tencentcs.cn', '+qcloudimg.com', 'dnspod.cn', 'anticheatexpert.com', '$url.cn', '+qlivecdn.com', '+tcdnlive.com', '+dnsv1.com', '+smtcdns.net', 'coding.net', '+codehub.cn' ] }, 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 '$acg.tv', '$b23.tv', 'bilibili.cn', 'bilibili.com', // 'bilibili.tv', '+acgvideo.com', '+bilivideo.com', '+bilivideo.cn', '+bilivideo.net', '+hdslb.com', '+biliimg.com', '+biliapi.com', '+biliapi.net', // 'biligame.cn', // not owned by bilibili, was put on sale by ename 'biligame.com', '+biligame.net', 'bilicomic.com', 'bilicomics.com', // 'bilibilipay.cn', // not owned by bilibili // 'bilibilipay.com', // not owned by bilibili '+bilicdn1.com' ] }, XIAOMI: { dns: 'https://doh.pub/dns-query', hosts: {}, realip: false, ruleset: true, domains: [ 'mi.com', 'duokan.com', '+mi-img.com', '+mi-idc.com', '+xiaoaisound.com', '+xiaomixiaoai.com', '+mi-fds.com', '+mifile.cn', '+mijia.tech', 'miui.com', 'xiaomi.com', 'xiaomi.cn', 'xiaomi.net', 'xiaomiev.com', 'xiaomiyoupin.com' ] }, BYTEDANCE: { dns: '180.184.2.2', hosts: {}, realip: false, ruleset: true, domains: [ 'bytedance.com', '+bytecdn.cn', '+volccdn.com', '+toutiaoimg.com', '+toutiaoimg.cn', '+toutiaostatic.com', '+toutiaovod.com', '+toutiaocloud.com', 'toutiaopage.com', 'feiliao.com', 'iesdouyin.com', '+pstatp.com', 'snssdk.com', '+bytegoofy.com', 'toutiao.com', 'feishu.cn', 'feishu.net', '+feishucdn.com', '+feishupkg.com', 'douyin.com', '+douyinpic.com', '+douyinstatic.com', '+douyincdn.com', '+douyinliving.com', '+douyinvod.com', 'huoshan.com', '+huoshanstatic.com', 'huoshanzhibo.com', 'ixigua.com', '+ixiguavideo.com', '+ixgvideo.com', '+volccdn.com', '+byted-static.com', 'volces.com', 'baike.com', '+zjcdn.com', '+zijieapi.com', 'feelgood.cn', '+bytetcc.com', '+bytednsdoc.com', '+byteimg.com', '+byteacctimg.com', '+ibytedapm.com', 'oceanengine.com', '+edge-byted.com', '+volcvideo.com' ] }, BAIDU: { dns: '180.76.76.76', hosts: {}, realip: false, ruleset: true, domains: [ '91.com', 'hao123.com', 'baidu.cn', 'baidu.com', 'iqiyi.com', '+iqiyipic.com', '+baidubce.com', '+bcelive.com', '+baiducontent.com', '+baidustatic.com', '+bdstatic.com', '+bdimg.com', '+bcebos.com', '+baidupcs.com', '+baidubcr.com', '+yunjiasu-cdn.net', 'tieba.com', 'xiaodutv.com', '+shifen.com', '+jomodns.com', '+bdydns.com', '+jomoxc.com', '+duapp.com', '+antpcdn.com', // 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', '+qhimgs?.com', // '+qhimgs0.com', // '+qhimgs1.com', // '+qhimgs2.com', // '+qhimgs3.com', // '+qhimgs4.com', // '+qhimgs5.com', // '+qhimgs6.com', '+qhres.com', '+qhres2.com', '+qhmsg.com', '+qhstatic.com', '+qhupdate.com', '+qihucdn.com', '360.com', '360.cn', '360.net', '360safe.com', '+360tpcdn.com', '360os.com', '+360webcache.com', '360kuai.com', 'so.com', 'haosou.com', 'yunpan.cn', 'yunpan.com', 'yunpan.com.cn', '+qh-cdn.com', 'baomitu.com', 'qiku.com' ] } }; const DOH_BOOTSTRAP = { ALIBABA: { hosts: { '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' ] }, DNSPOD: { hosts: { // 'dot.pub': ['120.53.53.53', '1.12.12.12'], 'doh.pub': [ '120.53.53.53', '1.12.12.12' ] }, realip: false, ruleset: false, dns: 'https://1.12.12.12/dns-query', domains: [ // '$dot.pub', '$doh.pub' ] }, QIHOO360: { hosts: { }, realip: false, ruleset: false, // Surge only supports UDP 53 or Hosts as the bootstrap server of domain DoH dns: '101.198.198.198', domains: [ // '$dns.360.cn', // '$dot.360.cn', '$doh.360.cn' ] } }; const AdGuardHomeDNSMapping = { system: [ 'udp://10.10.1.1:53' ], 'https://doh.pub/dns-query': [ 'tls://1.12.12.12', 'tls://120.53.53.53', 'https://1.12.12.12/dns-query', 'https://120.53.53.53/dns-query' ], 'quic://dns.alidns.com:853': [ 'quic://223.5.5.5', 'quic://223.6.6.6', 'h3://223.5.5.5/dns-query', 'h3://223.6.6.6/dns-query' ], 'https://doh.360.cn/dns-query': [ 'https://doh.360.cn/dns-query', 'tls://dot.360.cn' ], '180.76.76.76': [ 'udp://180.76.76.76' ], '180.184.2.2': [ 'udp://180.184.2.2', 'udp://180.184.1.1' ] }; } (domestic)); return domestic; }var direct = {};var hasRequiredDirect; function requireDirect () { if (hasRequiredDirect) return direct; hasRequiredDirect = 1; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { DIRECTS: function() { return DIRECTS; }, LAN: function() { return LAN; } }); const DIRECTS = { HOTSPOT_CAPTIVE_PORTAL: { dns: 'system', hosts: {}, realip: false, ruleset: false, domains: [ 'securelogin.com.cn', '$captive.apple.com', '$hotspot.cslwifi.com' ] }, SYSTEM: { dns: 'system', hosts: {}, realip: true, ruleset: false, domains: [ '+m2m', // '+ts.net', // TailScale Magic DNS // AdGuard '$injections.adguard.org', '$local.adguard.org', // Auto Discovery '+bogon' ] } }; const LAN = { ROUTER: { dns: 'system', hosts: {}, realip: false, ruleset: true, domains: [ '+home', // 'zte.home', // ZTE CPE // 'airbox.home', // 'bthub.home', // 'bthomehub.home', // 'hitronhub.home', // 'web.setup.home' // Aruba Router '$instant.arubanetworks.com', '$setmeup.arubanetworks.com', // ASUS router '$router.asus.com', '$repeater.asus.com', 'asusrouter.com', // NetGear 'routerlogin.net', 'routerlogin.com', // Tenda WiFi // 'tendawifi.com', // TP-Link Router 'tplinkwifi.net', 'tplogin.cn', 'tplinkap.net', 'tplinkmodem.net', 'tplinkplclogin.net', 'tplinkrepeater.net', // UniFi '+ui.direct', '$unifi', // Other Router // '$router.com', '+huaweimobilewifi.com', '+router', // 'my.router', // 'samsung.router', // '$easy.box', // Vodafone EasyBox '$aterm.me', '$console.gl-inet.com', // '$fritz.box', // '$fritz.repeater', // '$myfritz.box', // '$speedport.ip', // Telekom // '$giga.cube', // Vodafone GigaCube '$homerouter.cpe', '$mobile.hotspot', '$ntt.setup', '$pi.hole', '+plex.direct' ] }, LAN: { dns: 'system', hosts: { }, realip: true, ruleset: true, domains: [ '+lan', // 'amplifi.lan', // '$localhost', '+localdomain', 'home.arpa', // AS112 '10.in-addr.arpa', '16.172.in-addr.arpa', '17.172.in-addr.arpa', '18.172.in-addr.arpa', '19.172.in-addr.arpa', // '2?.172.in-addr.arpa', '20.172.in-addr.arpa', '21.172.in-addr.arpa', '22.172.in-addr.arpa', '23.172.in-addr.arpa', '24.172.in-addr.arpa', '25.172.in-addr.arpa', '26.172.in-addr.arpa', '27.172.in-addr.arpa', '28.172.in-addr.arpa', '29.172.in-addr.arpa', '30.172.in-addr.arpa', '31.172.in-addr.arpa', '168.192.in-addr.arpa', '254.169.in-addr.arpa' ] } }; } (direct)); return direct; }var hasRequiredBuildDomesticDirectLanRulesetDnsMappingModule; function requireBuildDomesticDirectLanRulesetDnsMappingModule () { if (hasRequiredBuildDomesticDirectLanRulesetDnsMappingModule) return buildDomesticDirectLanRulesetDnsMappingModule.exports; hasRequiredBuildDomesticDirectLanRulesetDnsMappingModule = 1; (function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { buildDomesticRuleset: function() { return buildDomesticRuleset; }, createGetDnsMappingRule: function() { return createGetDnsMappingRule; }, getDomesticAndDirectDomainsRulesetPromise: function() { return getDomesticAndDirectDomainsRulesetPromise; } }); const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0); const _domestic = /*@__PURE__*/ requireDomestic(); const _direct = /*@__PURE__*/ requireDirect(); const _fetchtextbyline = /*@__PURE__*/ fetchTextByLine.a(); const _createfile = /*@__PURE__*/ createFile.r(); const _trace = /*@__PURE__*/ index.r(); const _description = /*@__PURE__*/ base.r(); const _memopromise = /*@__PURE__*/ memoPromise.r(); const _yaml = /*#__PURE__*/ _interop_require_wildcard(require$$8); const _appendarrayinplace = /*@__PURE__*/ base.a(); const _dir = /*@__PURE__*/ fetchRetry.a(); const _ruleset = /*@__PURE__*/ ruleset.r(); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = { __proto__: null }; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function createGetDnsMappingRule(allowWildcard) { const hasWildcard = (domain)=>{ if (domain.includes('*') || domain.includes('?')) { if (!allowWildcard) { throw new TypeError(`Wildcard domain is not supported: ${domain}`); } return true; } return false; }; return (domain)=>{ const results = []; if (domain[0] === '$') { const d = domain.slice(1); if (hasWildcard(domain)) { results.push(`DOMAIN-WILDCARD,${d}`); } else { results.push(`DOMAIN,${d}`); } } else if (domain[0] === '+') { const d = domain.slice(1); if (hasWildcard(domain)) { results.push(`DOMAIN-WILDCARD,*.${d}`); } else { results.push(`DOMAIN-SUFFIX,${d}`); } } else if (hasWildcard(domain)) { results.push(`DOMAIN-WILDCARD,${domain}`, `DOMAIN-WILDCARD,*.${domain}`); } else { results.push(`DOMAIN-SUFFIX,${domain}`); } return results; }; } const getDomesticAndDirectDomainsRulesetPromise = (0, _memopromise.createMemoizedPromise)(async ()=>{ const domestics = await (0, _fetchtextbyline.readFileIntoProcessedArray)(_nodepath.default.join(_dir.SOURCE_DIR, 'non_ip/domestic.conf')); const directs = await (0, _fetchtextbyline.readFileIntoProcessedArray)(_nodepath.default.resolve(_dir.SOURCE_DIR, 'non_ip/direct.conf')); const lans = []; const getDnsMappingRuleWithWildcard = createGetDnsMappingRule(true); [ _domestic.DOH_BOOTSTRAP, _domestic.DOMESTICS ].forEach((item)=>{ Object.values(item).forEach(({ domains })=>{ (0, _appendarrayinplace.appendArrayInPlace)(domestics, domains.flatMap(getDnsMappingRuleWithWildcard)); }); }); Object.values(_direct.DIRECTS).forEach(({ domains })=>{ (0, _appendarrayinplace.appendArrayInPlace)(directs, domains.flatMap(getDnsMappingRuleWithWildcard)); }); Object.values(_direct.LAN).forEach(({ domains })=>{ (0, _appendarrayinplace.appendArrayInPlace)(directs, domains.flatMap(getDnsMappingRuleWithWildcard)); }); return [ domestics, directs, lans ]; }); const buildDomesticRuleset = (0, _trace.task)(require.main === module, __filename)(async (span)=>{ const [domestics, directs, lans] = await getDomesticAndDirectDomainsRulesetPromise(); const dataset = [ _domestic.DOH_BOOTSTRAP, _domestic.DOMESTICS, _direct.DIRECTS, _direct.LAN ].flatMap(Object.entries); return Promise.all([ new _ruleset.RulesetOutput(span, 'domestic', 'non_ip').withTitle('Sukka\'s Ruleset - Domestic Domains').withDescription([ ..._description.SHARED_DESCRIPTION, '', 'This file contains known addresses that are avaliable in the Mainland China.' ]).addFromRuleset(domestics).write(), new _ruleset.RulesetOutput(span, 'direct', 'non_ip').withTitle('Sukka\'s Ruleset - Direct Rules').withDescription([ ..._description.SHARED_DESCRIPTION, '', 'This file contains domains and process that should not be proxied.' ]).addFromRuleset(directs).write(), new _ruleset.RulesetOutput(span, 'lan', 'non_ip').withTitle('Sukka\'s Ruleset - LAN').withDescription([ ..._description.SHARED_DESCRIPTION, '', 'This file includes rules for LAN DOMAIN and reserved TLDs.' ]).addFromRuleset(lans).write(), ...dataset.map(([name, { ruleset, domains }])=>{ if (!ruleset) { return; } const output = new _ruleset.SurgeOnlyRulesetOutput(span, name.toLowerCase(), 'sukka_local_dns_mapping', _dir.OUTPUT_MODULES_RULES_DIR).withTitle(`Sukka's Ruleset - Local DNS Mapping (${name})`).withDescription([ ..._description.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(); }), (0, _createfile.compareAndWriteFile)(span, [ '#!name=[Sukka] Local DNS Mapping', `#!desc=Last Updated: ${new Date().toISOString()}`, '', '[Host]', ...Object.entries(// I use an object to deduplicate the domains // Otherwise I could just construct an array directly dataset.reduce((acc, cur)=>{ const ruleset_name = cur[0].toLowerCase(); const { domains, dns, hosts, ruleset } = cur[1]; Object.entries(hosts).forEach(([dns, ips])=>{ acc[dns] ||= ips.join(', '); }); 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; }, {})).map(([dns, ips])=>`${dns} = ${ips}`) ], _nodepath.default.resolve(_dir.OUTPUT_MODULES_DIR, 'sukka_local_dns_mapping.sgmodule')), (0, _createfile.compareAndWriteFile)(span, _yaml.stringify(dataset.reduce((acc, cur)=>{ const { domains, dns, ...rest } = cur[1]; domains.forEach((domain)=>{ switch(domain[0]){ case '$': domain = domain.slice(1); break; case '+': domain = `*.${domain.slice(1)}`; break; default: domain = `+.${domain}`; break; } acc.dns['nameserver-policy'][domain] = dns === 'system' ? [ 'system://', 'system', 'dhcp://system' ] : dns; }); if ('hosts' in rest) { Object.assign(acc.hosts, rest.hosts); } return acc; }, { dns: { 'nameserver-policy': {} }, hosts: {} }), { version: '1.1' }).split('\n'), _nodepath.default.join(_dir.OUTPUT_INTERNAL_DIR, 'clash_nameserver_policy.yaml')), (0, _createfile.compareAndWriteFile)(span, [ '# Local DNS Mapping for AdGuard Home', 'tls://1.12.12.12', 'tls://120.53.53.53', 'https://1.12.12.12/dns-query', 'https://120.53.53.53/dns-query', '[//]udp://10.10.1.1:53', ...[ _domestic.DOMESTICS, _direct.DIRECTS, _direct.LAN ].flatMap(Object.values).flatMap(({ domains, dns: _dns })=>domains.flatMap((domain)=>{ let dns; if (_dns in _domestic.AdGuardHomeDNSMapping) { dns = _domestic.AdGuardHomeDNSMapping[_dns].join(' '); } else { console.warn(`Unknown DNS "${_dns}" not in AdGuardHomeDNSMapping`); dns = _dns; } // if ( // // AdGuard Home has built-in AS112 / private PTR handling // domain.endsWith('.arpa') // // Ignore simple hostname // || !domain.includes('.') // ) { // return []; // } if (domain[0] === '$') { return [ `[/${domain.slice(1)}/]${dns}` ]; } if (domain[0] === '+') { return [ `[/${domain.slice(1)}/]${dns}` ]; } return [ `[/${domain}/]${dns}` ]; })) ], _nodepath.default.resolve(_dir.OUTPUT_INTERNAL_DIR, 'dns_mapping_adguardhome.conf')) ]); }); } (buildDomesticDirectLanRulesetDnsMappingModule, buildDomesticDirectLanRulesetDnsMappingModule.exports)); return buildDomesticDirectLanRulesetDnsMappingModule.exports; }exports.a=requireDirect;exports.b=requireDomestic;exports.r=requireBuildDomesticDirectLanRulesetDnsMappingModule;