<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Windows on 猫猫鱼的小窝</title>
    <link>https://cat.fjh1997.top/tags/windows/</link>
    <description>Recent content from 猫猫鱼的小窝</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    
    <managingEditor>xxx@example.com (catcatyu)</managingEditor>
    <webMaster>xxx@example.com (catcatyu)</webMaster>
    
    <copyright>本博客所有文章除特别声明外，均采用 BY-NC-SA 许可协议。转载请注明出处！</copyright>
    
    <lastBuildDate>Sat, 25 Jul 2026 21:00:00 +0800</lastBuildDate>
    
    
    <atom:link href="https://cat.fjh1997.top/tags/windows/atom.xml" rel="self" type="application/rss&#43;xml" />
    

    
    

    <item>
      <title>Windows 微信 / QQNT 阻止自动更新（配合 RevokeMsgPatcher 版本上限）</title>
      <link>https://cat.fjh1997.top/posts/2026072501.html</link>
      <pubDate>Sat, 25 Jul 2026 21:00:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/2026072501.html</guid>
      <description>
        <![CDATA[<h1>Windows 微信 / QQNT 阻止自动更新（配合 RevokeMsgPatcher 版本上限）</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <h2 id="为什么要阻止升级">
<a class="header-anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e9%98%bb%e6%ad%a2%e5%8d%87%e7%ba%a7"></a>
为什么要阻止升级
</h2><p><a href="https://github.com/huiyadanli/RevokeMsgPatcher" target="_blank" rel="noopener noreferrer nofollow">RevokeMsgPatcher</a>
 通过对客户端二进制做特征 patch，实现 PC 微信 / QQ 的防撤回等能力。特征是跟<strong>具体版本</strong>绑定的，客户端一升，偏移和指令序列往往就失效。</p>
<p>社区 PR <a href="https://github.com/huiyadanli/RevokeMsgPatcher/pull/1193" target="_blank" rel="noopener noreferrer nofollow">huiyadanli/RevokeMsgPatcher#1193</a>
（<code>fix: update QQNT anti-recall patterns</code>）把 QQNT 防撤回特征更新到了：</p>
<table>
  <thead>
      <tr>
          <th>客户端</th>
          <th>PR / 工具侧可用上限（本文写作时）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>QQNT</strong></td>
          <td><strong>9.9.20-36330</strong></td>
      </tr>
      <tr>
          <td><strong>微信（Weixin 4.x）</strong></td>
          <td><strong>4.1.9.30</strong></td>
      </tr>
  </tbody>
</table>
<p>也就是说：</p>
<ul>
<li>你装了更高版本的 QQNT / 微信，这个 PR 里的规则<strong>不一定还能匹配</strong>；</li>
<li>腾讯客户端默认会<strong>后台检查 + 热更新/补丁下载</strong>，一重启就可能悄悄升上去；</li>
<li>想稳定用防撤回，就得先把版本<strong>钉住</strong>，再跑 patch 工具。</li>
</ul>
<p>本文记录在 Windows 宿主机上实际踩过的路径：只拦 <code>dldir*.qq.com</code> <strong>不够</strong>；QQNT 和微信 4.x 的更新通道、本地缓存位置都不一样。</p>
<blockquote>
<p>说明：这是<strong>延后升级</strong>，不是永久锁死。服务端若强制最低版本，旧客户端仍可能无法登录。也不要用来路不明的「免更新破解版」。</p>
</blockquote>
<hr>
<h2 id="历史版本从哪里下">
<a class="header-anchor" href="#%e5%8e%86%e5%8f%b2%e7%89%88%e6%9c%ac%e4%bb%8e%e5%93%aa%e9%87%8c%e4%b8%8b"></a>
历史版本从哪里下
</h2><p>当前版本已经高于 patch 上限时，需要先<strong>降回可用版本</strong>，再立刻做防更新。不要去搜来路不明的「绿色版 / 免更新破解包」；社区有专门归档安装包的仓库（Release 资产，可自行核对哈希）：</p>
<table>
  <thead>
      <tr>
          <th>客户端</th>
          <th>历史版本仓库</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>QQNT</strong></td>
          <td><a href="https://github.com/PRO-2684/qqnt-version-history" target="_blank" rel="noopener noreferrer nofollow">PRO-2684/qqnt-version-history</a>
</td>
      </tr>
      <tr>
          <td><strong>微信 Windows</strong></td>
          <td><a href="https://github.com/cscnk52/wechat-windows-versions" target="_blank" rel="noopener noreferrer nofollow">cscnk52/wechat-windows-versions</a>
</td>
      </tr>
  </tbody>
</table>
<p>配合本文目标上限时，优先找：</p>
<ul>
<li>QQNT：<code>9.9.20-36330</code>（或 PR / 工具说明支持的最近一档）</li>
<li>微信：<code>4.1.9.30</code>（Weixin 4.x）</li>
</ul>
<p>建议流程：</p>
<ol>
<li>卸载当前过高版本（或至少退出客户端）</li>
<li>从上述仓库的 <strong>Releases</strong> 下载对应安装包</li>
<li>安装完成后<strong>先不要登录</strong>，立刻做本文后面的 hosts / 清缓存 / 锁目录</li>
<li>再登录，并运行 RevokeMsgPatcher</li>
</ol>
<blockquote>
<p>仓库由第三方维护，安装包是否完整、是否被服务端拒绝登录，以你本机实测为准；下载后尽量核对 Release 里公布的校验信息。</p>
</blockquote>
<hr>
<h2 id="先确认当前版本">
<a class="header-anchor" href="#%e5%85%88%e7%a1%ae%e8%ae%a4%e5%bd%93%e5%89%8d%e7%89%88%e6%9c%ac"></a>
先确认当前版本
</h2><h3 id="qqnt">
<a class="header-anchor" href="#qqnt"></a>
QQNT
</h3><p>安装目录常见：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">C:\Program Files\Tencent\QQNT\
</span></span></code></pre></td></tr></table>
</div>
</div><p>看当前热更新配置：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">C:\Program Files\Tencent\QQNT\versions\config.json
</span></span></code></pre></td></tr></table>
</div>
</div><p>关键字段：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;curVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;9.9.20-36330&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;readyVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;readyType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><code>curVersion</code>：正在用的版本目录名</li>
<li><code>readyVersion</code> 非空：本地<strong>已经下好/解压好</strong>，提示「新版本已就绪」，重启就会切过去</li>
</ul>
<p>进程命令行里也能看到：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">--app-path=&#34;C:\Program Files\Tencent\QQNT\versions\9.9.20-36330\resources\app&#34;
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="微信新版-weixin-4x">
<a class="header-anchor" href="#%e5%be%ae%e4%bf%a1%e6%96%b0%e7%89%88-weixin-4x"></a>
微信（新版 Weixin 4.x）
</h3><p>新版安装目录是 <code>Weixin</code>，不是老的 <code>WeChat</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">C:\Program Files\Tencent\Weixin\
</span></span><span class="line"><span class="cl">C:\Program Files\Tencent\Weixin\4.1.9.30\
</span></span></code></pre></td></tr></table>
</div>
</div><p>用户数据与更新缓存：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">%AppData%\Tencent\xwechat\
</span></span><span class="line"><span class="cl">%AppData%\Tencent\xwechat\update\
</span></span></code></pre></td></tr></table>
</div>
</div><p>更新组件：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">%AppData%\Tencent\xwechat\xplugin\plugins\WeixinUpdate\&lt;id&gt;\extracted\WeixinUpdate.exe
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="总原则更新分两段">
<a class="header-anchor" href="#%e6%80%bb%e5%8e%9f%e5%88%99%e6%9b%b4%e6%96%b0%e5%88%86%e4%b8%a4%e6%ae%b5"></a>
总原则：更新分两段
</h2><table>
  <thead>
      <tr>
          <th>阶段</th>
          <th>含义</th>
          <th>只改 hosts 够不够</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>检查更新</td>
          <td>问服务器有没有新版本 → <strong>弹窗</strong></td>
          <td>通常<strong>不够</strong></td>
      </tr>
      <tr>
          <td>下载 / 落地</td>
          <td>把安装包或热更新包写到本地</td>
          <td><strong>hosts / 权限 / 防火墙</strong> 能挡</td>
      </tr>
      <tr>
          <td>已就绪</td>
          <td>包已在本地，<code>readyVersion</code> 或 <code>update\patch</code> 已齐</td>
          <td><strong>必须删本地缓存</strong>，光拦域名没用</td>
      </tr>
  </tbody>
</table>
<p>所以会出现：</p>
<ul>
<li>hosts 已生效，但客户端仍提示「发现新版本 / 新版本已就绪」——正常；</li>
<li>点「立即更新」仍能下——说明走了<strong>别的域名</strong>，或<strong>IPv6 / 已建立连接</strong>没被拦；</li>
<li>点了就能装——说明包<strong>早就下完了</strong>。</li>
</ul>
<hr>
<h2 id="一qqnt真正的热更新域名不是-dldir">
<a class="header-anchor" href="#%e4%b8%80qqnt%e7%9c%9f%e6%ad%a3%e7%9a%84%e7%83%ad%e6%9b%b4%e6%96%b0%e5%9f%9f%e5%90%8d%e4%b8%8d%e6%98%af-dldir"></a>
一、QQNT：真正的热更新域名不是 dldir
</h2><h3 id="1-特征串从-majornode-里能抠到">
<a class="header-anchor" href="#1-%e7%89%b9%e5%be%81%e4%b8%b2%e4%bb%8e-majornode-%e9%87%8c%e8%83%bd%e6%8a%a0%e5%88%b0"></a>
1. 特征串（从 <code>major.node</code> 里能抠到）
</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">https://qqpatch.gtimg.cn
</span></span><span class="line"><span class="cl">https://qqpatch.gtimg.cn/hotUpdate_new
</span></span><span class="line"><span class="cl">https://qqpatch.gtimg.cn/dynamic_module/
</span></span></code></pre></td></tr></table>
</div>
</div><p>实际下载时 DNS 缓存里还出现过腾讯下载 CDN 变体，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">downv6.ydcdn.tcdnos.com
</span></span><span class="line"><span class="cl">downv6.aly.tcdnos.com
</span></span></code></pre></td></tr></table>
</div>
</div><p>（会随线路变化，以本机 DNS 缓存 / 抓包为准。）</p>
<h3 id="2-本地落地位置">
<a class="header-anchor" href="#2-%e6%9c%ac%e5%9c%b0%e8%90%bd%e5%9c%b0%e4%bd%8d%e7%bd%ae"></a>
2. 本地落地位置
</h3><p>热更新包会进：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">C:\Program Files\Tencent\QQNT\versions\
</span></span><span class="line"><span class="cl">  9.9.20-36330\          ← 当前版本目录
</span></span><span class="line"><span class="cl">  9.9.xx-xxxxx\          ← 已解压的新版本
</span></span><span class="line"><span class="cl">  9.9.xx-xxxxx.zip       ← 下载中的包（有时还会出现奇怪的 .zip.zip）
</span></span><span class="line"><span class="cl">  config.json
</span></span></code></pre></td></tr></table>
</div>
</div><p>若 <code>config.json</code> 里已有：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;readyVersion&#34;</span><span class="err">:</span> <span class="s2">&#34;9.9.32-51246&#34;</span><span class="err">,</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;readyType&#34;</span><span class="err">:</span> <span class="s2">&#34;HOT_UPDATE&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>则界面就是「新版本已就绪」——<strong>不必再下载</strong>。</p>
<h3 id="3-hosts管理员编辑">
<a class="header-anchor" href="#3-hosts%e7%ae%a1%e7%90%86%e5%91%98%e7%bc%96%e8%be%91"></a>
3. hosts（管理员编辑）
</h3><p>路径：<code>C:\Windows\System32\drivers\etc\hosts</code></p>
<p>建议同时写 <strong>IPv4 + IPv6</strong>（只写 <code>127.0.0.1</code> 时，IPv6 仍可能通）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># QQNT 热更新
</span></span><span class="line"><span class="cl">127.0.0.1 qqpatch.gtimg.cn
</span></span><span class="line"><span class="cl">::1 qqpatch.gtimg.cn
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># 实测出现过的下载 CDN（可按抓包增减）
</span></span><span class="line"><span class="cl">127.0.0.1 downv6.ydcdn.tcdnos.com
</span></span><span class="line"><span class="cl">::1 downv6.ydcdn.tcdnos.com
</span></span><span class="line"><span class="cl">127.0.0.1 downv6.aly.tcdnos.com
</span></span><span class="line"><span class="cl">::1 downv6.aly.tcdnos.com
</span></span><span class="line"><span class="cl">127.0.0.1 down.ydcdn.tcdnos.com
</span></span><span class="line"><span class="cl">::1 down.ydcdn.tcdnos.com
</span></span><span class="line"><span class="cl">127.0.0.1 down.aly.tcdnos.com
</span></span><span class="line"><span class="cl">::1 down.aly.tcdnos.com
</span></span><span class="line"><span class="cl">127.0.0.1 downv6.tcdnos.com
</span></span><span class="line"><span class="cl">::1 downv6.tcdnos.com
</span></span><span class="line"><span class="cl">127.0.0.1 down.tcdnos.com
</span></span><span class="line"><span class="cl">::1 down.tcdnos.com
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bat" data-lang="bat"><span class="line"><span class="cl">ipconfig /flushdns
</span></span></code></pre></td></tr></table>
</div>
</div><p>验证：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bat" data-lang="bat"><span class="line"><span class="cl">ping qqpatch.gtimg.cn
</span></span></code></pre></td></tr></table>
</div>
</div><p>应指向 <code>127.0.0.1</code>。</p>
<h3 id="4-清掉已就绪的新版本">
<a class="header-anchor" href="#4-%e6%b8%85%e6%8e%89%e5%b7%b2%e5%b0%b1%e7%bb%aa%e7%9a%84%e6%96%b0%e7%89%88%e6%9c%ac"></a>
4. 清掉「已就绪」的新版本
</h3><ol>
<li>托盘彻底退出 QQ</li>
<li>删除高于目标版本的目录和 zip，例如不要的 <code>9.9.32-*</code></li>
<li>编辑 <code>versions\config.json</code>，保证：</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;curVersion&#34;</span><span class="err">:</span> <span class="s2">&#34;9.9.20-36330&#34;</span><span class="err">,</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;readyVersion&#34;</span><span class="err">:</span> <span class="s2">&#34;&#34;</span><span class="err">,</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;readyInstaller&#34;</span><span class="err">:</span> <span class="s2">&#34;&#34;</span><span class="err">,</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;readyType&#34;</span><span class="err">:</span> <span class="s2">&#34;&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="4">
<li>再启动 QQ</li>
</ol>
<p>可选加固：给 <code>versions</code> 目录去掉普通用户的写入权限（过狠可能影响正常运行，慎用）。</p>
<h3 id="5-副作用">
<a class="header-anchor" href="#5-%e5%89%af%e4%bd%9c%e7%94%a8"></a>
5. 副作用
</h3><ul>
<li><code>qqpatch.gtimg.cn</code> 还承载部分主题 / 动态资源，拦截后个别皮肤资源可能异常。</li>
<li><code>tcdnos.com</code> 若被其它腾讯下载共用，也可能受影响。</li>
</ul>
<hr>
<h2 id="二微信-weixin-4xdldir--本地-update-目录">
<a class="header-anchor" href="#%e4%ba%8c%e5%be%ae%e4%bf%a1-weixin-4xdldir--%e6%9c%ac%e5%9c%b0-update-%e7%9b%ae%e5%bd%95"></a>
二、微信 Weixin 4.x：dldir + 本地 update 目录
</h2><h3 id="1-二进制里的下载入口">
<a class="header-anchor" href="#1-%e4%ba%8c%e8%bf%9b%e5%88%b6%e9%87%8c%e7%9a%84%e4%b8%8b%e8%bd%bd%e5%85%a5%e5%8f%a3"></a>
1. 二进制里的下载入口
</h3><p><code>Weixin.dll</code> 里能看到类似：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">https://dldir1.qq.com
</span></span><span class="line"><span class="cl">https://dldir1v6.qq.com
</span></span><span class="line"><span class="cl">https://dldir1v6.qq.com/weixin/Universal/Windows/XPlugin/updateConfigUniWin.xml
</span></span><span class="line"><span class="cl">https://support.weixin.qq.com/update/
</span></span></code></pre></td></tr></table>
</div>
</div><p>老办法「只 hosts 几个 dldir」对<strong>下载</strong>有帮助，但：</p>
<ol>
<li>要补 <strong>IPv6 <code>::1</code></strong>，否则 v6 线路可能绕过；</li>
<li>若 <code>%AppData%\Tencent\xwechat\update\</code> 里已经有完整 patch，点更新照样能装。</li>
</ol>
<h3 id="2-本地更新缓存长什么样">
<a class="header-anchor" href="#2-%e6%9c%ac%e5%9c%b0%e6%9b%b4%e6%96%b0%e7%bc%93%e5%ad%98%e9%95%bf%e4%bb%80%e4%b9%88%e6%a0%b7"></a>
2. 本地更新缓存长什么样
</h3><p>示例（版本号按你机器上的为准）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">%AppData%\Tencent\xwechat\update\
</span></span><span class="line"><span class="cl">  download\4.1.11.55\Weixin.dll.zip
</span></span><span class="line"><span class="cl">  download\4.1.11.55\Weixin.exe.zip
</span></span><span class="line"><span class="cl">  download\4.1.11.55\patch.zip
</span></span><span class="line"><span class="cl">  patch\4.1.11.55\Weixin.dll
</span></span><span class="line"><span class="cl">  patch\4.1.11.55\Weixin.exe
</span></span><span class="line"><span class="cl">  ...
</span></span></code></pre></td></tr></table>
</div>
</div><p>同时进程列表里可能出现：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">WeixinUpdate.exe
</span></span></code></pre></td></tr></table>
</div>
</div><p>路径类似：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">%AppData%\Tencent\xwechat\xplugin\plugins\WeixinUpdate\9013\extracted\WeixinUpdate.exe
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-hosts">
<a class="header-anchor" href="#3-hosts"></a>
3. hosts
</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># 微信 / 腾讯通用下载域（IPv4 + IPv6）
</span></span><span class="line"><span class="cl">127.0.0.1 dldir1.qq.com
</span></span><span class="line"><span class="cl">::1 dldir1.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir1v6.qq.com
</span></span><span class="line"><span class="cl">::1 dldir1v6.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir2.qq.com
</span></span><span class="line"><span class="cl">::1 dldir2.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir3.qq.com
</span></span><span class="line"><span class="cl">::1 dldir3.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir4.qq.com
</span></span><span class="line"><span class="cl">::1 dldir4.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir5.qq.com
</span></span><span class="line"><span class="cl">::1 dldir5.qq.com
</span></span><span class="line"><span class="cl">127.0.0.1 dldir6.qq.com
</span></span><span class="line"><span class="cl">::1 dldir6.qq.com
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bat" data-lang="bat"><span class="line"><span class="cl">ipconfig /flushdns
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="4-删缓存--锁-update-目录">
<a class="header-anchor" href="#4-%e5%88%a0%e7%bc%93%e5%ad%98--%e9%94%81-update-%e7%9b%ae%e5%bd%95"></a>
4. 删缓存 + 锁 update 目录
</h3><ol>
<li>退出微信（含托盘）</li>
<li>结束残留的 <code>WeixinUpdate.exe</code></li>
<li>删除整个：</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">%AppData%\Tencent\xwechat\update
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="4">
<li>重建空目录后，对 <code>update</code>：<strong>拒绝当前用户 / Users 的写入、修改、删除</strong>（Administrators / SYSTEM 保留完全控制）。</li>
</ol>
<p>这样即使检查到更新，也<strong>写不进缓存</strong>。</p>
<h3 id="5-防火墙拦-weixinupdateexe推荐">
<a class="header-anchor" href="#5-%e9%98%b2%e7%81%ab%e5%a2%99%e6%8b%a6-weixinupdateexe%e6%8e%a8%e8%8d%90"></a>
5. 防火墙拦 WeixinUpdate.exe（推荐）
</h3><p><code>Win + R</code> → <code>wf.msc</code> → <strong>出站规则</strong> → 新建规则 → 程序 → 选中上述 <code>WeixinUpdate.exe</code> → <strong>阻止连接</strong>。</p>
<p>插件版本目录（如 <code>9012</code> / <code>9013</code>）可能并存，每个路径各建一条，或更新后检查是否换了路径。</p>
<p>主程序 <code>Weixin.exe</code> <strong>不要</strong>整进程出站全拦，容易直接没法登录/收消息。</p>
<h3 id="6-副作用">
<a class="header-anchor" href="#6-%e5%89%af%e4%bd%9c%e7%94%a8"></a>
6. 副作用
</h3><ul>
<li><code>dldir*.qq.com</code> 是腾讯通用下载域，QQ 安装包、其它腾讯软件下载也可能受影响。</li>
<li>锁 <code>update</code> 后，官方热更新基本失效——对「钉死 4.1.9.30」是预期行为。</li>
</ul>
<hr>
<h2 id="三推荐操作顺序想钉在-revokemsgpatcher-可用版本">
<a class="header-anchor" href="#%e4%b8%89%e6%8e%a8%e8%8d%90%e6%93%8d%e4%bd%9c%e9%a1%ba%e5%ba%8f%e6%83%b3%e9%92%89%e5%9c%a8-revokemsgpatcher-%e5%8f%af%e7%94%a8%e7%89%88%e6%9c%ac"></a>
三、推荐操作顺序（想钉在 RevokeMsgPatcher 可用版本）
</h2><p>以目标 <strong>QQNT 9.9.20-36330</strong>、<strong>微信 4.1.9.30</strong> 为例：</p>
<ol>
<li><strong>先确认当前就是目标版本</strong>；若更高，从历史版本仓库装回：
<ul>
<li>QQNT：<a href="https://github.com/PRO-2684/qqnt-version-history" target="_blank" rel="noopener noreferrer nofollow">PRO-2684/qqnt-version-history</a>
</li>
<li>微信：<a href="https://github.com/cscnk52/wechat-windows-versions" target="_blank" rel="noopener noreferrer nofollow">cscnk52/wechat-windows-versions</a>
</li>
</ul>
</li>
<li><strong>立刻</strong>改 hosts（QQNT 的 <code>qqpatch</code> + 微信的 <code>dldir</code>，都带 <code>::1</code>）。</li>
<li><strong>立刻</strong>清 QQNT <code>versions</code> 里多余版本 + 清空 <code>readyVersion</code>。</li>
<li><strong>立刻</strong>清微信 <code>xwechat\update</code>，并锁写 + 拦 <code>WeixinUpdate.exe</code>。</li>
<li>再运行 <a href="https://github.com/huiyadanli/RevokeMsgPatcher" target="_blank" rel="noopener noreferrer nofollow">RevokeMsgPatcher</a>
（含 PR #1193 那套特征）。</li>
<li>日常少点「立即更新」；看到「已就绪」优先当本地缓存，先清再谈拦域名。</li>
</ol>
<hr>
<h2 id="四怎么确认拦截生效">
<a class="header-anchor" href="#%e5%9b%9b%e6%80%8e%e4%b9%88%e7%a1%ae%e8%ae%a4%e6%8b%a6%e6%88%aa%e7%94%9f%e6%95%88"></a>
四、怎么确认拦截生效
</h2><h3 id="dns">
<a class="header-anchor" href="#dns"></a>
DNS
</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bat" data-lang="bat"><span class="line"><span class="cl">ping qqpatch.gtimg.cn
</span></span><span class="line"><span class="cl">ping dldir1v6.qq.com
</span></span></code></pre></td></tr></table>
</div>
</div><p>应解析到 <code>127.0.0.1</code> / 本机。</p>
<h3 id="qqnt-1">
<a class="header-anchor" href="#qqnt-1"></a>
QQNT
</h3><ul>
<li><code>versions</code> 下不应再长出新的大体积 zip / 新版本目录；</li>
<li><code>config.json</code> 的 <code>readyVersion</code> 应保持空。</li>
</ul>
<h3 id="微信">
<a class="header-anchor" href="#%e5%be%ae%e4%bf%a1"></a>
微信
</h3><ul>
<li><code>xwechat\update</code> 下不应再出现 <code>download\</code> / <code>patch\</code> 大文件；</li>
<li>若仍弹更新但装不上、写目录失败，说明权限锁在起作用。</li>
</ul>
<h3 id="仍能下载时">
<a class="header-anchor" href="#%e4%bb%8d%e8%83%bd%e4%b8%8b%e8%bd%bd%e6%97%b6"></a>
仍能下载时
</h3><ol>
<li>在下载过程中看 DNS 缓存：</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-DnsClientCache</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="py">Entry</span> <span class="o">-match</span> <span class="s1">&#39;qq|weixin|gtimg|tcdnos|dldir&#39;</span> <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="2">
<li>看进程出站连接（<code>Get-NetTCPConnection -OwningProcess &lt;pid&gt;</code>），把新域名补进 hosts。</li>
<li>已建立的 TCP 连接不会因改 hosts 立刻断，需退出客户端再试。</li>
</ol>
<hr>
<h2 id="五和-revokemsgpatcher-的关系再强调一次">
<a class="header-anchor" href="#%e4%ba%94%e5%92%8c-revokemsgpatcher-%e7%9a%84%e5%85%b3%e7%b3%bb%e5%86%8d%e5%bc%ba%e8%b0%83%e4%b8%80%e6%ac%a1"></a>
五、和 RevokeMsgPatcher 的关系（再强调一次）
</h2><p>防更新的目的不是「永远不用新版本」，而是：</p>
<blockquote>
<p><strong>把客户端钉在 patch 特征仍然匹配的版本上，避免热更新把防撤回打失效。</strong></p>
</blockquote>
<p>PR #1193 侧当前明确测过 / 面向的上限是：</p>
<ul>
<li>QQNT：<code>9.9.20-36330</code>（含私聊 C2C 被动撤回路径）</li>
<li>微信：<code>4.1.9.30</code></li>
</ul>
<p>版本一涨，需要重新找特征、更新 <code>patch.json</code> / 资源，而不是指望旧二进制一直能用。<br>
上游合并进度、后续版本支持范围以仓库与 PR 讨论为准：<br>
<a href="https://github.com/huiyadanli/RevokeMsgPatcher/pull/1193" target="_blank" rel="noopener noreferrer nofollow">https://github.com/huiyadanli/RevokeMsgPatcher/pull/1193</a>
</p>
<hr>
<h2 id="六恢复方法简要">
<a class="header-anchor" href="#%e5%85%ad%e6%81%a2%e5%a4%8d%e6%96%b9%e6%b3%95%e7%ae%80%e8%a6%81"></a>
六、恢复方法（简要）
</h2><ol>
<li>从改 hosts 前的备份恢复 <code>C:\Windows\System32\drivers\etc\hosts</code>，或删掉本文相关段落。</li>
<li><code>ipconfig /flushdns</code></li>
<li>删除防火墙规则「Block WeixinUpdate outbound*」</li>
<li>恢复 <code>xwechat\update</code> 目录权限（去掉 Deny 写入）</li>
<li>需要升级时再走官方更新即可</li>
</ol>
<hr>
<h2 id="小结">
<a class="header-anchor" href="#%e5%b0%8f%e7%bb%93"></a>
小结
</h2><table>
  <thead>
      <tr>
          <th>客户端</th>
          <th>关键域名</th>
          <th>本地缓存</th>
          <th>额外手段</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>QQNT</td>
          <td><code>qqpatch.gtimg.cn</code>，以及 <code>*.tcdnos.com</code> 下载 CDN</td>
          <td><code>QQNT\versions\</code> + <code>config.json</code> 的 <code>readyVersion</code></td>
          <td>删已就绪版本目录</td>
      </tr>
      <tr>
          <td>微信 4.x</td>
          <td><code>dldir*.qq.com</code>（补 IPv6）</td>
          <td><code>%AppData%\Tencent\xwechat\update\</code></td>
          <td>锁目录 + 拦 <code>WeixinUpdate.exe</code></td>
      </tr>
  </tbody>
</table>
<p><strong>只拦 dldir、不管本地已就绪包，是最常见的「hosts 设了还是在更」原因。</strong><br>
为了配合 RevokeMsgPatcher 的版本上限，应把「拦域名 + 清缓存 + 必要时权限/防火墙」当成一套流程，而不是单点技巧。</p>

        
        <hr><p>本文2026-07-25首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-07-25</p>]]>
      </description>
      
    </item>
    
    

    <item>
      <title>使用mosdns-x实现DNS分流：白名单域名走DoH代理并自动回退</title>
      <link>https://cat.fjh1997.top/posts/2026070601.html</link>
      <pubDate>Mon, 06 Jul 2026 16:00:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/2026070601.html</guid>
      <description>
        <![CDATA[<h1>使用mosdns-x实现DNS分流：白名单域名走DoH代理并自动回退</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <h2 id="背景">
<a class="header-anchor" href="#%e8%83%8c%e6%99%af"></a>
背景
</h2><p>打开超星学习通（chaoxing.com）时页面一直加载缓慢，浏览器开发者工具发现 <code>static.wisweb.com</code> 和 <code>p2.cldisk.com</code> 两个资源域名 DNS 解析失败（ERR_NAME_NOT_RESOLVED）。排查发现系统 DNS 指向了本地 dnscrypt-proxy（127.0.0.1:53），而 dnscrypt-proxy 配置了通过 xray 代理访问 Cloudflare DoH，形成了一条脆弱的依赖链。</p>
<h2 id="问题根因">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e6%a0%b9%e5%9b%a0"></a>
问题根因
</h2><p>原来的 DNS 解析链路：</p>
<pre tabindex="0"><code>系统 DNS (127.0.0.1:53)
  → dnscrypt-proxy
    → http_proxy (127.0.0.1:10808)
      → xray 代理
        → Cloudflare DoH (cloudflare-dns.com)
</code></pre><p>这条链路存在多个单点故障：</p>
<ol>
<li><strong>dnscrypt-proxy 依赖 xray 代理</strong>：<code>http_proxy = 'http://127.0.0.1:10808'</code> 配置导致所有 DNS 查询都要经过 xray</li>
<li><strong>xray 节点域名需要 DNS 解析</strong>：xray 连接的节点域名 <code>d4.fjh1997.top</code> 本身需要 DNS 查询，存在循环依赖风险</li>
<li><strong>重启即崩</strong>：dnscrypt-proxy 重启后缓存清空，需要重新 bootstrap 连接 Cloudflare，但如果 xray 代理此时未就绪，整个 DNS 系统瘫痪</li>
</ol>
<h2 id="需求">
<a class="header-anchor" href="#%e9%9c%80%e6%b1%82"></a>
需求
</h2><ul>
<li><strong>默认域名</strong>走普通 DNS（快速、稳定、不依赖代理）</li>
<li><strong>白名单域名</strong>（Google、GitHub 等）走 Cloudflare DoH，通过 xray SOCKS5 代理加密访问</li>
<li>DoH 或代理故障时<strong>自动回退</strong>到普通 DNS</li>
<li>不能有循环依赖</li>
</ul>
<h2 id="方案选型">
<a class="header-anchor" href="#%e6%96%b9%e6%a1%88%e9%80%89%e5%9e%8b"></a>
方案选型
</h2><h3 id="尝试-dnsproxyadguard">
<a class="header-anchor" href="#%e5%b0%9d%e8%af%95-dnsproxyadguard"></a>
尝试 dnsproxy（AdGuard）
</h3><p>dnsproxy 支持按域名分流上游，但有两个致命问题：</p>
<ol>
<li><strong>不支持 HTTP 代理</strong>：<code>HTTPS_PROXY</code> 环境变量无效，直连 Cloudflare 被 GFW reset</li>
<li><strong>不支持 <code>http://</code> scheme</strong>作为 DoH 上游：日志报 <code>unsupported url scheme: http</code></li>
</ol>
<p>尝试用 Python 写中继脚本弥补，但需要自签证书、额外维护一个进程，方案过于复杂。</p>
<h3 id="最终选择mosdns-x">
<a class="header-anchor" href="#%e6%9c%80%e7%bb%88%e9%80%89%e6%8b%a9mosdns-x"></a>
最终选择：mosdns-x
</h3><p><a href="https://github.com/pmkol/mosdns-x" target="_blank" rel="noopener noreferrer nofollow">mosdns-x</a>
 是一个灵活的 DNS 路由器，原生支持：</p>
<ul>
<li><code>fast_forward</code> 插件的 <code>socks5</code> 参数 — 直接通过 SOCKS5 代理转发 DoH 请求</li>
<li><code>dial_addr</code> 参数 — 直接指定 DoH 服务器 IP，避免 DNS 循环依赖</li>
<li><code>primary</code>/<code>secondary</code> + <code>fast_fallback</code> — 优雅的故障回退机制</li>
<li><code>data_provider</code> — 白名单域名文件，支持 <code>auto_reload</code> 热更新</li>
</ul>
<h2 id="部署">
<a class="header-anchor" href="#%e9%83%a8%e7%bd%b2"></a>
部署
</h2><h3 id="macos-安装">
<a class="header-anchor" href="#macos-%e5%ae%89%e8%a3%85"></a>
macOS 安装
</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 通过代理下载（直连 GitHub 可能慢）</span>
</span></span><span class="line"><span class="cl">curl -sL --proxy socks5://127.0.0.1:10808 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -o /tmp/mosdns.zip <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="s2">&#34;https://github.com/pmkol/mosdns-x/releases/download/v26.05.25/mosdns-darwin-arm64.zip&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">unzip /tmp/mosdns.zip -d /tmp/mosdns-bin
</span></span><span class="line"><span class="cl">cp /tmp/mosdns-bin/mosdns /opt/homebrew/bin/mosdns
</span></span><span class="line"><span class="cl">chmod +x /opt/homebrew/bin/mosdns
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mosdns version
</span></span><span class="line"><span class="cl"><span class="c1"># version: v4.6.0, build time: 26.05.25</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="白名单域名文件">
<a class="header-anchor" href="#%e7%99%bd%e5%90%8d%e5%8d%95%e5%9f%9f%e5%90%8d%e6%96%87%e4%bb%b6"></a>
白名单域名文件
</h3><p>创建 <code>/opt/homebrew/etc/mosdns/whitelist.txt</code>，每行一个域名，后缀匹配（<code>google.com</code> 会匹配 <code>www.google.com</code> 等）：</p>
<pre tabindex="0"><code># Google
google.com
googleapis.com
gstatic.com
youtube.com
ytimg.com
ggpht.com
googlevideo.com

# GitHub
github.com
githubusercontent.com
githubassets.com
github.io

# 社交媒体
twitter.com
x.com
twimg.com
t.co
facebook.com
instagram.com
whatsapp.com

# AI
openai.com
anthropic.com
claude.ai
chatgpt.com

# 其他
wikipedia.org
wikimedia.org
cloudflare.com
microsoft.com
apple.com
</code></pre><h3 id="mosdns-配置文件">
<a class="header-anchor" href="#mosdns-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6"></a>
mosdns 配置文件
</h3><p>创建 <code>/opt/homebrew/etc/mosdns/config.yaml</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">log</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">level</span><span class="p">:</span><span class="w"> </span><span class="l">error</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">data_providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">doh_whitelist</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="l">/opt/homebrew/etc/mosdns/whitelist.txt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">auto_reload</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">plugins</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># 缓存</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">cache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">cache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">size</span><span class="p">:</span><span class="w"> </span><span class="m">4096</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">lazy_cache_ttl</span><span class="p">:</span><span class="w"> </span><span class="m">86400</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># 默认上游: AliDNS 普通 DNS (快、稳、不依赖代理)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">forward_default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">fast_forward</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">upstream</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;223.5.5.5&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;223.6.6.6&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># DoH 上游: Cloudflare DoH 经 xray SOCKS5 代理</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># dial_addr 直接指定 IP，无需 DNS 解析，避免循环依赖</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">forward_doh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">fast_forward</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">upstream</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://cloudflare-dns.com/dns-query&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">dial_addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;1.1.1.1:443&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">socks5</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1:10808&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">idle_timeout</span><span class="p">:</span><span class="w"> </span><span class="m">30</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># 白名单域名匹配</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">query_is_whitelist</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">query_matcher</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">domain</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="s2">&#34;provider:doh_whitelist&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># 白名单处理: DoH 优先，超时回退到普通 DNS</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">whitelist_handler</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">sequence</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">exec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">primary</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">forward_doh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">secondary</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">forward_default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">fast_fallback</span><span class="p">:</span><span class="w"> </span><span class="m">300</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">always_standby</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># 主流水线</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">main_sequence</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">sequence</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">exec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">cache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">query_is_whitelist</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">exec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">whitelist_handler</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="l">_return</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="l">forward_default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">servers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">exec</span><span class="p">:</span><span class="w"> </span><span class="l">main_sequence</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">listeners</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">udp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1:53&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">tcp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1:53&#34;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="macos-launchd-服务">
<a class="header-anchor" href="#macos-launchd-%e6%9c%8d%e5%8a%a1"></a>
macOS launchd 服务
</h3><p>创建 <code>/Library/LaunchDaemons/com.mosdns.plist</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;plist</span> <span class="na">version=</span><span class="s">&#34;1.0&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>Label<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>com.mosdns<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>ProgramArguments<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;array&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>/opt/homebrew/bin/mosdns<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>start<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>-c<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>/opt/homebrew/etc/mosdns/config.yaml<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/array&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>RunAtLoad<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>KeepAlive<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>StandardErrorPath<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>/opt/homebrew/var/log/mosdns.log<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dict&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/plist&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>加载服务并切换系统 DNS：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo launchctl load /Library/LaunchDaemons/com.mosdns.plist
</span></span><span class="line"><span class="cl">networksetup -setdnsservers Wi-Fi 127.0.0.1
</span></span><span class="line"><span class="cl">sudo dscacheutil -flushcache <span class="o">&amp;&amp;</span> sudo killall -HUP mDNSResponder
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="windows-部署为系统服务">
<a class="header-anchor" href="#windows-%e9%83%a8%e7%bd%b2%e4%b8%ba%e7%b3%bb%e7%bb%9f%e6%9c%8d%e5%8a%a1"></a>
Windows 部署为系统服务
</h3><p>Windows 不建议把 <code>mosdns.exe</code> 直接放进注册表启动项或交互式计划任务。<code>mosdns.exe</code> 是控制台程序，这样做在登录时会弹出黑框；如果同时配置了多个启动入口，还会出现多个实例争用 53 端口、任务返回 <code>0xFFFFFFFF</code> 等问题。</p>
<p>mosdns-x 自带 Windows 服务管理功能，正确做法是将其注册为系统服务。以下步骤已在 Windows 11、mosdns-x <code>v4.6.0</code>（build <code>26.05.25</code>）上验证。</p>
<h4 id="相关脚本下载">
<a class="header-anchor" href="#%e7%9b%b8%e5%85%b3%e8%84%9a%e6%9c%ac%e4%b8%8b%e8%bd%bd"></a>
相关脚本下载
</h4><p>本文配套脚本已放在站点静态目录，可直接下载：</p>
<table>
  <thead>
      <tr>
          <th>文件</th>
          <th>说明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/files/mosdns/healthcheck.ps1">healthcheck.ps1</a>
</td>
          <td>UDP 默认上游健康探测：失败才 <code>Restart-Service mosdns</code></td>
      </tr>
      <tr>
          <td><a href="/files/mosdns/install-healthcheck.ps1">install-healthcheck.ps1</a>
</td>
          <td>管理员一键安装探测脚本 + 计划任务 <code>mosdns-udp-health</code></td>
      </tr>
      <tr>
          <td><a href="/files/mosdns/config.windows.yaml">config.windows.yaml</a>
</td>
          <td>Windows 示例配置（默认 UDP 多上游 + 白名单 DoH）</td>
      </tr>
      <tr>
          <td><a href="/files/mosdns/whitelist.txt">whitelist.txt</a>
</td>
          <td>示例白名单</td>
      </tr>
      <tr>
          <td><a href="/files/mosdns/README.md">README.md</a>
</td>
          <td>简要说明</td>
      </tr>
  </tbody>
</table>
<p>也可从 GitHub 仓库路径获取：<a href="https://github.com/fjh1997/cat/tree/main/static/files/mosdns" target="_blank" rel="noopener noreferrer"><code>static/files/mosdns/</code></a>
</p>
<p>一键下载健康检查到 <code>C:\mosdns</code> 并注册任务（管理员 PowerShell）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">New-Item</span> <span class="n">-ItemType</span> <span class="n">Directory</span> <span class="n">-Path</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span> <span class="n">-Force</span> <span class="p">|</span> <span class="nb">Out-Null</span>
</span></span><span class="line"><span class="cl"><span class="nb">Invoke-WebRequest</span> <span class="n">https</span><span class="err">:</span><span class="p">//</span><span class="n">cat</span><span class="p">.</span><span class="py">fjh1997</span><span class="p">.</span><span class="n">top</span><span class="p">/</span><span class="n">files</span><span class="p">/</span><span class="n">mosdns</span><span class="p">/</span><span class="n">healthcheck</span><span class="p">.</span><span class="py">ps1</span> <span class="n">-OutFile</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="n">healthcheck</span><span class="p">.</span><span class="py">ps1</span>
</span></span><span class="line"><span class="cl"><span class="nb">Invoke-WebRequest</span> <span class="n">https</span><span class="err">:</span><span class="p">//</span><span class="n">cat</span><span class="p">.</span><span class="py">fjh1997</span><span class="p">.</span><span class="n">top</span><span class="p">/</span><span class="n">files</span><span class="p">/</span><span class="n">mosdns</span><span class="p">/</span><span class="nb">install-healthcheck</span><span class="p">.</span><span class="py">ps1</span> <span class="n">-OutFile</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="nb">install-healthcheck</span><span class="p">.</span><span class="py">ps1</span>
</span></span><span class="line"><span class="cl"><span class="n">powershell</span> <span class="n">-ExecutionPolicy</span> <span class="n">Bypass</span> <span class="o">-File</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="nb">install-healthcheck</span><span class="p">.</span><span class="py">ps1</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="1-准备目录和文件">
<a class="header-anchor" href="#1-%e5%87%86%e5%a4%87%e7%9b%ae%e5%bd%95%e5%92%8c%e6%96%87%e4%bb%b6"></a>
1. 准备目录和文件
</h4><p>从 <a href="https://github.com/pmkol/mosdns-x/releases" target="_blank" rel="noopener noreferrer nofollow">mosdns-x Releases</a>
 下载 <code>mosdns-windows-amd64.zip</code>，解压后整理成：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">C:\mosdns\
</span></span><span class="line"><span class="cl">├── mosdns.exe
</span></span><span class="line"><span class="cl">├── config.yaml              # 示例: /files/mosdns/config.windows.yaml
</span></span><span class="line"><span class="cl">├── whitelist.txt            # 示例: /files/mosdns/whitelist.txt
</span></span><span class="line"><span class="cl">├── healthcheck.ps1          # 可选 UDP 健康检查
</span></span><span class="line"><span class="cl">└── install-healthcheck.ps1
</span></span></code></pre></td></tr></table>
</div>
</div><p>示例配置与白名单可直接下载：</p>
<ul>
<li><a href="/files/mosdns/config.windows.yaml">config.windows.yaml</a>
 → 保存为 <code>C:\mosdns\config.yaml</code>（按需改 SOCKS 端口/上游）</li>
<li><a href="/files/mosdns/whitelist.txt">whitelist.txt</a>
 → <code>C:\mosdns\whitelist.txt</code></li>
</ul>
<p>Windows 版配置逻辑与前文一致，只需要把文件路径换成 Windows 路径。YAML 中推荐使用正斜杠，避免反斜杠转义：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">log</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;C:/mosdns/mosdns.log&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">level</span><span class="p">:</span><span class="w"> </span><span class="l">error</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">data_providers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">doh_whitelist</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;C:/mosdns/whitelist.txt&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">auto_reload</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>中间的 <code>plugins</code> 配置直接沿用前文。<code>servers</code> 可以同时监听 IPv4 和 IPv6 回环地址：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">servers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">exec</span><span class="p">:</span><span class="w"> </span><span class="l">main_sequence</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="m">5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">listeners</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">udp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1:53&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">tcp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1:53&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">udp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[::1]:53&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">tcp</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[::1]:53&#34;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>先在管理员 PowerShell 中检查版本和配置能否启动：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-Location</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">version</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="nb">start </span><span class="n">-c</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="n">config</span><span class="p">.</span><span class="py">yaml</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>看到四个监听器正常启动后按 <code>Ctrl+C</code> 退出，再安装服务。</p>
<h4 id="2-安装并启动-windows-服务">
<a class="header-anchor" href="#2-%e5%ae%89%e8%a3%85%e5%b9%b6%e5%90%af%e5%8a%a8-windows-%e6%9c%8d%e5%8a%a1"></a>
2. 安装并启动 Windows 服务
</h4><p>仍在管理员 PowerShell 中执行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-Location</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 注册为开机自动启动的 Windows 服务</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">install</span> <span class="n">-d</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span> <span class="n">-c</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="n">config</span><span class="p">.</span><span class="py">yaml</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># install 只负责注册，不会立即启动</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="nb">start
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 查看 mosdns 自带的服务状态</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">status</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 也可以通过 Windows SCM 查看</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">-Name</span> <span class="n">mosdns</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>正常情况下，服务应显示为 <code>Running</code>，启动类型为 <code>Automatic</code>，登录桌面时也不会出现控制台窗口。</p>
<blockquote>
<p>该服务功能由 mosdns-x 内置的 <code>service</code> 子命令提供。官方说明其底层基于 <code>kardianos/service</code>，Windows 已实测可用，但仍建议安装后检查服务、监听端口和实际 DNS 解析结果。</p>
</blockquote>
<h4 id="3-将-windows-dns-指向本机">
<a class="header-anchor" href="#3-%e5%b0%86-windows-dns-%e6%8c%87%e5%90%91%e6%9c%ac%e6%9c%ba"></a>
3. 将 Windows DNS 指向本机
</h4><p>先查看正在使用的物理网卡名称：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-NetAdapter</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="n">Status</span> <span class="o">-eq</span> <span class="n">Up</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>假设网卡名为 <code>以太网</code>，执行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">netsh</span> <span class="n">interface</span> <span class="n">ipv4</span> <span class="nb">set </span><span class="n">dnsservers</span> <span class="n">name</span><span class="p">=</span><span class="s2">&#34;以太网&#34;</span> <span class="n">static</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">primary</span> <span class="n">validate</span><span class="p">=</span><span class="n">no</span>
</span></span><span class="line"><span class="cl"><span class="n">netsh</span> <span class="n">interface</span> <span class="n">ipv6</span> <span class="nb">set </span><span class="n">dnsservers</span> <span class="n">name</span><span class="p">=</span><span class="s2">&#34;以太网&#34;</span> <span class="n">static</span> <span class="p">::</span><span class="mf">1</span> <span class="n">primary</span> <span class="n">validate</span><span class="p">=</span><span class="n">no</span>
</span></span><span class="line"><span class="cl"><span class="nb">Clear-DnsClientCache</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果使用 Wi-Fi，把命令中的 <code>以太网</code> 换成实际接口名。只需要修改当前上网的物理网卡，不要批量修改 WSL、Hyper-V、VMware、Tailscale、WireGuard 等虚拟网卡。</p>
<h4 id="4-验证服务端口和解析">
<a class="header-anchor" href="#4-%e9%aa%8c%e8%af%81%e6%9c%8d%e5%8a%a1%e7%ab%af%e5%8f%a3%e5%92%8c%e8%a7%a3%e6%9e%90"></a>
4. 验证服务、端口和解析
</h4><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 服务必须处于 Running</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">-Name</span> <span class="n">mosdns</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 127.0.0.1 和 ::1 的 TCP/UDP 53 应归同一个 mosdns PID</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-NetUDPEndpoint</span> <span class="n">-LocalPort</span> <span class="mf">53</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-NetTCPConnection</span> <span class="n">-LocalPort</span> <span class="mf">53</span> <span class="n">-State</span> <span class="n">Listen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 测试普通 DNS 和白名单域名</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">baidu</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">google</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">github</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>mosdns 服务会早于用户登录启动，而 xray 的 <code>127.0.0.1:10808</code> 可能稍后才就绪。此时白名单查询暂时走 <code>secondary</code> 普通 DNS 回退是预期行为；xray 启动后，后续查询会自动恢复使用 Cloudflare DoH。</p>
<h4 id="5-避免重复启动">
<a class="header-anchor" href="#5-%e9%81%bf%e5%85%8d%e9%87%8d%e5%a4%8d%e5%90%af%e5%8a%a8"></a>
5. 避免重复启动
</h4><p>确认服务运行正常后，不要再保留同名计划任务或注册表启动项。可以先检查：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-ScheduledTask</span> <span class="n">-TaskName</span> <span class="n">mosdns</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-ItemProperty</span> <span class="n">HKCU</span><span class="err">:</span><span class="p">\</span><span class="n">Software</span><span class="p">\</span><span class="n">Microsoft</span><span class="p">\</span><span class="n">Windows</span><span class="p">\</span><span class="n">CurrentVersion</span><span class="p">\</span><span class="n">Run</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Name</span> <span class="n">mosdns</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果这些入口是以前手动创建的，可以删除：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Unregister-ScheduledTask</span> <span class="n">-TaskName</span> <span class="n">mosdns</span> <span class="n">-Confirm:</span><span class="vm">$false</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
</span></span><span class="line"><span class="cl"><span class="nb">Remove-ItemProperty</span> <span class="n">HKCU</span><span class="err">:</span><span class="p">\</span><span class="n">Software</span><span class="p">\</span><span class="n">Microsoft</span><span class="p">\</span><span class="n">Windows</span><span class="p">\</span><span class="n">CurrentVersion</span><span class="p">\</span><span class="n">Run</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Name</span> <span class="n">mosdns</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>服务日常管理命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-Location</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">restart</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">stop</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="nb">start
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 确实不再使用时才卸载</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">stop</span>
</span></span><span class="line"><span class="cl"><span class="p">.\</span><span class="n">mosdns</span><span class="p">.</span><span class="py">exe</span> <span class="n">service</span> <span class="n">uninstall</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="windows-服务账户为何默认是-localsystem而不是用户态">
<a class="header-anchor" href="#windows-%e6%9c%8d%e5%8a%a1%e8%b4%a6%e6%88%b7%e4%b8%ba%e4%bd%95%e9%bb%98%e8%ae%a4%e6%98%af-localsystem%e8%80%8c%e4%b8%8d%e6%98%af%e7%94%a8%e6%88%b7%e6%80%81"></a>
Windows 服务账户：为何默认是 LocalSystem，而不是用户态
</h3><p><code>mosdns.exe service install</code> 注册的服务默认以 <strong>LocalSystem（SYSTEM）</strong> 运行。这不是“必须最高权限才安全”，而是工程取舍：</p>
<table>
  <thead>
      <tr>
          <th>方式</th>
          <th>优点</th>
          <th>缺点</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>LocalSystem 服务</strong>（当前方案）</td>
          <td>开机即可解析 DNS，<strong>不依赖用户登录</strong>；绑定 <code>127.0.0.1:53</code> 更省事；崩溃可由 SCM 自动拉起</td>
          <td>权限面大；出问题时排查要区分 Session 0 / 用户会话</td>
      </tr>
      <tr>
          <td><strong>当前用户交互式启动</strong></td>
          <td>权限更小，更接近“最小权限”</td>
          <td>未登录时没有 DNS；注销即停；黑框/多实例问题又会回来</td>
      </tr>
      <tr>
          <td><strong>专用低权限账户 + 服务</strong></td>
          <td>介于两者之间，相对更安全</td>
          <td>要单独建账户、授目录权限、处理 53 端口权限，维护成本高</td>
      </tr>
  </tbody>
</table>
<p><strong>结论：</strong></p>
<ul>
<li>作为<strong>系统 DNS 转发器</strong>，更合理的模型是 <strong>服务 + 开机自启</strong>，而不是“用户登录后才起的用户态进程”。</li>
<li>若坚持更安全：可改为专用本地账户跑服务，而不是直接用交互用户会话；<strong>不必</strong>为了“用户态更安全”放弃 Windows 服务模型。</li>
<li>本文实测：UDP 上游假死与“是不是 LocalSystem”<strong>无直接关系</strong>——同一 LocalSystem 下 <strong>SYSTEM 裸发 UDP 到阿里 DNS 完全正常</strong>，问题在 <strong>mosdns 进程内复用的 UDP 连接</strong>。</li>
</ul>
<h3 id="windows-默认上游建议多路兜底">
<a class="header-anchor" href="#windows-%e9%bb%98%e8%ae%a4%e4%b8%8a%e6%b8%b8%e5%bb%ba%e8%ae%ae%e5%a4%9a%e8%b7%af%e5%85%9c%e5%ba%95"></a>
Windows 默认上游建议多路兜底
</h3><p>生产环境建议默认上游不要只写两个 AliDNS，可加上路由器与备用公共 DNS，降低单一上游抖动：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">tag</span><span class="p">:</span><span class="w"> </span><span class="l">forward_default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">fast_forward</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">args</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">upstream</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;192.168.1.254&#34;</span><span class="w">   </span><span class="c"># 按实际网关修改；没有可删</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;223.5.5.5&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;223.6.6.6&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">addr</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;119.29.29.29&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">trusted</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>日志排查时临时把 <code>log.level</code> 调到 <code>info</code>，稳定后再改回 <code>error</code>。</p>
<h3 id="windows-踩坑udp-上游假死2026-07-补充">
<a class="header-anchor" href="#windows-%e8%b8%a9%e5%9d%91udp-%e4%b8%8a%e6%b8%b8%e5%81%87%e6%ad%bb2026-07-%e8%a1%a5%e5%85%85"></a>
Windows 踩坑：UDP 上游“假死”（2026-07 补充）
</h3><h4 id="现象">
<a class="header-anchor" href="#%e7%8e%b0%e8%b1%a1"></a>
现象
</h4><ul>
<li>服务显示 <code>Running</code>，<code>127.0.0.1:53</code> 也在听。</li>
<li><strong>白名单域名</strong>（Google/GitHub，走 DoH + SOCKS5）仍正常。</li>
<li><strong>默认域名</strong>（baidu、超星静态资源等，走明文 UDP 上游）全部超时：<code>context deadline exceeded</code>。</li>
<li>用户态用同一份 <code>config.yaml</code> 起 mosdns（监听高端口）则 <strong>UDP 上游完全正常</strong>。</li>
</ul>
<p>容易误判成：</p>
<ol>
<li>上游 DNS 挂了</li>
<li>和 ICS（SharedAccess）“抢上游端口”</li>
<li>LocalSystem 不能发 UDP</li>
</ol>
<p>下面三条都能排除。</p>
<h4 id="根因已用抓包--管理员实验验证">
<a class="header-anchor" href="#%e6%a0%b9%e5%9b%a0%e5%b7%b2%e7%94%a8%e6%8a%93%e5%8c%85--%e7%ae%a1%e7%90%86%e5%91%98%e5%ae%9e%e9%aa%8c%e9%aa%8c%e8%af%81"></a>
根因（已用抓包 + 管理员实验验证）
</h4><p><code>fast_forward</code> 会对上游做 <strong>连接复用</strong>（进程内可见长期 connected 的 UDP：<code>0.0.0.0:xxxxx → 223.5.5.5:53</code> 等）。</p>
<p>在 Windows 上，服务跑久之后（休眠唤醒、网卡切换、Hyper-V/WSL 虚拟网卡抖动等），这些 <strong>connected UDP 可能进入“假死”</strong>：</p>
<table>
  <thead>
      <tr>
          <th>检查项</th>
          <th>假死进程</th>
          <th>说明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>netstat</code></td>
          <td>仍显示连着 <code>223.5.5.5:53</code></td>
          <td>套接字对象还在</td>
      </tr>
      <tr>
          <td>Wireshark/dumpcap 抓以太网 <code>udp and host 223.5.5.5</code></td>
          <td><strong>0 包</strong></td>
          <td><strong>根本没把查询打到网卡</strong></td>
      </tr>
      <tr>
          <td>mosdns 日志</td>
          <td>有客户端 query，最终 <code>deadline exceeded</code></td>
          <td>请求进了 mosdns，上游侧空转</td>
      </tr>
      <tr>
          <td><code>Restart-Service mosdns</code></td>
          <td>新 PID、新临时端口，UDP 立刻恢复</td>
          <td>清掉假死连接即可</td>
      </tr>
  </tbody>
</table>
<p>进一步对照：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">SYSTEM 进程 raw UDP → 223.5.5.5     ✅ 正常
</span></span><span class="line"><span class="cl">假死中的 mosdns 服务（旧 PID）      ❌ 线上 0 包
</span></span><span class="line"><span class="cl">重启后的 mosdns 服务（新 PID）      ✅ UDP 恢复
</span></span><span class="line"><span class="cl">ICS (SharedAccess) 保持 Running     ✅ 不必为修 UDP 去关 ICS
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>因此：</strong></p>
<ol>
<li><strong>不是上游服务器坏了。</strong></li>
<li><strong>不是 ICS 和 <code>223.5.5.5</code> 抢端口</strong>——上游在远端，客户端用的是临时源端口。</li>
<li>ICS 占 <code>0.0.0.0:53</code> 主要影响的是“谁当本机 DNS <strong>服务端</strong>监听 53”；你的 mosdns 监听 <code>127.0.0.1:53</code> 可以并存。</li>
<li>若本机还开 <strong>WSL2</strong>，微软文档要求 <strong>ICS/SharedAccess 参与 HNS/DNS</strong>，<strong>不要为了本机 DNS 长期禁用 ICS</strong>。</li>
</ol>
<h4 id="快速恢复坚持-udp-上游时">
<a class="header-anchor" href="#%e5%bf%ab%e9%80%9f%e6%81%a2%e5%a4%8d%e5%9d%9a%e6%8c%81-udp-%e4%b8%8a%e6%b8%b8%e6%97%b6"></a>
快速恢复（坚持 UDP 上游时）
</h4><p>管理员 PowerShell：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Restart-Service</span> <span class="n">mosdns</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">www</span><span class="p">.</span><span class="py">baidu</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span> <span class="n">-Type</span> <span class="n">A</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">static</span><span class="p">.</span><span class="py">wisweb</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span> <span class="n">-Type</span> <span class="n">A</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="健康检查失败才重启推荐">
<a class="header-anchor" href="#%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e5%a4%b1%e8%b4%a5%e6%89%8d%e9%87%8d%e5%90%af%e6%8e%a8%e8%8d%90"></a>
健康检查：失败才重启（推荐）
</h4><p>官方 <code>idle_timeout</code> 只作用于 TCP/DoT/DoH 等，<strong>不会</strong>回收明文 UDP 连接。要在坚持 UDP 上游的前提下自愈，使用配套脚本（<a href="/files/mosdns/healthcheck.ps1">healthcheck.ps1</a>
 / <a href="/files/mosdns/install-healthcheck.ps1">install-healthcheck.ps1</a>
）：</p>
<ol>
<li>周期性用 <code>127.0.0.1</code> 解析非白名单域名（走默认 UDP 上游）。</li>
<li><strong>仅失败时</strong> <code>Restart-Service mosdns</code>，正常时零打扰。</li>
<li>以 SYSTEM 计划任务运行（默认每 3 分钟）。</li>
</ol>
<p>管理员一键安装：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 已下载到 C:\mosdns 时：</span>
</span></span><span class="line"><span class="cl"><span class="n">powershell</span> <span class="n">-ExecutionPolicy</span> <span class="n">Bypass</span> <span class="o">-File</span> <span class="n">C:</span><span class="p">\</span><span class="n">mosdns</span><span class="p">\</span><span class="nb">install-healthcheck</span><span class="p">.</span><span class="py">ps1</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>或直接从站点拉取（见上文「相关脚本下载」）。</p>
<blockquote>
<p>这与早期“暴力 watchdog 杀进程”不同：<strong>仅探测失败才重启</strong>，正常时不碰服务。</p>
</blockquote>
<p>日志默认写到 <code>C:\mosdns\healthcheck.log</code>。</p>
<h4 id="排查清单给未来的自己">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e6%b8%85%e5%8d%95%e7%bb%99%e6%9c%aa%e6%9d%a5%e7%9a%84%e8%87%aa%e5%b7%b1"></a>
排查清单（给未来的自己）
</h4><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 1) 服务与监听</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">mosdns</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-NetUDPEndpoint</span> <span class="n">-LocalPort</span> <span class="mf">53</span> <span class="p">|</span> <span class="nb">Format-Table</span> <span class="n">LocalAddress</span><span class="p">,</span><span class="n">OwningProcess</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 2) 是否在复用“假死”上游 socket（长期固定远程 53 很可疑）</span>
</span></span><span class="line"><span class="cl"><span class="nv">$pid</span> <span class="p">=</span> <span class="p">(</span><span class="nb">Get-CimInstance</span> <span class="n">Win32_Service</span> <span class="n">-Filter</span> <span class="s2">&#34;Name=&#39;mosdns&#39;&#34;</span><span class="p">).</span><span class="py">ProcessId</span>
</span></span><span class="line"><span class="cl"><span class="n">netstat</span> <span class="n">-ano</span> <span class="n">-p</span> <span class="n">UDP</span> <span class="p">|</span> <span class="n">findstr</span> <span class="nv">$pid</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 3) 分流是否正常：默认域 vs 白名单</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">www</span><span class="p">.</span><span class="py">baidu</span><span class="p">.</span><span class="py">com</span>  <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span> <span class="n">-Type</span> <span class="n">A</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">www</span><span class="p">.</span><span class="py">google</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-DnsOnly</span> <span class="n">-Type</span> <span class="n">A</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 4) 对照：本机直连上游是否正常（排除运营商/上游故障）</span>
</span></span><span class="line"><span class="cl"><span class="nb">Resolve-DnsName</span> <span class="n">www</span><span class="p">.</span><span class="py">baidu</span><span class="p">.</span><span class="py">com</span> <span class="n">-Server</span> <span class="mf">223.5</span><span class="p">.</span><span class="py">5</span><span class="p">.</span><span class="py">5</span> <span class="n">-DnsOnly</span> <span class="n">-Type</span> <span class="n">A</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 5) 仍异常：抓包看服务查询时有没有 192.168.x.x → 223.5.5.5 的 DNS</span>
</span></span><span class="line"><span class="cl"><span class="c">#    有请求无应答 → 上游/中间设备；完全无请求 → 假死连接或进程未真正 send</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>配置务必改 <strong>服务实际加载的路径</strong> <code>C:\mosdns\config.yaml</code>（<code>sc qc mosdns</code> 可见），不要改用户目录里另一份拷贝。</p>
<h2 id="架构说明">
<a class="header-anchor" href="#%e6%9e%b6%e6%9e%84%e8%af%b4%e6%98%8e"></a>
架构说明
</h2><pre tabindex="0"><code>系统 DNS: 127.0.0.1 → mosdns (mosdns-x v4.6.0)
  │
  ├── 默认域名 → AliDNS 普通 DNS (223.5.5.5)
  │     快速、稳定、不依赖代理
  │     chaoxing.com, wisweb.com, cldisk.com 等
  │
  └── 白名单域名 → Cloudflare DoH (1.1.1.1:443)
        ├── 经 xray SOCKS5 代理 (127.0.0.1:10808)
        ├── dial_addr 直连 IP，无需 DNS 解析
        ├── 300ms 超时自动回退到 AliDNS
        │
        google.com, github.com, twitter.com 等
</code></pre><h3 id="关键设计">
<a class="header-anchor" href="#%e5%85%b3%e9%94%ae%e8%ae%be%e8%ae%a1"></a>
关键设计
</h3><p><strong>避免循环依赖</strong>：<code>dial_addr: &quot;1.1.1.1:443&quot;</code> 直接指定 Cloudflare 的 IP，mosdns 连接 DoH 服务器时不需要先解析域名。xray 的 SOCKS5 入口也是 <code>127.0.0.1:10808</code>，本地直连无需 DNS。</p>
<p><strong>自动回退</strong>：<code>fast_fallback: 300</code> 表示 DoH 请求超过 300ms 未响应时，自动发起普通 DNS 查询作为备选。<code>always_standby: false</code> 表示不预先发起备选查询，仅在超时后才回退，减少不必要的查询。</p>
<p><strong>白名单热更新</strong>：<code>auto_reload: true</code> 让 mosdns 监控白名单文件变化。macOS 编辑 <code>/opt/homebrew/etc/mosdns/whitelist.txt</code>，Windows 编辑 <code>C:\mosdns\whitelist.txt</code>，保存后都会自动生效，无需重启服务。</p>
<p><strong>Windows 服务模型</strong>：用内置 <code>service</code> 跑 LocalSystem，保证未登录也可解析；安全上若要收紧，优先考虑专用服务账户，而不是退回用户态启动项。</p>
<p><strong>Windows UDP 自愈</strong>：明文 UDP 上游可能因连接复用假死；保留 UDP 策略时，用“探测失败才重启”的健康检查，而不是改成全站 DoH 或关掉 ICS。</p>
<h2 id="验证">
<a class="header-anchor" href="#%e9%aa%8c%e8%af%81"></a>
验证
</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 默认域名 - 走 AliDNS</span>
</span></span><span class="line"><span class="cl">nslookup www.chaoxing.com
</span></span><span class="line"><span class="cl"><span class="c1"># Name: bistatic-mh.aichaoxing.com</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Address: 140.210.88.45</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">nslookup static.wisweb.com
</span></span><span class="line"><span class="cl"><span class="c1"># Name: k1.gslb.ksyuncdn.com</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Address: 115.231.33.4</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 白名单域名 - 走 Cloudflare DoH via xray</span>
</span></span><span class="line"><span class="cl">nslookup google.com
</span></span><span class="line"><span class="cl"><span class="c1"># Name: google.com</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Address: 142.251.210.142</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">nslookup github.com
</span></span><span class="line"><span class="cl"><span class="c1"># Name: github.com</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Address: 20.205.243.166</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="清理旧服务">
<a class="header-anchor" href="#%e6%b8%85%e7%90%86%e6%97%a7%e6%9c%8d%e5%8a%a1"></a>
清理旧服务
</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 禁用 dnscrypt-proxy</span>
</span></span><span class="line"><span class="cl">sudo mv /Library/LaunchDaemons/homebrew.mxcl.dnscrypt-proxy.plist <span class="se">\
</span></span></span><span class="line"><span class="cl">       /Library/LaunchDaemons/homebrew.mxcl.dnscrypt-proxy.plist.disabled
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 禁用 dnsproxy 和 doh-relay</span>
</span></span><span class="line"><span class="cl">sudo mv /Library/LaunchDaemons/com.dnsproxy.plist <span class="se">\
</span></span></span><span class="line"><span class="cl">       /Library/LaunchDaemons/com.dnsproxy.plist.disabled
</span></span><span class="line"><span class="cl">sudo mv /Library/LaunchDaemons/com.doh-relay.plist <span class="se">\
</span></span></span><span class="line"><span class="cl">       /Library/LaunchDaemons/com.doh-relay.plist.disabled
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="配置文件位置">
<a class="header-anchor" href="#%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e4%bd%8d%e7%bd%ae"></a>
配置文件位置
</h2><table>
  <thead>
      <tr>
          <th>文件</th>
          <th>macOS</th>
          <th>Windows</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主配置</td>
          <td><code>/opt/homebrew/etc/mosdns/config.yaml</code></td>
          <td><code>C:\mosdns\config.yaml</code></td>
      </tr>
      <tr>
          <td>白名单</td>
          <td><code>/opt/homebrew/etc/mosdns/whitelist.txt</code></td>
          <td><code>C:\mosdns\whitelist.txt</code></td>
      </tr>
      <tr>
          <td>日志</td>
          <td><code>/opt/homebrew/var/log/mosdns.log</code></td>
          <td><code>C:\mosdns\mosdns.log</code></td>
      </tr>
      <tr>
          <td>自启动方式</td>
          <td><code>/Library/LaunchDaemons/com.mosdns.plist</code></td>
          <td>内置 <code>mosdns</code> Windows 服务</td>
      </tr>
      <tr>
          <td>UDP 健康检查（可选）</td>
          <td>—</td>
          <td>计划任务 <code>mosdns-udp-health</code> + <code>C:\mosdns\healthcheck.ps1</code></td>
      </tr>
  </tbody>
</table>
<p>重启命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo launchctl unload /Library/LaunchDaemons/com.mosdns.plist
</span></span><span class="line"><span class="cl">sudo launchctl load /Library/LaunchDaemons/com.mosdns.plist
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="总结">
<a class="header-anchor" href="#%e6%80%bb%e7%bb%93"></a>
总结
</h2><p>从&quot;超星加载慢&quot;到最终方案，经历了：</p>
<ol>
<li><strong>诊断</strong>：浏览器 DevTools 发现 DNS 解析失败</li>
<li><strong>根因</strong>：dnscrypt-proxy 的 <code>http_proxy</code> 配置造成脆弱的代理依赖链</li>
<li><strong>尝试 dnsproxy</strong>：不支持 HTTP 代理，不支持 <code>http://</code> scheme，方案失败</li>
<li><strong>尝试 Python 中继</strong>：可行但过于复杂，需要额外维护进程和自签证书</li>
<li><strong>mosdns-x</strong>：原生 <code>socks5</code> 参数 + <code>dial_addr</code> + <code>fast_fallback</code>，完美满足所有需求</li>
</ol>
<p>mosdns-x 的插件化设计非常灵活，<code>fast_forward</code> 插件的 <code>socks5</code> 参数直接解决了&quot;DoH 走代理&quot;的核心需求，<code>dial_addr</code> 避免了 DNS 循环依赖，<code>primary</code>/<code>secondary</code> + <code>fast_fallback</code> 提供了优雅的故障回退。配合 <code>data_provider</code> 的 <code>auto_reload</code>，白名单维护也非常方便。</p>
<p>Windows 上后续补充的经验：</p>
<ol>
<li><strong>用系统服务，不要用户态启动项</strong>——为的是开机可用，不是“SYSTEM 更安全”。</li>
<li><strong>默认路径坚持 UDP 时，要防连接假死</strong>——表现为白名单还行、国内域全挂；重启服务即愈；可用健康检查自愈。</li>
<li><strong>需要 WSL2 时不要长期关 ICS</strong>——ICS 占 <code>0.0.0.0:53</code> 与 <code>127.0.0.1:53</code> 可并存；UDP 假死不是“和上游抢 53 端口”。</li>
</ol>

        
        <hr><p>本文2026-07-06首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-07-06</p>]]>
      </description>
      
    </item>
    
    

    <item>
      <title>windows下安装openssh server卡顿的时候使用代理安装的方法</title>
      <link>https://cat.fjh1997.top/posts/2026042801.html</link>
      <pubDate>Tue, 28 Apr 2026 23:55:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/2026042801.html</guid>
      <description>
        <![CDATA[<h1>windows下安装openssh server卡顿的时候使用代理安装的方法</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <h2 id="问题现象">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e7%8e%b0%e8%b1%a1"></a>
问题现象
</h2><p>一开始我是从 Windows 的“设置 -&gt; 系统 -&gt; 可选功能 -&gt; 查看功能”里添加 <code>OpenSSH 服务器</code>，界面一直停在“正在添加”，进度很慢：</p>
<p><img
  src="/images/windows-openssh-server-optional-feature-stuck.png"
  alt="可选功能里安装 OpenSSH 服务器卡住" width="582" height="799"
  loading="lazy"
  decoding="async"
/>
</p>
<p>后面不再等可选功能页面，改成用命令行安装和排查 OpenSSH Server：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Add-WindowsCapability</span> <span class="n">-Online</span> <span class="n">-Name</span> <span class="n">OpenSSH</span><span class="p">.</span><span class="n">Server</span><span class="p">~~~~</span><span class="mf">0.0</span><span class="p">.</span><span class="py">1</span><span class="p">.</span><span class="py">0</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>命令执行很慢，长时间没有进度。即使给当前 PowerShell 加了代理，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nv">$env:http_proxy</span><span class="p">=</span><span class="s2">&#34;http://127.0.0.1:10809&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">$env:https_proxy</span><span class="p">=</span><span class="s2">&#34;http://127.0.0.1:10809&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>也不一定有用。</p>
<p>原因是 <code>Add-WindowsCapability</code> 背后不是简单的 PowerShell 下载，而是通过 Windows Update、BITS、CBS/TrustedInstaller 这些系统组件去获取 FoD（Features on Demand）内容。当前用户的环境变量代理不等于系统服务账户代理。</p>
<h2 id="排查过程">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b"></a>
排查过程
</h2><p>先看 WinHTTP 代理：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">netsh</span> <span class="n">winhttp</span> <span class="n">show</span> <span class="n">proxy</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>再看代理端口是否真的在监听：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-NetTCPConnection</span> <span class="n">-LocalAddress</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-LocalPort</span> <span class="mf">10809</span> <span class="n">-State</span> <span class="n">Listen</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果使用 v2rayN/xray，通常 HTTP 代理端口是 <code>127.0.0.1:10809</code>；如果使用 Clash，常见端口是 <code>127.0.0.1:7890</code>。</p>
<p>然后看 CBS/DISM 日志：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Select-String</span> <span class="n">-Path</span> <span class="n">C:</span><span class="p">\</span><span class="n">Windows</span><span class="p">\</span><span class="n">Logs</span><span class="p">\</span><span class="n">CBS</span><span class="p">\</span><span class="n">CBS</span><span class="p">.</span><span class="py">log</span> <span class="n">-Pattern</span> <span class="s2">&#34;FCAcquirerWUClient|DownloadProgress|0x&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">Select-String</span> <span class="n">-Path</span> <span class="n">C:</span><span class="p">\</span><span class="n">Windows</span><span class="p">\</span><span class="n">Logs</span><span class="p">\</span><span class="n">DISM</span><span class="p">\</span><span class="n">dism</span><span class="p">.</span><span class="py">log</span> <span class="n">-Pattern</span> <span class="s2">&#34;OpenSSH|Add-Capability|0x&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>我这里看到的关键日志是：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">FCAcquirerWUClient: WULib DownloadProgress: [0 / 100]
</span></span></code></pre></td></tr></table>
</div>
</div><p>也就是卡在 Windows Update 下载阶段，并不是 OpenSSH 本身安装慢。</p>
<p>还要检查 CBS 是否有待重启事务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Test-Path</span> <span class="s2">&#34;HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">Test-Path</span> <span class="s2">&#34;HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果返回 <code>True</code>，建议先重启。CBS 有 pending reboot 时，<code>Add-WindowsCapability</code> 很容易卡住、失败或重复下载。</p>
<h2 id="正确的代理配置">
<a class="header-anchor" href="#%e6%ad%a3%e7%a1%ae%e7%9a%84%e4%bb%a3%e7%90%86%e9%85%8d%e7%bd%ae"></a>
正确的代理配置
</h2><p>以 <code>127.0.0.1:10809</code> 为例，管理员 PowerShell 执行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">netsh</span> <span class="n">winhttp</span> <span class="nb">set </span><span class="n">proxy</span> <span class="nb">proxy-server</span><span class="p">=</span><span class="s2">&#34;http=127.0.0.1:10809;https=127.0.0.1:10809&#34;</span> <span class="nb">bypass-list</span><span class="p">=</span><span class="s2">&#34;localhost;127.0.0.1;&lt;local&gt;&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>再给 BITS 的三个服务账户设置代理：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">localsystem</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">networkservice</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">localservice</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>重启相关服务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Restart-Service</span> <span class="n">wuauserv</span><span class="p">,</span><span class="n">bits</span><span class="p">,</span><span class="n">DoSvc</span><span class="p">,</span><span class="n">cryptsvc</span> <span class="n">-Force</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果之前已经卡了很久，建议直接重启系统。我的情况就是代理配置正确后仍然卡在 0%，重启清掉 CBS pending 状态后才成功。</p>
<h2 id="重新安装-openssh-server">
<a class="header-anchor" href="#%e9%87%8d%e6%96%b0%e5%ae%89%e8%a3%85-openssh-server"></a>
重新安装 OpenSSH Server
</h2><p>重启后确认代理程序已经启动，端口能连通：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Test-NetConnection</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="py">1</span> <span class="n">-Port</span> <span class="mf">10809</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后执行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">dism</span><span class="p">.</span><span class="py">exe</span> <span class="p">/</span><span class="n">Online</span> <span class="p">/</span><span class="nb">Add-Capability</span> <span class="p">/</span><span class="n">CapabilityName</span><span class="err">:</span><span class="n">OpenSSH</span><span class="p">.</span><span class="n">Server</span><span class="p">~~~~</span><span class="mf">0.0</span><span class="p">.</span><span class="py">1</span><span class="p">.</span><span class="py">0</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>也可以继续使用 PowerShell：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Add-WindowsCapability</span> <span class="n">-Online</span> <span class="n">-Name</span> <span class="n">OpenSSH</span><span class="p">.</span><span class="n">Server</span><span class="p">~~~~</span><span class="mf">0.0</span><span class="p">.</span><span class="py">1</span><span class="p">.</span><span class="py">0</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>注意 capability 名称最后是 <code>0.0.1.0</code>，不要写成 <code>0.0.1.</code>。</p>
<h2 id="安装后启用-sshd">
<a class="header-anchor" href="#%e5%ae%89%e8%a3%85%e5%90%8e%e5%90%af%e7%94%a8-sshd"></a>
安装后启用 sshd
</h2><p>安装成功后检查文件和服务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Test-Path</span> <span class="n">C:</span><span class="p">\</span><span class="n">Windows</span><span class="p">\</span><span class="n">System32</span><span class="p">\</span><span class="n">OpenSSH</span><span class="p">\</span><span class="n">sshd</span><span class="p">.</span><span class="py">exe</span>
</span></span><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">sshd</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>启用并启动服务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-Service</span> <span class="n">-Name</span> <span class="n">sshd</span> <span class="n">-StartupType</span> <span class="n">Automatic</span>
</span></span><span class="line"><span class="cl"><span class="nb">Start-Service</span> <span class="n">-Name</span> <span class="n">sshd</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>开放防火墙 22 端口：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">New-NetFirewallRule</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Name</span> <span class="s2">&#34;OpenSSH-Server-In-TCP&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-DisplayName</span> <span class="s2">&#34;OpenSSH SSH Server (sshd)&#34;</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Enabled</span> <span class="n">True</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Direction</span> <span class="n">Inbound</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Protocol</span> <span class="n">TCP</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-Action</span> <span class="n">Allow</span> <span class="p">`</span>
</span></span><span class="line"><span class="cl">  <span class="n">-LocalPort</span> <span class="mf">22</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果规则已经存在，可以改成所有网络配置文件都生效：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Set-NetFirewallRule</span> <span class="n">-Name</span> <span class="s2">&#34;OpenSSH-Server-In-TCP&#34;</span> <span class="n">-Enabled</span> <span class="n">True</span> <span class="n">-Profile</span> <span class="n">Any</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="验证">
<a class="header-anchor" href="#%e9%aa%8c%e8%af%81"></a>
验证
</h2><p>查看服务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">sshd</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>正常应该是：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Status   : Running
</span></span><span class="line"><span class="cl">StartType: Automatic
</span></span></code></pre></td></tr></table>
</div>
</div><p>查看监听：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">netstat</span> <span class="n">-ano</span> <span class="n">-p</span> <span class="n">tcp</span> <span class="p">|</span> <span class="nb">Select-String</span> <span class="s2">&#34;:22 &#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>正常会看到：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">TCP    0.0.0.0:22    0.0.0.0:0    LISTENING
</span></span></code></pre></td></tr></table>
</div>
</div><p>局域网其他机器连接：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh 用户名@Windows主机IP
</span></span></code></pre></td></tr></table>
</div>
</div><p>例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh fjh1996@192.168.1.10
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="总结">
<a class="header-anchor" href="#%e6%80%bb%e7%bb%93"></a>
总结
</h2><p>这个问题的关键点是：</p>
<ol>
<li><code>http_proxy</code> / <code>https_proxy</code> 只影响当前进程，不足以让 Windows Update 服务走代理。</li>
<li><code>Add-WindowsCapability</code> 背后依赖 Windows Update、BITS 和 CBS。</li>
<li>需要同时配置 WinHTTP 代理和 BITS 服务账户代理。</li>
<li>如果 CBS 已经有 <code>RebootPending</code>，先重启，否则可能一直卡在 <code>DownloadProgress: [0 / 100]</code>。</li>
<li>安装成功后还要启动 <code>sshd</code> 服务并检查防火墙规则。</li>
</ol>
<p>最终有效流程就是：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">netsh</span> <span class="n">winhttp</span> <span class="nb">set </span><span class="n">proxy</span> <span class="nb">proxy-server</span><span class="p">=</span><span class="s2">&#34;http=127.0.0.1:10809;https=127.0.0.1:10809&#34;</span> <span class="nb">bypass-list</span><span class="p">=</span><span class="s2">&#34;localhost;127.0.0.1;&lt;local&gt;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">localsystem</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">networkservice</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span><span class="line"><span class="cl"><span class="n">bitsadmin</span> <span class="p">/</span><span class="n">util</span> <span class="p">/</span><span class="n">setieproxy</span> <span class="n">localservice</span> <span class="n">MANUAL_PROXY</span> <span class="mf">127.0</span><span class="p">.</span><span class="py">0</span><span class="p">.</span><span class="mf">1</span><span class="err">:</span><span class="mf">10809</span> <span class="n">NULL</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Restart-Service</span> <span class="n">wuauserv</span><span class="p">,</span><span class="n">bits</span><span class="p">,</span><span class="n">DoSvc</span><span class="p">,</span><span class="n">cryptsvc</span> <span class="n">-Force</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">dism</span><span class="p">.</span><span class="py">exe</span> <span class="p">/</span><span class="n">Online</span> <span class="p">/</span><span class="nb">Add-Capability</span> <span class="p">/</span><span class="n">CapabilityName</span><span class="err">:</span><span class="n">OpenSSH</span><span class="p">.</span><span class="n">Server</span><span class="p">~~~~</span><span class="mf">0.0</span><span class="p">.</span><span class="py">1</span><span class="p">.</span><span class="py">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">Set-Service</span> <span class="n">-Name</span> <span class="n">sshd</span> <span class="n">-StartupType</span> <span class="n">Automatic</span>
</span></span><span class="line"><span class="cl"><span class="nb">Start-Service</span> <span class="n">-Name</span> <span class="n">sshd</span>
</span></span></code></pre></td></tr></table>
</div>
</div>
        
        <hr><p>本文2026-04-28首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-04-28</p>]]>
      </description>
      
    </item>
    
    

    <item>
      <title>VMware Workstation 虚拟网卡丢失 &#43; VMware Tools 复制粘贴失效的完整排查与修复</title>
      <link>https://cat.fjh1997.top/posts/10604.html</link>
      <pubDate>Thu, 16 Apr 2026 14:38:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/10604.html</guid>
      <description>
        <![CDATA[<h1>VMware Workstation 虚拟网卡丢失 + VMware Tools 复制粘贴失效的完整排查与修复</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <h2 id="问题背景">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af"></a>
问题背景
</h2><p>宿主机 Windows（VMware Workstation 17.6.0），虚拟机 Windows 7 SP1 32位。遇到两个问题：</p>
<ol>
<li>宿主机无法连接虚拟机（ping 不通）</li>
<li>修复网络后，VMware Tools 的复制粘贴功能不工作</li>
</ol>
<p>以下是完整的排查过程。</p>
<h2 id="问题一宿主机无法连接虚拟机">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e4%b8%80%e5%ae%bf%e4%b8%bb%e6%9c%ba%e6%97%a0%e6%b3%95%e8%bf%9e%e6%8e%a5%e8%99%9a%e6%8b%9f%e6%9c%ba"></a>
问题一：宿主机无法连接虚拟机
</h2><h3 id="现象">
<a class="header-anchor" href="#%e7%8e%b0%e8%b1%a1"></a>
现象
</h3><p>虚拟机 IP 为 <code>192.168.191.129</code>（NAT 模式），从宿主机 ping 100% 丢包：</p>
<pre tabindex="0"><code>ping 192.168.191.129
请求超时。
请求超时。
数据包: 已发送 = 2，已接收 = 0，丢失 = 2 (100% 丢失)
</code></pre><h3 id="排查过程">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b"></a>
排查过程
</h3><p>检查宿主机网卡状态：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-NetAdapter</span> <span class="p">|</span> <span class="nb">Format-Table</span> <span class="n">Name</span><span class="p">,</span> <span class="n">InterfaceDescription</span><span class="p">,</span> <span class="n">Status</span><span class="p">,</span> <span class="n">MacAddress</span> <span class="n">-AutoSize</span>
</span></span></code></pre></td></tr></table>
</div>
</div><pre tabindex="0"><code>Name                          InterfaceDescription                       Status      MacAddress
----                          --------------------                       ------      ----------
以太网                        Intel(R) Ethernet Connection (22) I219-LM  Up          F4-F1-9E-42-D8-DD
VMware Network Adapter VMnet1 VMware Virtual Ethernet Adapter for VMnet1 Not Present 00-50-56-C0-00-01
VMware Network Adapter VMnet8 VMware Virtual Ethernet Adapter for VMnet8 Not Present 00-50-56-C0-00-08
</code></pre><p>关键发现：VMnet1（Host-Only）和 VMnet8（NAT）状态都是 <code>Not Present</code>，<code>AdminStatus: Down</code>。</p>
<p>再看 IPv4 地址分配：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-NetIPAddress</span> <span class="n">-AddressFamily</span> <span class="n">IPv4</span> <span class="p">|</span> <span class="nb">Format-Table</span> <span class="n">InterfaceAlias</span><span class="p">,</span> <span class="n">IPAddress</span><span class="p">,</span> <span class="n">PrefixLength</span> <span class="n">-AutoSize</span>
</span></span></code></pre></td></tr></table>
</div>
</div><pre tabindex="0"><code>InterfaceAlias              IPAddress   PrefixLength
--------------              ---------   ------------
以太网                      10.30.17.50           24
Loopback Pseudo-Interface 1 127.0.0.1              8
</code></pre><p>宿主机只有物理网卡有 IP，VMware 虚拟网卡完全没有加载，自然没有到 <code>192.168.191.x</code> 网段的路由。</p>
<p>同时 VMware NAT Service 虽然在运行，但网卡驱动本身没有加载：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="nb">Get-Service</span> <span class="n">-Name</span> <span class="s1">&#39;VMware*&#39;</span> <span class="p">|</span> <span class="nb">Format-Table</span> <span class="n">Name</span><span class="p">,</span> <span class="n">DisplayName</span><span class="p">,</span> <span class="n">Status</span> <span class="n">-AutoSize</span>
</span></span></code></pre></td></tr></table>
</div>
</div><pre tabindex="0"><code>Name                   DisplayName          Status
----                   -----------          ------
VMware NAT Service     VMware NAT Service  Running
VmwareAutostartService VMware 自动启动服务  Stopped
</code></pre><h3 id="根因">
<a class="header-anchor" href="#%e6%a0%b9%e5%9b%a0"></a>
根因
</h3><p>VMware 虚拟网卡驱动未正确加载，网卡处于 <code>Not Present</code> 状态。NAT Service 虽然在跑，但没有对应的虚拟网卡承载流量。</p>
<h3 id="解决方法">
<a class="header-anchor" href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%b3%95"></a>
解决方法
</h3><p>打开 VMware Workstation → Edit → Virtual Network Editor → 点击 &ldquo;Restore Defaults&rdquo;（需要管理员权限）。这会重新创建 VMnet1/VMnet8 并重装虚拟网卡驱动。</p>
<p>如果不行，还可以：</p>
<ul>
<li>在设备管理器中检查是否有被禁用或带感叹号的 VMware 网卡，右键启用或更新驱动</li>
<li>修复安装 VMware Workstation（运行安装程序选 Repair）</li>
</ul>
<p>恢复后虚拟机 IP 变为 <code>192.168.78.128</code>，网络连通。</p>
<h2 id="问题二vmware-tools-服务启动失败">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e4%ba%8cvmware-tools-%e6%9c%8d%e5%8a%a1%e5%90%af%e5%8a%a8%e5%a4%b1%e8%b4%a5"></a>
问题二：VMware Tools 服务启动失败
</h2><h3 id="现象-1">
<a class="header-anchor" href="#%e7%8e%b0%e8%b1%a1-1"></a>
现象
</h3><p>网络恢复后，SSH 进入虚拟机发现 VMware Tools 没有正常工作。</p>
<h3 id="排查过程-1">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b-1"></a>
排查过程
</h3><p>通过 SSH（paramiko）远程执行命令检查（注意：这台 VM 是 Windows 7，不是 Linux）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">sc query VMTools
</span></span></code></pre></td></tr></table>
</div>
</div><pre tabindex="0"><code>SERVICE_NAME: VMTools
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 1  STOPPED
        WIN32_EXIT_CODE    : 183 (0xB7)
</code></pre><p>VMTools 服务状态为 <code>STOPPED</code>，退出码 <code>183</code>（<code>ERROR_ALREADY_EXISTS</code>）。</p>
<p>同时检查进程：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">tasklist <span class="p">|</span> findstr /i vmtoolsd
</span></span></code></pre></td></tr></table>
</div>
</div><p>发现 <code>vmtoolsd.exe</code>（PID 1868）在用户会话（Console Session 1）里运行着——这是用户态的托盘进程，但系统服务层面的 VMTools 没有启动。</p>
<h3 id="根因-1">
<a class="header-anchor" href="#%e6%a0%b9%e5%9b%a0-1"></a>
根因
</h3><p>之前异常退出后残留了用户态 <code>vmtoolsd.exe</code> 进程，占用了资源，导致系统服务启动时报错 183（<code>ERROR_ALREADY_EXISTS</code>，资源冲突）。</p>
<h3 id="解决方法-1">
<a class="header-anchor" href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%b3%95-1"></a>
解决方法
</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl"><span class="p">:</span><span class="c1">: 先杀掉残留的 vmtoolsd 进程</span>
</span></span><span class="line"><span class="cl">taskkill /f /im vmtoolsd.exe
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="c1">: 然后重新启动服务</span>
</span></span><span class="line"><span class="cl">net start VMTools
</span></span></code></pre></td></tr></table>
</div>
</div><p>执行后服务恢复正常：</p>
<pre tabindex="0"><code>SERVICE_NAME: VMTools
        STATE              : 4  RUNNING
        WIN32_EXIT_CODE    : 0
</code></pre><h2 id="问题三复制粘贴仍然不工作">
<a class="header-anchor" href="#%e9%97%ae%e9%a2%98%e4%b8%89%e5%a4%8d%e5%88%b6%e7%b2%98%e8%b4%b4%e4%bb%8d%e7%84%b6%e4%b8%8d%e5%b7%a5%e4%bd%9c"></a>
问题三：复制粘贴仍然不工作
</h2><h3 id="现象-2">
<a class="header-anchor" href="#%e7%8e%b0%e8%b1%a1-2"></a>
现象
</h3><p>VMTools 服务正常运行后，宿主机和虚拟机之间的复制粘贴仍然不可用。</p>
<h3 id="排查过程-2">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b-2"></a>
排查过程
</h3><h4 id="第一步检查用户态进程">
<a class="header-anchor" href="#%e7%ac%ac%e4%b8%80%e6%ad%a5%e6%a3%80%e6%9f%a5%e7%94%a8%e6%88%b7%e6%80%81%e8%bf%9b%e7%a8%8b"></a>
第一步：检查用户态进程
</h4><p>复制粘贴功能依赖两个 <code>vmtoolsd.exe</code> 进程：</p>
<ul>
<li>系统服务进程（Session 0）：负责基础的 Guest-Host 通信</li>
<li>用户态进程 <code>vmtoolsd.exe -n vmusr</code>（桌面会话）：负责加载 <code>dndcp.dll</code> 插件处理剪贴板同步和拖拽</li>
</ul>
<p>检查发现只有系统服务进程在运行，用户态进程缺失。</p>
<p>确认插件文件存在：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl"><span class="k">dir</span> <span class="s2">&#34;C:\Program Files\VMware\VMware Tools\plugins\vmusr&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>dndcp.dll</code>（拖拽和复制粘贴插件）文件完好。</p>
<p>注册表中 VMware User Process 启动项也存在，但重启后用户态进程就是没有自动拉起。</p>
<h4 id="第二步尝试手动启动用户态进程">
<a class="header-anchor" href="#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e5%b0%9d%e8%af%95%e6%89%8b%e5%8a%a8%e5%90%af%e5%8a%a8%e7%94%a8%e6%88%b7%e6%80%81%e8%bf%9b%e7%a8%8b"></a>
第二步：尝试手动启动用户态进程
</h4><p>由于 SSH 会话处于 Session 0（服务会话），直接 <code>start</code> 无法在 Session 1 的桌面上创建进程。通过创建批处理文件 + 计划任务的方式在用户桌面会话中启动：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl"><span class="k">echo</span> start <span class="s2">&#34;&#34;</span> <span class="s2">&#34;C:/PROGRA~1/VMware/VMware Tools/vmtoolsd.exe&#34;</span> -n vmusr <span class="p">&gt;</span> C:/vmusr.bat
</span></span><span class="line"><span class="cl">schtasks /create /tn <span class="s2">&#34;StartVMusr&#34;</span> /tr <span class="s2">&#34;C:/vmusr.bat&#34;</span> /sc once /st 00:00 /f /rl highest
</span></span><span class="line"><span class="cl">schtasks /run /tn <span class="s2">&#34;StartVMusr&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>启动后确认两个进程都在运行：</p>
<ul>
<li>PID 1384 — Services 会话（系统服务）</li>
<li>PID 2772 — Console Session 1，ADMIN 用户（用户态）</li>
</ul>
<p>但复制粘贴仍然不工作，而且重启虚拟机后用户态进程又消失了。说明手动拉起只是临时方案，根本原因在别处。</p>
<h4 id="第三步检查-vmx-配置">
<a class="header-anchor" href="#%e7%ac%ac%e4%b8%89%e6%ad%a5%e6%a3%80%e6%9f%a5-vmx-%e9%85%8d%e7%bd%ae"></a>
第三步：检查 VMX 配置
</h4><p>检查虚拟机的 <code>.vmx</code> 配置文件（<code>D:\Windows 7\Windows 7.vmx</code>），发现只有：</p>
<pre tabindex="0"><code>isolation.tools.hgfs.disable = &#34;FALSE&#34;
</code></pre><p>缺少 copy/paste 相关的配置项。在 VMware Workstation 17 上，如果没有显式启用，默认可能是禁用的。</p>
<p>通过 rpctool 在 Guest 内确认 isolation 状态均为 <code>UNSET</code>，说明 VMX 层面没有显式配置。</p>
<h3 id="根因-2">
<a class="header-anchor" href="#%e6%a0%b9%e5%9b%a0-2"></a>
根因
</h3><p>两个原因叠加：</p>
<ol>
<li>VMX 配置文件中缺少 <code>isolation.tools.copy.disable = &quot;FALSE&quot;</code> 和 <code>isolation.tools.paste.disable = &quot;FALSE&quot;</code> 的显式配置，在 Workstation 17 上默认行为可能是禁用</li>
<li>由于 isolation 配置缺失，用户态 <code>vmtoolsd -n vmusr</code> 进程无法正常自动启动（负责剪贴板同步的进程缺失）</li>
</ol>
<p>也就是说，用户态进程不自动启动的根本原因就是 VMX 里缺少 isolation 配置。加上配置后，重启虚拟机用户态进程就能正常自动拉起了。</p>
<h3 id="解决方法-2">
<a class="header-anchor" href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%b3%95-2"></a>
解决方法
</h3><p>关闭虚拟机，在 <code>.vmx</code> 文件中添加以下三行：</p>
<pre tabindex="0"><code>isolation.tools.copy.disable = &#34;FALSE&#34;
isolation.tools.paste.disable = &#34;FALSE&#34;
isolation.tools.dnd.disable = &#34;FALSE&#34;
</code></pre><p>然后重新启动虚拟机。启动后验证：</p>
<ul>
<li>VMTools 服务正常运行（RUNNING）</li>
<li>用户态 <code>vmtoolsd -n vmusr</code>（Console Session 1）自动启动——之前一直无法自启的问题也一并解决</li>
<li>复制粘贴功能恢复正常</li>
</ul>
<h2 id="总结">
<a class="header-anchor" href="#%e6%80%bb%e7%bb%93"></a>
总结
</h2><table>
  <thead>
      <tr>
          <th>问题</th>
          <th>根因</th>
          <th>解决方法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>宿主机 ping 不通虚拟机</td>
          <td>VMware 虚拟网卡驱动未加载（Not Present）</td>
          <td>Virtual Network Editor → Restore Defaults</td>
      </tr>
      <tr>
          <td>VMTools 服务启动失败（错误码 183）</td>
          <td>残留的用户态 vmtoolsd 进程占用资源</td>
          <td><code>taskkill /f /im vmtoolsd.exe</code> 后重启服务</td>
      </tr>
      <tr>
          <td>复制粘贴不工作 + 用户态 vmtoolsd 不自启</td>
          <td>VMX 缺少 isolation 配置，导致用户态进程无法自启</td>
          <td>在 vmx 中添加 copy/paste/dnd 的 disable=FALSE 配置后重启</td>
      </tr>
  </tbody>
</table>

        
        <hr><p>本文2026-04-16首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-04-16</p>]]>
      </description>
      
        <category>运维排错</category>
      
    </item>
    
  </channel>
</rss>
