Atmosphère DNS.mitm 深度解析:如何用一份 hosts 文件拦截所有域名解析并切断遥测上报

发布时间:2026/10/5 13:07:08
Atmosphère DNS.mitm 深度解析:如何用一份 hosts 文件拦截所有域名解析并切断遥测上报 Atmosphère DNS.mitm 深度解析如何用一份 hosts 文件拦截所有域名解析并切断遥测上报【免费下载链接】AtmosphereAtmosphère is a work-in-progress customized firmware for the Nintendo Switch.项目地址: https://gitcode.com/GitHub_Trending/at/Atmosphere你在 Switch 上运行 Atmosphère 定制固件时可能希望做几件系统本身做不到的事把 Nintendo 遥测服务器的域名解析劫持到回环地址让遥测数据发不出去把某个广告域名解析到0.0.0.0或者把一个测试域名指向局域网里某台机器的固定 IP。Atmosphère 的DNS.mitmDNS 中间人重定向机制自 0.18.0 引入就是干这个的它以 MITM 方式代理系统 DNS 解析服务sfdnsres按一份可扩展的hosts 文件把指定域名直接解析成你写死的 IPv4 地址命中的请求根本不经过真实 DNS未命中的则原样转发。一个具体的痛点为什么要在 DNS 层做文章假设你的目标是让 Switch 连不上遥测服务器。常规思路是断网、改路由器——但这类做法是全局的游戏联机、系统更新全都会受影响。DNS 层拦截的好处是粒度细到单个域名只有命中规则的主机名会被转寄到你指定的 IP其余解析请求照常走运营商 DNS。你可以把 DNS.mitm 想象成一个收件箱转寄服务所有寄往域名解析科系统服务sfdnsres的信件先经过它信上有它在意的收件人名单你的 hosts 规则就按名单改投没有则原封不动转给原科室。这个转寄窗口在 dnsmitm_module.cpp 第 32 行注册服务名编码为sfdnsres挂载代码见同文件第 143 行的RegisterMitmServer调用。值得强调的是拦截范围ResolverImpl::ShouldMitm对所有客户端进程一律返回true见 dnsmitm_resolver_impl.hpp 第 34–40 行即系统服务、游戏、homebrew 的解析请求全都会先过规则表没有进程白名单这一说。出厂默认行为是receive-lp1.dg.srv.nintendo.net和receive-lp1.er.srv.nintendo.net两个遥测域名被重定向到127.0.0.1连接必然失败——遥测上报就此在 DNS 层面被切断。先搞清楚规则从哪个文件读hosts 文件选择顺序很多人配置不生效第一步就错在写错了文件。系统启动或手动触发重解析时Atmosphère 按下面的顺序逐个探测、命中即停完整分支逻辑在 dnsmitm_host_redirection.cpp 第 268–292 行的SelectHostsFile优先级文件路径生效条件1/atmosphere/hosts/emummc_XXXX.txtXXXX 为 4 位十六进制 emummc id如emummc_0001.txt仅 emummc 环境2/atmosphere/hosts/emummc.txt仅 emummc 环境3/atmosphere/hosts/sysmmc.txt仅 sysmmc内置存储环境4/atmosphere/hosts/default.txt任何环境的兜底这里有个容易踩的坑路径中的/atmosphere/是相对 SD 卡根目录的实际位置是SD:/atmosphere/hosts/xxx.txt。另外注意 emummc 环境下优先级 1、2 的 emummc 专属文件会优先于sysmmc.txt和default.txt多张 SD 卡各自跑不同 emummc 时可以给每个 emummc id 单独配一份规则。还有一个便利行为如果default.txt不存在Atmosphère 会在初始化时自动创建并写入默认遥测屏蔽内容见 dnsmitm_host_redirection.cpp 第 325–335 行所以第一次启动后 SD 卡上通常已经有一份可编辑的 hosts 文件。快速上手一份最小可运行的 hosts 文件DNS.mitm 的 hosts 格式与标准 hosts 基本一致但有两个扩展语法用一张表说清语法含义示例*通配符匹配任意位置 0 个或多个任意字符*.tracker.com匹配a.tracker.com和a.b.tracker.com%占位符展开为系统设置项nsd!environment_identifier的值量产机恒为lp1receive-%.dg.srv.nintendo.net等价于receive-lp1.dg.srv.nintendo.net%在词法分析阶段就被展开成完整标识串dnsmitm_host_redirection.cpp 第 210–216 行与 233–236 行lp1常量定义在 nsd_types.hpp 第 34 行非量产环境该值可能不同所以跟随系统更新时直接用%比手写lp1更稳。*的匹配由wildcardcmp完成这是一个支持贪婪回溯的经典通配算法见同文件第 27–65 行。一份实际可用的default.txt长这样# 屏蔽广告域名 0.0.0.0 ads.example.com # 把整个 tracker 子域打到本机 127.0.0.1 *.tracker.example.com # 测试域名指向局域网设备 192.168.1.100 my.test.server规则书写约定一行一个 IPv4 地址后跟一个或多个主机名用空格或 Tab 分隔行首必须是数字否则整行按注释/非法行忽略状态机解析见同文件第 90–250 行。文件大小上限32 KiB0x8000 字节超限会被断言拒绝见第 361 行的显式校验。默认规则永远排在你的规则之前一个反直觉但重要的设计即使你提供了自定义 hosts 文件Atmosphère 的默认遥测屏蔽规则仍会被额外解析效果等价于把默认规则前置拼接到你的文件之前。初始化顺序可以直接从InitializeResolverRedirections第 304–384 行读出来先解析默认规则再选文件、解析自定义内容。为什么这样设计因为如果你的自定义 hosts 没跟着系统更新而更新新版本换了遥测域名兜底规则仍能屏蔽新域名——把遥测风险压到最低。同时这也决定了覆盖方向同一域名若你的规则与默认规则冲突以你的为准。机制上AddRedirection先按主机名删掉旧规则、再把新规则插到链表头部第 83–86 行查询时GetRedirectedHostByName从表头顺序匹配、命中即返回第 386–397 行所以后解析的条目天然压住先解析的。如果你确定不需要兜底比如你自己维护完整的遥测名单可以在system_settings.ini关闭该行为见下文配置速查。深入原理一次解析请求是如何被拦截的当你写的程序调用gethostbyname/getaddrinfo时请求走sfdnsres服务的GetHostByNameRequest/GetAddrInfoRequest及带 Options 的 5.0.0 变体接口声明见 dnsmitm_resolver_impl.hpp 第 19–26 行。ResolverImpl的处理只有两条分支以GetHostByNameRequest为例dnsmitm_resolver_impl.cpp 第 89–109 行命中规则直接构造hostent结构把规则里的 IP 填进去经serializer/目录下的DNSSerializer序列化后作为返回值发回host_error/errno均置 0——对调用方而言就是一次解析成功全程没有网络交互未命中返回ResultShouldForwardToSession请求原样转发给真实的sfdnsres会话处理。服务端并发模型方面整个 DNS.mitm 用8 个线程1 主 7 附加循环调用LoopProcess处理请求最多同时接受30 个会话MaxSessions见 dnsmitm_module.cpp 第 34 行线程启动逻辑见第 66–104 行。对普通用户来说这基本无需关心只说明该子系统的吞吐能力是为全系统所有进程的并发解析设计的。还有一个边界必须知道重定向只支持 IPv4。构造重定向结果时若调用方通过 hint 强制要求AF_INET6实现会直接断言失败AMS_ABORT见 dnsmitm_resolver_impl.cpp 第 59–64 行。所以 hosts 文件里请只写 IPv4 目标地址不要写 IPv6。不重启如何刷新规则hosts 文件只在启动时解析一次。如果你修改了文件但不想重启homebrew 程序可以向已连接的sfdnsres会话发送 Atmosphère 私有扩展 IPC 命令65000AtmosphereReloadHostsFile它会调用InitializeResolverRedirections重建整张规则表命令声明在 dnsmitm_resolver_impl.hpp 第 24 行实现在 dnsmitm_resolver_impl.cpp 第 212–216 行。注意这是私有命令普通的gethostbyname调用不会触发重解析——这是设计使然避免每次解析都重读文件。排查问题两级日志定位为什么没生效DNS.mitm 把诊断能力做成了两级日志都写在 SD 卡atmosphere/logs目录下。第一级启动日志默认开启无需配置。每次启动或重解析时选中的 hosts 文件路径与最终生效的全部规则都会写入dns_mitm_startup.log且每次初始化先删除旧文件再重建第 316–319 行。打开它你能直接确认三件事实际选中的是哪一个 hosts 文件Selected /hosts/xxx.txt是否追加了默认规则Adding defaults to redirection list.最终规则表长什么样Redirections:之后逐条主机名 - IP。九成规则没生效问题在这一步就能定位要么选错文件要么行首没写数字导致整行被忽略。第二级请求级调试日志需显式开启。在system_settings.ini打开开关后每一次GetHostByName/GetAddrInfo请求和每次命中重定向都会追加写入dns_mitm_debug.log格式形如[0000000000000000]: GetHostByNameRequest(host.example.com) [0000000000000000]: Redirecting host.example.com to 127.0.0.1方括号内是发起请求进程的 program id十六进制。配合请求分支代码dnsmitm_resolver_impl.cpp 第 94–101 行可以看到日志与拦截逻辑是同一处打点。排查哪个进程在解析什么域名某请求为何走了真实 DNS时这份日志就是第一手证据。日志写入实现见 dnsmitm_debug.cpp 第 35–75 行注意它按追加模式写、跨重启保留与每次重建的启动日志不同。配置速查system_settings.ini 的三个开关三个配置项都放在[atmosphere]段模板注释见 system_settings.ini 第 53–62 行配置项默认值作用enable_dns_mitmu8!0x1总开关。设为u8!0x0后模块线程直接返回DNS.mitm 完全关闭检查点在 dnsmitm_module.cpp 第 128–131 行add_defaults_to_dns_hostsu8!0x1是否在自定义 hosts 之外追加默认遥测屏蔽规则。设为u8!0x0后仅你的文件生效遥测域名需自行维护enable_dns_mitm_debug_logu8!0x0设为u8!0x1开启请求级调试日志dns_mitm_debug.log最小改动示例只关掉默认规则追加其余保持默认[atmosphere] add_defaults_to_dns_hosts u8!0x0改完system_settings.ini需要重启系统使其生效。常见问题与注意事项改了 hosts 不重启就生效吗不会。规则表只在启动时构建除非有 homebrew 发送 IPC 65000 触发重解析否则必须重启。同一域名写了两条规则听谁的同一文件内后定义的覆盖先定义的默认规则永远排最前所以你的自定义内容总能覆盖默认规则的同名条目。为什么我把某域名解析到了 IPv6 地址却报错重定向目标仅支持 IPv4且被重定向的解析若强制要求 IPv6 结果会触发断言。hosts 中只写 IPv4。%一定会展开成lp1吗量产机是。该值读自系统设置项nsd!environment_identifier非量产环境可能不同见 nsd_types.hpp 第 34–35 行非量产常量dd1已列出。规则表能放多大单个 hosts 文件上限 32 KiB单行主机名缓冲区为 0x200 字节超长主机名同样会触发断言而非静默截断。能只拦某些进程吗不能。ShouldMitm对所有进程返回true规则对系统内一切解析请求生效包括系统服务与游戏进程——写规则时留意通配符的范围*的匹配面很宽。彻底不用 DNS.mitm 会怎样设enable_dns_mitm u8!0x0后整个子系统不启动默认遥测屏蔽也随之消失遥测域名将走真实 DNS 解析。特性文档原始出处为 docs/features/dns_mitm.md模块总览见 docs/components/modules/ams_mitm.mdDNS.mitm 的完整实现集中在 stratosphere/ams_mitm/source/dns_mitm/ 目录从配置到排错的每一步都能在上面提到的源码位置找到对应依据。【免费下载链接】AtmosphereAtmosphère is a work-in-progress customized firmware for the Nintendo Switch.项目地址: https://gitcode.com/GitHub_Trending/at/Atmosphere创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考