<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tech on HiDa</title><link>https://www.0niu.cn/categories/tech/</link><description>Recent content in Tech on HiDa</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Thu, 21 May 2026 10:50:57 +0800</lastBuildDate><atom:link href="https://www.0niu.cn/categories/tech/index.xml" rel="self" type="application/rss+xml"/><item><title>屏蔽深信服BBC登录页粒子动画</title><link>https://www.0niu.cn/posts/block-sangfor-bbc-particles-animation/</link><pubDate>Thu, 21 May 2026 10:50:57 +0800</pubDate><guid>https://www.0niu.cn/posts/block-sangfor-bbc-particles-animation/</guid><description>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>每次登录深信服 BBC（Business Behavior Control）时，都会被登录页面上那个花里胡哨的粒子动画困扰——漂浮的小点、连线，看起来酷炫，实际毫无用处，纯纯画蛇添足、华而不实，还白白浪费 CPU 和 GPU 资源。&lt;/p></description><content>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>每次登录深信服 BBC（Business Behavior Control）时，都会被登录页面上那个花里胡哨的粒子动画困扰——漂浮的小点、连线，看起来酷炫，实际毫无用处，纯纯画蛇添足、华而不实，还白白浪费 CPU 和 GPU 资源。&lt;/p>
&lt;h2 id="解决方案">解决方案&lt;/h2>
&lt;p>只需要在 uBlock Origin Lite 中添加一条自定义过滤规则，即可屏蔽这个烦人的粒子动画。&lt;/p>
&lt;h3 id="操作步骤">操作步骤&lt;/h3>
&lt;ol>
&lt;li>打开 uBlock Origin Lite 的选项页面（点击扩展图标 → 齿轮图标）&lt;/li>
&lt;li>切换到 &lt;strong>&amp;ldquo;我的规则&amp;rdquo;（My Rules）&lt;/strong> 选项卡&lt;/li>
&lt;li>在规则输入框中添加以下规则：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>&amp;lt;hostip&amp;gt;##canvas.particles-js-canvas-el
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>将 &lt;code>&amp;lt;hostip&amp;gt;&lt;/code> 替换为你的深信服 BBC 服务器地址，例如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>10.0.0.1##canvas.particles-js-canvas-el
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="4">
&lt;li>点击 &lt;strong>&amp;ldquo;应用更改&amp;rdquo;（Apply changes）&lt;/strong>&lt;/li>
&lt;/ol>
&lt;h3 id="规则说明">规则说明&lt;/h3>
&lt;ul>
&lt;li>&lt;code>10.0.0.1&lt;/code> — 你的深信服 BBC 服务器 IP 地址&lt;/li>
&lt;li>&lt;code>##&lt;/code> — uBlock Origin 的元素隐藏语法&lt;/li>
&lt;li>&lt;code>canvas.particles-js-canvas-el&lt;/code> — 粒子动画使用的 Canvas 元素的 CSS 选择器&lt;/li>
&lt;/ul>
&lt;p>这条规则会让 uBlock Origin Lite 直接隐藏该 Canvas 元素，页面不再渲染粒子动画，登录页面瞬间清爽，CPU/GPU 占用也随之降低。&lt;/p>
&lt;h2 id="效果">效果&lt;/h2>
&lt;p>添加规则后，深信服 BBC 登录页面将不再显示粒子动画，只保留干净的登录表单。页面加载更快，资源占用更低。&lt;/p>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/uBlockOrigin/uBlock/wiki/Static-filter-syntax#element-hiding-filters">uBlock Origin Lite — element hiding syntax&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/VincentGarreau/particles.js/">particles.js&lt;/a>&lt;/li>
&lt;/ul></content></item><item><title>firewalld 配置 internal 到 public 区域的流量转发</title><link>https://www.0niu.cn/posts/firewalld-forward-internal-to-public/</link><pubDate>Mon, 18 May 2026 19:22:32 +0800</pubDate><guid>https://www.0niu.cn/posts/firewalld-forward-internal-to-public/</guid><description>&lt;p>firewalld 支持通过 Policy 对象实现跨区域流量转发。本文介绍如何配置策略，允许 internal 区域的流量转发到 public 区域，使内网主机可以通过防火墙访问外部网络。&lt;/p>
&lt;h2 id="前提条件">前提条件&lt;/h2>
&lt;ul>
&lt;li>firewalld 已安装并运行（&lt;code>systemctl status firewalld&lt;/code>）&lt;/li>
&lt;li>有 root 或 sudo 权限&lt;/li>
&lt;li>了解 firewalld 的 Zone 和 Policy 概念&lt;/li>
&lt;/ul></description><content>&lt;p>firewalld 支持通过 Policy 对象实现跨区域流量转发。本文介绍如何配置策略，允许 internal 区域的流量转发到 public 区域，使内网主机可以通过防火墙访问外部网络。&lt;/p>
&lt;h2 id="前提条件">前提条件&lt;/h2>
&lt;ul>
&lt;li>firewalld 已安装并运行（&lt;code>systemctl status firewalld&lt;/code>）&lt;/li>
&lt;li>有 root 或 sudo 权限&lt;/li>
&lt;li>了解 firewalld 的 Zone 和 Policy 概念&lt;/li>
&lt;/ul>
&lt;h2 id="创建转发策略">创建转发策略&lt;/h2>
&lt;p>firewalld 的 Zone 控制接口上的流量方向，而 Policy 用于定义跨区域的流量转发规则。我们需要创建一个 Policy，将 internal 作为入口区域，public 作为出口区域。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 创建新策略&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --new-policy allow-internal-to-public
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 设置入口区域（源）为 internal，出口区域（目标）为 public&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --policy allow-internal-to-public --add-ingress-zone internal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --policy allow-internal-to-public --add-egress-zone public
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 设置动作为 ACCEPT，并给予高优先级（确保不被其他策略覆盖）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --policy allow-internal-to-public --set-target ACCEPT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --policy allow-internal-to-public --set-priority -100
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>关键参数说明：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>参数&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>--add-ingress-zone&lt;/code>&lt;/td>
&lt;td>流量进入的区域（源区域）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--add-egress-zone&lt;/code>&lt;/td>
&lt;td>流量出去的区域（目标区域）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--set-target ACCEPT&lt;/code>&lt;/td>
&lt;td>匹配该策略的流量默认放行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--set-priority -100&lt;/code>&lt;/td>
&lt;td>优先级数值越小越优先，负数确保优先于默认策略&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="开启伪装masquerade">开启伪装（MASQUERADE）&lt;/h2>
&lt;p>为了让内网 IP 的流量通过 public 区域的出口 IP 访问外部网络，需要为 public 区域开启源地址伪装（SNAT）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --permanent --zone&lt;span style="color:#f92672">=&lt;/span>public --add-masquerade
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="启用-ip-转发">启用 IP 转发&lt;/h2>
&lt;p>Linux 内核默认关闭 IP 转发功能，需要手动开启：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 临时启用（重启后失效）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo sysctl -w net.ipv4.ip_forward&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 永久启用&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo net.ipv4.ip_forward&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> | sudo tee -a /etc/sysctl.d/99-ipforward.conf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="重载防火墙">重载防火墙&lt;/h2>
&lt;p>以上所有 &lt;code>--permanent&lt;/code> 操作需要重载后才会生效：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --reload
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="验证配置">验证配置&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看策略列表&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --get-policies
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看策略详情&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --info-policy allow-internal-to-public
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看 public 区域是否开启伪装&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo firewall-cmd --zone&lt;span style="color:#f92672">=&lt;/span>public --query-masquerade
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看 IP 转发状态&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl net.ipv4.ip_forward
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="常见问题">常见问题&lt;/h2>
&lt;p>&lt;strong>内网主机无法访问外部？&lt;/strong> 检查以下几点：&lt;/p>
&lt;ol>
&lt;li>确认 &lt;code>net.ipv4.ip_forward&lt;/code> 已设为 &lt;code>1&lt;/code>&lt;/li>
&lt;li>确认 public 区域的伪装已开启&lt;/li>
&lt;li>确认 internal 区域的接口绑定正确：&lt;code>sudo firewall-cmd --zone=internal --list-all&lt;/code>&lt;/li>
&lt;li>确认内网主机的默认网关指向防火墙的 internal 接口 IP&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>策略优先级被覆盖？&lt;/strong> 使用更小的优先级数值（如 &lt;code>-200&lt;/code>），firewalld 优先级范围是 &lt;code>-32768&lt;/code> 到 &lt;code>32767&lt;/code>，数值越小越优先。&lt;/p>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://firewalld.org/documentation/concepts/policies.html">firewalld 官方文档 - Policies&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://firewalld.org/documentation/man-pages/firewalld.zone.html">firewalld.zone(5) man page&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://firewalld.org/documentation/man-pages/firewalld.policy.html">firewalld.policy(5) man page&lt;/a>&lt;/li>
&lt;/ul></content></item><item><title>在VyOS上运行ZeroTier实现站点间组网</title><link>https://www.0niu.cn/posts/vyos-zerotier-site-to-site/</link><pubDate>Wed, 22 Apr 2026 10:42:28 +0800</pubDate><guid>https://www.0niu.cn/posts/vyos-zerotier-site-to-site/</guid><description>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>VyOS 是一个开源的路由器操作系统，ZeroTier 则是一个易于使用的 SD-WAN 方案。将两者结合，可以用 VyOS 作为各站点的网关设备，通过 ZeroTier 组建虚拟网络，实现站点间的安全通信。&lt;/p>
&lt;p>相比传统的 IPsec VPN 或 BGP over WireGuard 方案，ZeroTier 的优势在于：无需公网 IP、无需手动配置隧道对端、通过 Central 控制台统一管理路由。适合中小规模的多站点部署。&lt;/p></description><content>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>VyOS 是一个开源的路由器操作系统，ZeroTier 则是一个易于使用的 SD-WAN 方案。将两者结合，可以用 VyOS 作为各站点的网关设备，通过 ZeroTier 组建虚拟网络，实现站点间的安全通信。&lt;/p>
&lt;p>相比传统的 IPsec VPN 或 BGP over WireGuard 方案，ZeroTier 的优势在于：无需公网 IP、无需手动配置隧道对端、通过 Central 控制台统一管理路由。适合中小规模的多站点部署。&lt;/p>
&lt;p>本文基于 VyOS 1.4（Rolling Release）和 ZeroTier 官方 Docker 镜像，演示从容器部署到路由配置的完整流程。&lt;/p>
&lt;h2 id="网络拓扑">网络拓扑&lt;/h2>
&lt;p>假设有 3 个站点，每个站点一台 VyOS 路由器，通过 ZeroTier 组网：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Site 1&lt;/strong>：RTR1，本地子网 10.1.0.0/24&lt;/li>
&lt;li>&lt;strong>Site 2&lt;/strong>：RTR2，本地子网 10.2.0.0/24&lt;/li>
&lt;li>&lt;strong>Site 3&lt;/strong>：RTR3，本地子网 10.3.0.0/24&lt;/li>
&lt;/ul>
&lt;p>ZeroTier 虚拟网络分配 10.13.0.0/16，每个节点通过 ZeroTier 自动分配一个 IP。&lt;/p>
&lt;h2 id="基础网络配置">基础网络配置&lt;/h2>
&lt;p>确保每台 VyOS 有互联网连接和 DNS 解析：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>configure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set interfaces ethernet eth0 address dhcp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set system name-server 223.5.5.5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>commit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>save
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>验证连通性：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>ping 223.5.5.5 count 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="部署-zerotier-容器">部署 ZeroTier 容器&lt;/h2>
&lt;p>VyOS 1.4 原生支持容器管理，我们使用 ZeroTier 官方 Docker 镜像。&lt;/p>
&lt;h3 id="1-拉取镜像">1. 拉取镜像&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>add container image zerotier/zerotier:latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>VyOS 1.4 下载镜像时没有进度条，静默等待即可。用以下命令确认：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>show container image
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="2-创建持久化目录">2. 创建持久化目录&lt;/h3>
&lt;p>将 ZeroTier 数据目录映射到 /config/ 下，确保重启后配置不丢失：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>sudo mkdir -p /config/containers/zt1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-配置容器">3. 配置容器&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span style="display:flex;">&lt;span>configure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 allow&lt;span style="color:#f92672">-&lt;/span>host&lt;span style="color:#f92672">-&lt;/span>networks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 cap&lt;span style="color:#f92672">-&lt;/span>add net&lt;span style="color:#f92672">-&lt;/span>admin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 device tun destination &lt;span style="color:#f92672">/&lt;/span>dev&lt;span style="color:#f92672">/&lt;/span>net&lt;span style="color:#f92672">/&lt;/span>tun
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 device tun source &lt;span style="color:#f92672">/&lt;/span>dev&lt;span style="color:#f92672">/&lt;/span>net&lt;span style="color:#f92672">/&lt;/span>tun
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 image zerotier&lt;span style="color:#f92672">/&lt;/span>zerotier:latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 volume ZT_Path destination &lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#66d9ef">var&lt;/span>&lt;span style="color:#f92672">/&lt;/span>lib&lt;span style="color:#f92672">/&lt;/span>zerotier&lt;span style="color:#f92672">-&lt;/span>one
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set container name zt1 volume ZT_Path source &lt;span style="color:#f92672">/&lt;/span>config&lt;span style="color:#f92672">/&lt;/span>containers&lt;span style="color:#f92672">/&lt;/span>zt1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>commit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>save
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>关键参数说明：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>allow-host-networks&lt;/strong>：容器共享宿主网络栈，ZeroTier 创建的接口直接出现在 VyOS 上&lt;/li>
&lt;li>&lt;strong>cap-add net-admin&lt;/strong>：授予容器网络管理权限，允许创建虚拟网卡&lt;/li>
&lt;li>&lt;strong>device tun&lt;/strong>：将宿主的 TUN 设备映射进容器&lt;/li>
&lt;li>&lt;strong>volume ZT_Path&lt;/strong>：持久化 ZeroTier 的身份文件和配置&lt;/li>
&lt;/ul>
&lt;p>验证容器状态：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>show container
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="映射-zerotier-接口">映射 ZeroTier 接口&lt;/h2>
&lt;p>通过 devicemap 文件将 ZeroTier 网络映射为指定的以太网接口（如 zt0），便于后续配置防火墙策略：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>sudo su
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd /config/containers/zt1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cat &amp;gt; devicemap &amp;lt;&amp;lt; EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;NetworkID&amp;gt;=zt0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exit
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>将 &lt;code>&amp;lt;NetworkID&amp;gt;&lt;/code> 替换为你在 ZeroTier Central 创建的网络 ID。然后重启容器使映射生效：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>restart container zt1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="加入-zerotier-网络">加入 ZeroTier 网络&lt;/h2>
&lt;p>进入容器，执行 join 命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>connect container zt1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>zerotier-cli join &amp;lt;NetworkID&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exit
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>返回 &lt;code>200 join OK&lt;/code> 表示加入成功。记录下 &lt;code>zerotier-cli info&lt;/code> 输出的 Node ID。&lt;/p>
&lt;h2 id="在-central-中授权节点">在 Central 中授权节点&lt;/h2>
&lt;p>登录 ZeroTier Central，在对应网络中：&lt;/p>
&lt;ol>
&lt;li>找到新加入的节点，将 Node ID 与各路由器对上&lt;/li>
&lt;li>勾选 Auth 列的复选框授权&lt;/li>
&lt;li>可选：为每个节点设置名称便于识别&lt;/li>
&lt;/ol>
&lt;p>授权后，在 VyOS 上确认接口已获取 IP：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>show interfaces ethernet zt0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>应能看到 ZeroTier 分配的 IP（如 10.13.x.x/16）。&lt;/p>
&lt;h2 id="配置路由">配置路由&lt;/h2>
&lt;h3 id="方法一通过-zerotier-central-推送路由推荐">方法一：通过 ZeroTier Central 推送路由（推荐）&lt;/h3>
&lt;p>在 ZeroTier Central 的 &lt;strong>Managed Routes&lt;/strong> 中添加各站点路由：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>目标网段&lt;/th>
&lt;th>Via（节点 IP）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>10.1.0.0/24&lt;/td>
&lt;td>10.13.x.1（RTR1）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10.2.0.0/24&lt;/td>
&lt;td>10.13.x.2（RTR2）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10.3.0.0/24&lt;/td>
&lt;td>10.13.x.3（RTR3）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>路由会自动下发到所有节点。ZeroTier 将路由 metric 设为 5000，不会覆盖本地更优先的路由。&lt;/p>
&lt;h3 id="方法二在-vyos-上配置静态路由">方法二：在 VyOS 上配置静态路由&lt;/h3>
&lt;p>如果不想依赖 Central 推送，也可以手动在 VyOS 上配置：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>configure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># RTR1 上
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set protocols static route 10.2.0.0/24 next-hop 10.13.x.2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set protocols static route 10.3.0.0/24 next-hop 10.13.x.3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>commit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>save
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="验证连通性">验证连通性&lt;/h2>
&lt;p>查看路由表确认路由已下发：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>show ip route
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>从 RTR1 ping 其他站点：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>ping 10.2.0.1 source-address 10.1.0.1 count 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ping 10.3.0.1 source-address 10.1.0.1 count 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="注意事项">注意事项&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Managed Routes 上限&lt;/strong>：ZeroTier Central 限制每个网络最多 128 条托管路由&lt;/li>
&lt;li>&lt;strong>路由优先级&lt;/strong>：ZeroTier 推送的路由 metric 为 5000，本地静态路由默认 metric 20，后者优先&lt;/li>
&lt;li>&lt;strong>MTU&lt;/strong>：ZeroTier 虚拟接口 MTU 通常为 2800（内部会自动分片），一般无需调整&lt;/li>
&lt;li>&lt;strong>持久化&lt;/strong>：/config/ 下的文件在 save 和重启后会保留，容器数据和 devicemap 都在其中&lt;/li>
&lt;li>&lt;strong>容器自动启动&lt;/strong>：配置 set container name zt1 后，VyOS 重启会自动启动容器&lt;/li>
&lt;/ul>
&lt;h2 id="扩展大规模部署">扩展：大规模部署&lt;/h2>
&lt;p>如果站点数量超过 127 个（128 条路由减去默认路由），或者需要多租户隔离，可以考虑：&lt;/p>
&lt;ul>
&lt;li>使用 BGP over ZeroTier 替代托管路由，实现更灵活的路由策略&lt;/li>
&lt;li>结合 MPLS 实现多租户场景&lt;/li>
&lt;li>自建 ZeroTier Planet/Moon 控制器，脱离 Central 的托管路由限制&lt;/li>
&lt;/ul>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>在 VyOS 上通过容器运行 ZeroTier 是一种轻量且易维护的组网方式。核心步骤只有：拉镜像、配容器、join 网络、授权、配路由。对于没有公网 IP 的站点，ZeroTier 可以通过 NAT 穿透建立 P2P 连接，无需额外的 VPN 网关或 DDNS 配置。&lt;/p>
&lt;p>原文：&lt;a href="https://lev-0.com/2024/06/27/using-zerotier-for-site-to-site-routing-on-vyos/">Using ZeroTier for Site-to-Site Routing on VyOS&lt;/a>&lt;/p></content></item><item><title>redirusr 和 redircmp — Active Directory 默认容器重定向</title><link>https://www.0niu.cn/posts/redirusr-redircmp-active-directory-default-container-redirection/</link><pubDate>Tue, 09 Sep 2025 23:45:00 +0000</pubDate><guid>https://www.0niu.cn/posts/redirusr-redircmp-active-directory-default-container-redirection/</guid><description>&lt;p>Active Directory（AD）新建用户和计算机时，默认存放在 &lt;code>CN=Users&lt;/code> 和 &lt;code>CN=Computers&lt;/code> 容器中。这两个是&lt;strong>容器（Container）&lt;strong>而非&lt;/strong>组织单元（OU）&lt;/strong>，无法直接应用组策略（GPO）。在生产环境中，通常需要将默认位置指向自定义 OU，以便统一管理策略和权限。&lt;/p>
&lt;p>Windows Server 提供了 &lt;code>redirusr.exe&lt;/code> 和 &lt;code>redircmp.exe&lt;/code> 两个内置工具来完成这一操作。&lt;/p></description><content>&lt;p>Active Directory（AD）新建用户和计算机时，默认存放在 &lt;code>CN=Users&lt;/code> 和 &lt;code>CN=Computers&lt;/code> 容器中。这两个是&lt;strong>容器（Container）&lt;strong>而非&lt;/strong>组织单元（OU）&lt;/strong>，无法直接应用组策略（GPO）。在生产环境中，通常需要将默认位置指向自定义 OU，以便统一管理策略和权限。&lt;/p>
&lt;p>Windows Server 提供了 &lt;code>redirusr.exe&lt;/code> 和 &lt;code>redircmp.exe&lt;/code> 两个内置工具来完成这一操作。&lt;/p>
&lt;h2 id="为什么需要重定向">为什么需要重定向&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>对比&lt;/th>
&lt;th>Users / Computers 容器&lt;/th>
&lt;th>自定义 OU&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>类型&lt;/td>
&lt;td>Container（容器）&lt;/td>
&lt;td>OU（组织单元）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GPO 链接&lt;/td>
&lt;td>❌ 不支持&lt;/td>
&lt;td>✅ 支持&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>委派控制&lt;/td>
&lt;td>❌ 不支持&lt;/td>
&lt;td>✅ 支持&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>典型用途&lt;/td>
&lt;td>AD 内置账户、域控制器&lt;/td>
&lt;td>按部门/角色组织管理对象&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>新建用户时如果忘记选择目标 OU，对象就会落入默认容器，导致策略未生效。重定向可以从根本上避免这个问题。&lt;/p>
&lt;/blockquote>
&lt;h2 id="原理wellknownobjects-属性">原理：wellKnownObjects 属性&lt;/h2>
&lt;p>重定向的本质是修改域根对象的 &lt;code>wellKnownObjects&lt;/code> 属性。AD 通过该属性记录几个&lt;strong>知名容器&lt;/strong>的 DN：&lt;/p>
&lt;ul>
&lt;li>&lt;code>CN=Users&lt;/code> → 新建用户默认位置&lt;/li>
&lt;li>&lt;code>CN=Computers&lt;/code> → 新计算机加入域时的默认位置&lt;/li>
&lt;/ul>
&lt;p>&lt;code>redirusr&lt;/code> 和 &lt;code>redircmp&lt;/code> 只是修改这个属性的便捷工具，效果等同于用 ADSI Edit 或 LDP 手动修改。&lt;/p>
&lt;h2 id="使用方法">使用方法&lt;/h2>
&lt;p>两个工具位于域控制器上的 &lt;code>%SystemRoot%\System32&lt;/code> 目录下，语法完全一致。&lt;/p>
&lt;h3 id="redirusr--重定向用户默认容器">redirusr — 重定向用户默认容器&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>redirusr &lt;span style="color:#e6db74">&amp;#34;OU=Staff,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>执行后，所有新建用户将默认放入 &lt;code>OU=Staff,DC=example,DC=com&lt;/code>。&lt;/p>
&lt;h3 id="redircmp--重定向计算机默认容器">redircmp — 重定向计算机默认容器&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>redircmp &lt;span style="color:#e6db74">&amp;#34;OU=Workstations,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>执行后，新计算机加入域时将默认放入 &lt;code>OU=Workstations,DC=example,DC=com&lt;/code>。&lt;/p>
&lt;h3 id="验证">验证&lt;/h3>
&lt;p>通过 ADSI Edit 查看：&lt;/p>
&lt;ol>
&lt;li>打开 ADSI Edit → 连接到默认命名上下文&lt;/li>
&lt;li>右键点击域根节点（如 &lt;code>DC=example,DC=com&lt;/code>）→ 属性&lt;/li>
&lt;li>找到 &lt;code>wellKnownObjects&lt;/code> 属性&lt;/li>
&lt;li>确认 &lt;code>CN=Users&lt;/code> 和 &lt;code>CN=Computers&lt;/code> 对应的 DN 已更新&lt;/li>
&lt;/ol>
&lt;p>也可以用 PowerShell 快速查看：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>Get-ADDomain | Select-Object UsersContainer, ComputersContainer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>重定向后此命令会返回新的 OU 路径。&lt;/p>
&lt;/blockquote>
&lt;h2 id="完整示例">完整示例&lt;/h2>
&lt;p>假设域名为 &lt;code>corp.example.com&lt;/code>，计划结构如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>DC=corp,DC=example,DC=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── OU=Accounts ← 用户默认位置
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── OU=Admins
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── OU=Employees
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── OU=Workstations ← 计算机默认位置
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── OU=Laptops
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── OU=Desktops
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── OU=Servers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── OU=Groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── CN=Users ← 原默认容器（保留，不可删除）
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└── CN=Computers ← 原默认容器（保留，不可删除）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>执行：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 在域控制器上以域管理员身份运行&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>redirusr &lt;span style="color:#e6db74">&amp;#34;OU=Accounts,DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>redircmp &lt;span style="color:#e6db74">&amp;#34;OU=Workstations,DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>之后新建用户 &lt;code>john&lt;/code>，会自动出现在 &lt;code>OU=Accounts&lt;/code> 下而非 &lt;code>CN=Users&lt;/code>。&lt;/p>
&lt;h2 id="注意事项">注意事项&lt;/h2>
&lt;h3 id="1-不可逆">1. 不可逆&lt;/h3>
&lt;p>重定向是&lt;strong>单向操作&lt;/strong>，微软不提供撤销命令。如需回退，只能通过 ADSI Edit 手动将 &lt;code>wellKnownObjects&lt;/code> 中的 DN 改回 &lt;code>CN=Users&lt;/code> / &lt;code>CN=Computers&lt;/code>。&lt;/p>
&lt;h3 id="2-原容器仍存在">2. 原容器仍存在&lt;/h3>
&lt;p>&lt;code>CN=Users&lt;/code> 和 &lt;code>CN=Computers&lt;/code> 容器&lt;strong>不会被删除&lt;/strong>，其中的现有对象也不受影响。已有用户/计算机停留在原位，只有&lt;strong>后续新建&lt;/strong>的对象才会进入新 OU。&lt;/p>
&lt;p>如需将已有对象迁移到新 OU：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 批量移动 CN=Users 下的用户到新 OU&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Get-ADUser -Filter * -SearchBase &lt;span style="color:#e6db74">&amp;#34;CN=Users,DC=corp,DC=example,DC=com&amp;#34;&lt;/span> |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Move-ADObject -TargetPath &lt;span style="color:#e6db74">&amp;#34;OU=Accounts,DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 批量移动 CN=Computers 下的计算机到新 OU&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Get-ADComputer -Filter * -SearchBase &lt;span style="color:#e6db74">&amp;#34;CN=Computers,DC=corp,DC=example,DC=com&amp;#34;&lt;/span> |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Move-ADObject -TargetPath &lt;span style="color:#e6db74">&amp;#34;OU=Workstations,DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-目标-ou-必须已存在">3. 目标 OU 必须已存在&lt;/h3>
&lt;p>执行前确保目标 OU 已创建，否则会报错：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 预先创建 OU&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>New-ADOrganizationalUnit -Name &lt;span style="color:#e6db74">&amp;#34;Accounts&amp;#34;&lt;/span> -Path &lt;span style="color:#e6db74">&amp;#34;DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>New-ADOrganizationalUnit -Name &lt;span style="color:#e6db74">&amp;#34;Workstations&amp;#34;&lt;/span> -Path &lt;span style="color:#e6db74">&amp;#34;DC=corp,DC=example,DC=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="4-不影响手动指定-ou">4. 不影响手动指定 OU&lt;/h3>
&lt;p>通过 ADUC、&lt;code>New-ADUser&lt;/code>、&lt;code>New-ADComputer&lt;/code> 等工具&lt;strong>手动指定了目标 OU 的操作不受影响&lt;/strong>。重定向只改变不指定位置时的默认行为。&lt;/p>
&lt;h3 id="5-需要域管理员权限">5. 需要域管理员权限&lt;/h3>
&lt;p>执行 &lt;code>redirusr&lt;/code> 和 &lt;code>redircmp&lt;/code> 需要域管理员（Domain Admins）权限。&lt;/p>
&lt;h2 id="与其他方法的对比">与其他方法的对比&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>方法&lt;/th>
&lt;th>优点&lt;/th>
&lt;th>缺点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>redirusr / redircmp&lt;/strong>&lt;/td>
&lt;td>简单一行命令，微软官方工具&lt;/td>
&lt;td>不可逆，需手动迁移已有对象&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ADSI Edit 修改 wellKnownObjects&lt;/strong>&lt;/td>
&lt;td>更灵活，可回退&lt;/td>
&lt;td>操作复杂，容易出错&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>脚本创建时指定 OU&lt;/strong>&lt;/td>
&lt;td>完全可控&lt;/td>
&lt;td>无法防止 ADUC 图形界面忘记选择&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Powershell 策略审计&lt;/strong>&lt;/td>
&lt;td>可检测遗漏&lt;/td>
&lt;td>需要额外部署，非根本解决&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>对于大多数场景，&lt;code>redirusr&lt;/code> + &lt;code>redircmp&lt;/code> 是最简单直接的方案。&lt;/p>
&lt;h2 id="最佳实践">最佳实践&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>建域时就执行&lt;/strong>：在新建域之后、创建大量用户之前完成重定向&lt;/li>
&lt;li>&lt;strong>预先创建好 OU 结构&lt;/strong>：规划好组织架构后再执行&lt;/li>
&lt;li>&lt;strong>立即迁移已有对象&lt;/strong>：避免部分对象在新 OU、部分在旧容器造成混乱&lt;/li>
&lt;li>&lt;strong>记录变更&lt;/strong>：在运维文档中记录重定向操作，方便后续排查&lt;/li>
&lt;li>&lt;strong>验证 GPO 生效&lt;/strong>：重定向后创建测试用户/计算机，确认链接到 OU 的 GPO 正常应用&lt;/li>
&lt;/ol></content></item><item><title>使用官方 Registry v2 搭建 Docker Mirror 私有镜像仓库</title><link>https://www.0niu.cn/posts/docker-registry-mirror/</link><pubDate>Mon, 09 Jun 2025 22:51:00 +0800</pubDate><guid>https://www.0niu.cn/posts/docker-registry-mirror/</guid><description>&lt;p>在国内网络环境下，直接从 Docker Hub 拉取镜像经常遇到超时或被限流的问题。搭建一个本地 Docker Mirror 代理仓库可以有效解决这个痛点。本文介绍如何使用官方 Registry v2 搭建私有镜像代理仓库。&lt;/p>
&lt;h2 id="为什么要搭-docker-mirror">为什么要搭 Docker Mirror&lt;/h2>
&lt;h3 id="1-docker-hub-公网限速">1. Docker Hub 公网限速&lt;/h3>
&lt;p>Docker Hub 对匿名用户的拉取限速为 &lt;strong>100 次/6 小时&lt;/strong>，免费账户为 &lt;strong>200 次/6 小时&lt;/strong>。在 CI/CD 流水线或多人团队环境下，这个限额很容易触达。通过自建 Mirror 代理，所有节点的拉取请求汇聚到 Mirror 节点，Mirror 对上游只产生一次请求，有效规避限额。&lt;/p>
&lt;h3 id="2-缓存加速-build">2. 缓存加速 Build&lt;/h3>
&lt;p>在 CI/CD 构建中，每次 &lt;code>docker build&lt;/code> 都需要拉取基础镜像。即使代码没有变化，基础镜像也会被反复从公网拉取，浪费时间。Mirror 缓存了基础镜像后：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>首次构建&lt;/strong>：从上游拉取并缓存&lt;/li>
&lt;li>&lt;strong>后续构建&lt;/strong>：直接从 Mirror 拉取，速度提升 5-10 倍&lt;/li>
&lt;li>&lt;strong>多节点并行构建&lt;/strong>：共享同一个 Mirror，只消耗一次外网流量&lt;/li>
&lt;/ul></description><content>&lt;p>在国内网络环境下，直接从 Docker Hub 拉取镜像经常遇到超时或被限流的问题。搭建一个本地 Docker Mirror 代理仓库可以有效解决这个痛点。本文介绍如何使用官方 Registry v2 搭建私有镜像代理仓库。&lt;/p>
&lt;h2 id="为什么要搭-docker-mirror">为什么要搭 Docker Mirror&lt;/h2>
&lt;h3 id="1-docker-hub-公网限速">1. Docker Hub 公网限速&lt;/h3>
&lt;p>Docker Hub 对匿名用户的拉取限速为 &lt;strong>100 次/6 小时&lt;/strong>，免费账户为 &lt;strong>200 次/6 小时&lt;/strong>。在 CI/CD 流水线或多人团队环境下，这个限额很容易触达。通过自建 Mirror 代理，所有节点的拉取请求汇聚到 Mirror 节点，Mirror 对上游只产生一次请求，有效规避限额。&lt;/p>
&lt;h3 id="2-缓存加速-build">2. 缓存加速 Build&lt;/h3>
&lt;p>在 CI/CD 构建中，每次 &lt;code>docker build&lt;/code> 都需要拉取基础镜像。即使代码没有变化，基础镜像也会被反复从公网拉取，浪费时间。Mirror 缓存了基础镜像后：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>首次构建&lt;/strong>：从上游拉取并缓存&lt;/li>
&lt;li>&lt;strong>后续构建&lt;/strong>：直接从 Mirror 拉取，速度提升 5-10 倍&lt;/li>
&lt;li>&lt;strong>多节点并行构建&lt;/strong>：共享同一个 Mirror，只消耗一次外网流量&lt;/li>
&lt;/ul>
&lt;h3 id="3-离线可用与稳定性">3. 离线可用与稳定性&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>离线可用&lt;/td>
&lt;td>已缓存的镜像在内网环境下随时可用，不依赖外网连接&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>稳定可控&lt;/td>
&lt;td>不受 Docker Hub 宕机、限速、DNS 污染等公网问题影响&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>节省带宽&lt;/td>
&lt;td>多个节点共享缓存，外网出口带宽消耗大幅降低&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="架构说明">架构说明&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Docker Client → Caddy (HTTPS) → Registry v2 (Mirror) → DaoCloud 上游 → Docker Hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↓
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 本地缓存（命中则直接返回）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>整个链路的请求流程：&lt;/p>
&lt;ol>
&lt;li>Docker Client 向 &lt;code>docker pull&lt;/code> 配置的 Mirror 地址发起拉取请求&lt;/li>
&lt;li>请求经 Caddy HTTPS 反向代理转发到 Registry v2&lt;/li>
&lt;li>Registry 检查本地缓存，命中则直接返回&lt;/li>
&lt;li>缓存未命中时，Registry 向 DaoCloud 上游代理转发请求&lt;/li>
&lt;li>DaoCloud 再从 Docker Hub 获取镜像数据并逐层返回&lt;/li>
&lt;li>Registry 将收到的每一层数据写入本地缓存&lt;/li>
&lt;/ol>
&lt;h2 id="环境准备">环境准备&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Docker 20.10+&lt;/strong>：确保 Docker Engine 版本支持 &lt;code>registry-mirrors&lt;/code> 配置&lt;/li>
&lt;li>&lt;strong>域名&lt;/strong>：一个已解析到服务器 IP 的域名，用于 Caddy 自动申请 HTTPS 证书（如 &lt;code>mirror.example.com&lt;/code>）&lt;/li>
&lt;li>&lt;strong>SSD 存储&lt;/strong>：建议至少 100GB 以上，镜像层文件较大且频繁读写，SSD 能显著提升缓存命中后的响应速度&lt;/li>
&lt;li>&lt;strong>开放端口&lt;/strong>：只需开放 443 端口（HTTPS），Registry 本身通过 Docker 内部网络通信，不暴露端口到宿主机&lt;/li>
&lt;/ul>
&lt;h2 id="部署-registry-v2-mirror">部署 Registry v2 Mirror&lt;/h2>
&lt;h3 id="配置文件">配置文件&lt;/h3>
&lt;p>创建 &lt;code>config.yml&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Registry 配置文件版本，当前为 0.1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">version&lt;/span>: &lt;span style="color:#ae81ff">0.1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 日志配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">log&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 日志级别：debug / info / warn / error / fatal，默认 info&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">level&lt;/span>: &lt;span style="color:#ae81ff">info&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 日志格式：json / text / logfmt，默认 logfmt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">formatter&lt;/span>: &lt;span style="color:#ae81ff">logfmt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 附加字段，会添加到每条日志中，默认无&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">fields&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">service&lt;/span>: &lt;span style="color:#ae81ff">registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>: &lt;span style="color:#ae81ff">production&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 存储配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 存储驱动类型，默认 filesystem&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">filesystem&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 镜像层数据的存储根目录，默认 /var/lib/registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">rootdirectory&lt;/span>: &lt;span style="color:#ae81ff">/var/lib/registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 并发文件系统操作的线程数，默认 100&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">maxthreads&lt;/span>: &lt;span style="color:#ae81ff">100&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Blob 描述符缓存，用于加速 manifest 请求&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">blobdescriptor&lt;/span>: &lt;span style="color:#ae81ff">inmemory&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 启用删除 API，允许通过 DELETE 接口删除 blob，默认 false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">delete&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">enabled&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 存储维护任务配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">maintenance&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 上传清理，自动清理未完成的上传文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uploadpurging&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 是否启用上传清理，默认 true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">enabled&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 未完成上传文件的保留时间，超过此时间将被清理，默认 168h（7 天）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">age&lt;/span>: &lt;span style="color:#ae81ff">168h&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 清理检查间隔，默认 24h&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">interval&lt;/span>: &lt;span style="color:#ae81ff">24h&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 是否只预览不实际删除，默认 false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dryrun&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 只读模式开关，设为 true 时拒绝所有写入操作（push、delete），拉取正常&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 可用于 GC 时临时开启，防止并发写入，默认 false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">readonly&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">enabled&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># HTTP 服务器配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">http&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 监听地址和端口，默认 :5000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">addr&lt;/span>: :&lt;span style="color:#ae81ff">5000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 监听的网络接口，默认 localhost（仅本地访问）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">host&lt;/span>: &lt;span style="color:#ae81ff">0.0.0.0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># HTTP 响应头设置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">headers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 防止浏览器 MIME 类型嗅探，安全最佳实践&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">X-Content-Type-Options&lt;/span>: [&lt;span style="color:#ae81ff">nosniff]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># CORS 允许的来源，设为 * 允许所有来源&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">Access-Control-Allow-Origin&lt;/span>: [&lt;span style="color:#e6db74">&amp;#39;*&amp;#39;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># CORS 允许的 HTTP 方法&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">Access-Control-Allow-Methods&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">HEAD&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">GET&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">OPTIONS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># CORS 允许的请求头&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">Access-Control-Allow-Headers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">Authorization&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">Accept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 上游代理配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">proxy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 上游镜像源地址（必填）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">remoteurl&lt;/span>: &lt;span style="color:#ae81ff">https://docker.m.daocloud.io&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 上游认证用户名（可选，公共源不需要）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># username:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 上游认证密码（可选，公共源不需要）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># password:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 健康检查配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">health&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">storagedriver&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 是否启用存储健康检查（默认：true）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">enabled&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 检查间隔（默认：10s）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">interval&lt;/span>: &lt;span style="color:#ae81ff">10s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 连续失败多少次后标记不健康（默认：3）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">threshold&lt;/span>: &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="关键配置项说明">关键配置项说明&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置项&lt;/th>
&lt;th>默认值&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>storage.filesystem.rootdirectory&lt;/code>&lt;/td>
&lt;td>&lt;code>/var/lib/registry&lt;/code>&lt;/td>
&lt;td>镜像存储路径&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>storage.cache.blobdescriptor&lt;/code>&lt;/td>
&lt;td>&lt;code>inmemory&lt;/code>&lt;/td>
&lt;td>Blob 元数据缓存方式，可选 &lt;code>redis&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>storage.delete.enabled&lt;/code>&lt;/td>
&lt;td>&lt;code>false&lt;/code>&lt;/td>
&lt;td>&lt;strong>必须设为 true&lt;/strong>，否则无法执行 GC&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>storage.maintenance.readonly.enabled&lt;/code>&lt;/td>
&lt;td>&lt;code>false&lt;/code>&lt;/td>
&lt;td>只读模式，GC 时临时开启&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>proxy.remoteurl&lt;/code>&lt;/td>
&lt;td>-&lt;/td>
&lt;td>上游镜像源地址&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>health.storagedriver.enabled&lt;/code>&lt;/td>
&lt;td>&lt;code>true&lt;/code>&lt;/td>
&lt;td>存储驱动健康检查&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="上游源选择daocloud">上游源选择：DaoCloud&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>稳定性&lt;/strong>&lt;/td>
&lt;td>DaoCloud 是国内主流容器厂商，镜像站长期维护&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>完整性&lt;/strong>&lt;/td>
&lt;td>同步 Docker Hub 全量镜像&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>速度&lt;/strong>&lt;/td>
&lt;td>国内 CDN 加速&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>免费&lt;/strong>&lt;/td>
&lt;td>公共服务，无需注册&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>其他可选的上游源：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># DaoCloud&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">remoteurl&lt;/span>: &lt;span style="color:#ae81ff">https://docker.m.daocloud.io&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 阿里云&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">remoteurl&lt;/span>: &lt;span style="color:#ae81ff">https://registry.cn-hangzhou.aliyuncs.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 腾讯云&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">remoteurl&lt;/span>: &lt;span style="color:#ae81ff">https://mirror.ccs.tencentyun.com&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>可以部署多个 Mirror 实例使用不同的上游源，互为备份。&lt;/p>
&lt;/blockquote>
&lt;h2 id="缓存类型">缓存类型&lt;/h2>
&lt;p>Registry v2 的 proxy 模式使用以下缓存机制：&lt;/p>
&lt;h3 id="1-blob-缓存层缓存">1. Blob 缓存（层缓存）&lt;/h3>
&lt;p>镜像的每一层（layer）都会被缓存到本地存储：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#66d9ef">var&lt;/span>&lt;span style="color:#f92672">/&lt;/span>lib&lt;span style="color:#f92672">/&lt;/span>registry&lt;span style="color:#f92672">/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">├──&lt;/span> docker&lt;span style="color:#f92672">/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└──&lt;/span> registry&lt;span style="color:#f92672">/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└──&lt;/span> v2&lt;span style="color:#f92672">/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">├──&lt;/span> blobs&lt;span style="color:#f92672">/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└──&lt;/span> sha256&lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#75715e"># 镜像层数据&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└──&lt;/span> repositories&lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#75715e"># 仓库元数据&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="2-manifest-缓存清单缓存">2. Manifest 缓存（清单缓存）&lt;/h3>
&lt;p>镜像的 manifest（包含层关系、tag 等信息）也会被缓存。&lt;/p>
&lt;h3 id="3-blobdescriptor-缓存元数据缓存">3. BlobDescriptor 缓存（元数据缓存）&lt;/h3>
&lt;p>配置 &lt;code>storage.cache.blobdescriptor&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 内存缓存（默认，适合中小规模）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">blobdescriptor&lt;/span>: &lt;span style="color:#ae81ff">inmemory&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Redis 缓存（适合大规模部署）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">blobdescriptor&lt;/span>: &lt;span style="color:#ae81ff">redis&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">addr&lt;/span>: &lt;span style="color:#ae81ff">redis:6379&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">password&lt;/span>: &lt;span style="color:#ae81ff">yourpassword&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">db&lt;/span>: &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ringlimit&lt;/span>: &lt;span style="color:#ae81ff">100&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="缓存策略">缓存策略&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>缓存类型&lt;/th>
&lt;th>说明&lt;/th>
&lt;th>建议场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>inmemory&lt;/code>&lt;/td>
&lt;td>元数据存内存，blob 存磁盘&lt;/td>
&lt;td>镜像数量 &amp;lt; 10000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis&lt;/code>&lt;/td>
&lt;td>元数据存 Redis，blob 存磁盘&lt;/td>
&lt;td>镜像数量 &amp;gt; 10000，多实例&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="缓存未命中">缓存未命中&lt;/h3>
&lt;ol>
&lt;li>Registry 检查本地存储 → 未找到&lt;/li>
&lt;li>转发请求到上游（DaoCloud）&lt;/li>
&lt;li>上游返回数据 → Registry 同时缓存到本地并返回给客户端&lt;/li>
&lt;li>后续请求直接从本地返回&lt;/li>
&lt;/ol>
&lt;h2 id="gc垃圾回收">GC（垃圾回收）&lt;/h2>
&lt;p>随着时间推移，Registry 中会积累大量不再使用的镜像层数据（例如旧版本镜像被更新替换）。GC 用于清理这些无用数据，释放磁盘空间。&lt;/p>
&lt;h3 id="gc-原理">GC 原理&lt;/h3>
&lt;p>Registry 使用 &lt;strong>content-addressable&lt;/strong> 存储，每个 blob 通过 SHA256 哈希标识。GC 的核心逻辑：&lt;/p>
&lt;ol>
&lt;li>标记所有被当前 manifest 引用的 blob&lt;/li>
&lt;li>删除未被引用的 blob（垃圾数据）&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>manifest v2 → 引用 blob A, B, C
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>manifest v1 → 引用 blob A, B, D（旧版本）
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GC 后：blob D 被清除（只被旧 manifest 引用）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="在线-gcread-only-模式">在线 GC（read-only 模式）&lt;/h3>
&lt;p>Registry v2 支持 &lt;strong>只读模式（read-only mode）&lt;/strong>，GC 前切换为只读，避免并发写入导致数据不一致：&lt;/p>
&lt;ol>
&lt;li>将 Registry 切换为只读模式（拒绝写入，拉取正常）&lt;/li>
&lt;li>执行 GC 清理未引用的 blob&lt;/li>
&lt;li>恢复读写模式&lt;/li>
&lt;/ol>
&lt;h4 id="第一步预览dry-run">第一步：预览（dry-run）&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安全操作，不影响服务，建议先执行确认&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec registry-mirror bin/registry garbage-collect &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> /etc/docker/registry/config.yml &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --dry-run
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>ubuntu for sha256:abc123...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>nginx for sha256:def456...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="第二步切换只读--执行-gc--恢复">第二步：切换只读 + 执行 GC + 恢复&lt;/h4>
&lt;blockquote>
&lt;p>&lt;strong>注意&lt;/strong>：不能通过环境变量 &lt;code>REGISTRY_STORAGE_MAINTENANCE_READONLY_ENABLED=true&lt;/code> 设置只读模式，会触发 panic（Registry 的已知 bug，环境变量覆盖 maintenance 子配置时 map key 类型不匹配）。
&lt;strong>正确做法是通过 &lt;code>docker exec&lt;/code> 修改容器内的 config.yml，再用 &lt;code>docker restart&lt;/code> 重载配置&lt;/strong>。&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 1. 开启只读模式 + 重启生效&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec registry-mirror sed -i &lt;span style="color:#e6db74">&amp;#34;/readonly:/,/enabled:/ s/enabled: false/enabled: true/&amp;#34;&lt;/span> /etc/docker/registry/config.yml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker restart registry-mirror
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 2. 等待容器就绪后执行 GC&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec registry-mirror bin/registry garbage-collect /etc/docker/registry/config.yml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 3. 恢复读写模式 + 重启生效&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec registry-mirror sed -i &lt;span style="color:#e6db74">&amp;#34;/readonly:/,/enabled:/ s/enabled: true/enabled: false/&amp;#34;&lt;/span> /etc/docker/registry/config.yml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker restart registry-mirror
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="定期-gc-建议">定期 GC 建议&lt;/h3>
&lt;p>建议通过 cron 定期执行 GC：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 每月 1 号凌晨 3 点执行 GC&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> * * root docker exec registry-mirror sed -i &lt;span style="color:#e6db74">&amp;#34;/readonly:/,/enabled:/ s/enabled: false/enabled: true/&amp;#34;&lt;/span> /etc/docker/registry/config.yml &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> docker restart registry-mirror &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> sleep &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> docker exec registry-mirror bin/registry garbage-collect /etc/docker/registry/config.yml &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> docker exec registry-mirror sed -i &lt;span style="color:#e6db74">&amp;#34;/readonly:/,/enabled:/ s/enabled: true/enabled: false/&amp;#34;&lt;/span> /etc/docker/registry/config.yml &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> docker restart registry-mirror
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="gc-与删除-api-的区别">GC 与删除 API 的区别&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>方式&lt;/th>
&lt;th>作用&lt;/th>
&lt;th>用途&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>DELETE /v2/&amp;lt;name&amp;gt;/manifests/&amp;lt;digest&amp;gt;&lt;/code>&lt;/td>
&lt;td>删除指定 manifest&lt;/td>
&lt;td>删除特定镜像 tag&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>garbage-collect&lt;/code>&lt;/td>
&lt;td>清理未引用的 blob&lt;/td>
&lt;td>回收磁盘空间&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>两者通常配合使用：先通过 DELETE API 删除不需要的 manifest，再执行 GC 释放空间。&lt;/p>
&lt;/blockquote>
&lt;h2 id="caddy-server--https-反向代理">Caddy Server — HTTPS 反向代理&lt;/h2>
&lt;p>Docker 客户端配置 &lt;code>registry-mirrors&lt;/code> 要求使用 HTTPS。使用 &lt;a href="https://caddyserver.com/">Caddy&lt;/a> 的核心优势是 &lt;strong>零配置自动 HTTPS&lt;/strong>，自动申请和续期 Let&amp;rsquo;s Encrypt 证书。&lt;/p>
&lt;h3 id="为什么选-caddy">为什么选 Caddy&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>Caddy&lt;/th>
&lt;th>Nginx&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>HTTPS 证书&lt;/td>
&lt;td>自动申请续期&lt;/td>
&lt;td>需配合 certbot&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>配置复杂度&lt;/td>
&lt;td>极简&lt;/td>
&lt;td>较复杂&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HTTP/3&lt;/td>
&lt;td>原生支持&lt;/td>
&lt;td>需额外编译模块&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>适合场景&lt;/td>
&lt;td>中小规模、快速部署&lt;/td>
&lt;td>大规模、复杂路由&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="caddyfile-配置">Caddyfile 配置&lt;/h3>
&lt;p>创建 &lt;code>Caddyfile&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>mirror.example.com {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverse_proxy registry:5000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> # 上传大镜像需要放宽限制
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> request_body {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> max_size 10GB
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> # Docker 客户端需要的 header
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> header /v2/ Docker-Distribution-Api-Version &amp;#34;registry/2.0&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> # 访问日志
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> output file /data/caddy/access.log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> format console
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> # 健康检查端点不记日志
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> @health path /v2/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log @health {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> output discard
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>确保域名 &lt;code>mirror.example.com&lt;/code> 的 DNS A 记录已指向服务器公网 IP，Caddy 才能自动申请 Let&amp;rsquo;s Encrypt 证书。&lt;/p>
&lt;/blockquote>
&lt;h3 id="完整-docker-composeymlcaddy--registry">完整 docker-compose.yml（Caddy + Registry）&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;3.8&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">caddy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">caddy:2-alpine&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">registry-caddy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">always&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;80:80&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;443:443&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;443:443/udp&amp;#34;&lt;/span> &lt;span style="color:#75715e"># HTTP/3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./Caddyfile:/etc/caddy/Caddyfile&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./caddy_data:/data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./caddy_config:/config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">depends_on&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">registry&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">condition&lt;/span>: &lt;span style="color:#ae81ff">service_healthy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">registry&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">registry:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">registry-mirror&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">always&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 不暴露端口，仅通过 Caddy 访问&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">expose&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;5000&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./data:/var/lib/registry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./config.yml:/etc/docker/registry/config.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">REGISTRY_STORAGE_DELETE_ENABLED=true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">REGISTRY_HTTP_ADDR=0.0.0.0:5000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">healthcheck&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">test&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;CMD&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;wget&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;--spider&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;-q&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;http://localhost:5000/v2/&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">interval&lt;/span>: &lt;span style="color:#ae81ff">30s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">timeout&lt;/span>: &lt;span style="color:#ae81ff">10s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">retries&lt;/span>: &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="启动服务">启动服务&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 启动&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker compose up -d
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看 Caddy 日志，确认证书申请成功&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker logs -f registry-caddy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>看到类似输出表示 HTTPS 证书已自动获取：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>{&amp;#34;level&amp;#34;:&amp;#34;info&amp;#34;,&amp;#34;msg&amp;#34;:&amp;#34;certificate obtained successfully&amp;#34;,&amp;#34;identifier&amp;#34;:&amp;#34;mirror.example.com&amp;#34;}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="验证">验证&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 测试 HTTPS 访问&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl https://mirror.example.com/v2/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 应返回空 JSON：{}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="docker-客户端配置">Docker 客户端配置&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;registry-mirrors&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;https://mirror.example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;insecure-registries&amp;#34;&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>使用 Caddy 提供 HTTPS 后，&lt;strong>不需要&lt;/strong> 配置 &lt;code>insecure-registries&lt;/code>，安全性更好。&lt;/p>
&lt;/blockquote>
&lt;h3 id="caddy-数据持久化">Caddy 数据持久化&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>./caddy_data/ # TLS 证书（自动申请、自动续期）
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./caddy_config/ # Caddy 配置缓存
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>证书续期由 Caddy 自动处理，无需人工干预。&lt;/p>
&lt;h2 id="日常运维">日常运维&lt;/h2>
&lt;h3 id="查看存储占用">查看存储占用&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看缓存目录大小&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>du -sh /data/registry/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看各仓库占用&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>du -sh /data/registry/docker/registry/v2/repositories/*
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="查看日志">查看日志&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker logs -f --tail &lt;span style="color:#ae81ff">100&lt;/span> registry-mirror
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker logs -f --tail &lt;span style="color:#ae81ff">100&lt;/span> registry-caddy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="健康检查">健康检查&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 检查服务状态&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl https://mirror.example.com/v2/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 检查上游连通性&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl https://mirror.example.com/v2/_catalog
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="完整目录结构">完整目录结构&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>docker-mirror/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── docker-compose.yml # Caddy + Registry
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── Caddyfile # Caddy HTTPS 反向代理配置
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── config.yml # Registry 配置
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── data/ # Registry 镜像缓存
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── caddy_data/ # Caddy TLS 证书
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└── caddy_config/ # Caddy 配置缓存
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="总结">总结&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>要点&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>核心组件&lt;/td>
&lt;td>官方 Registry v2 + proxy 模式&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HTTPS 代理&lt;/td>
&lt;td>Caddy（零配置自动 HTTPS、证书自动续期）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>上游源&lt;/td>
&lt;td>DaoCloud（稳定、完整、免费）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>缓存加速&lt;/td>
&lt;td>Blob 磁盘缓存 + 元数据内存/Redis 缓存，加速 CI/CD Build&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GC&lt;/td>
&lt;td>read-only 模式 + docker exec，防止并发写入&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>运维要点&lt;/td>
&lt;td>监控磁盘用量、定期 GC、关注上游可用性&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>对于内网 Docker 环境，搭建一个 Mirror 代理仓库是性价比极高的基础设施投入，一次部署长期受益。&lt;/p></content></item><item><title>使用 resolvectl 临时指定 DNS 服务器</title><link>https://www.0niu.cn/posts/resolvectl-temporary-dns/</link><pubDate>Thu, 08 May 2025 10:16:00 +0800</pubDate><guid>https://www.0niu.cn/posts/resolvectl-temporary-dns/</guid><description>&lt;p>在日常运维中，我们经常需要临时切换 DNS 服务器来排查域名解析问题。传统做法是修改 &lt;code>/etc/resolv.conf&lt;/code>，但在使用 systemd-resolved 的现代 Linux 发行版中，&lt;code>resolvectl&lt;/code> 提供了更优雅的解决方案。&lt;/p></description><content>&lt;p>在日常运维中，我们经常需要临时切换 DNS 服务器来排查域名解析问题。传统做法是修改 &lt;code>/etc/resolv.conf&lt;/code>，但在使用 systemd-resolved 的现代 Linux 发行版中，&lt;code>resolvectl&lt;/code> 提供了更优雅的解决方案。&lt;/p>
&lt;h2 id="为什么用-resolvectl">为什么用 resolvectl&lt;/h2>
&lt;p>传统的修改 &lt;code>/etc/resolv.conf&lt;/code> 方式有几个痛点：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>systemd-resolved 管理下会被覆盖&lt;/strong>：直接编辑 &lt;code>/etc/resolv.conf&lt;/code> 可能无效，因为该文件是一个指向 &lt;code>/run/systemd/resolve/stub-resolv.conf&lt;/code> 的符号链接&lt;/li>
&lt;li>&lt;strong>需要 root 权限&lt;/strong>：编辑系统文件必须 sudo&lt;/li>
&lt;li>&lt;strong>容易忘记还原&lt;/strong>：排查完问题后忘记改回来，可能影响业务&lt;/li>
&lt;/ul>
&lt;p>而 &lt;code>resolvectl&lt;/code> 的优势：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>传统方式&lt;/th>
&lt;th>resolvectl&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>修改配置文件&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>❌&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>需要 root&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>❌（per-link）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>重启后恢复&lt;/td>
&lt;td>需手动还原&lt;/td>
&lt;td>✅ 自动恢复&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>影响范围&lt;/td>
&lt;td>全局&lt;/td>
&lt;td>可按网卡控制&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="查看当前-dns-状态">查看当前 DNS 状态&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看全局 DNS 配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl status
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看指定网卡&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl status eth0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看当前生效的 DNS 服务器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl dns
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Global
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Resolving DNS Servers: 192.168.1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Fallback DNS Servers: 8.8.8.8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Link 2 (eth0)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Current Scopes: DNS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Resolving DNS Servers: 192.168.1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DNS Domain: lan
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="临时指定-dnsper-link">临时指定 DNS（per-link）&lt;/h2>
&lt;h3 id="指定单网卡-dns">指定单网卡 DNS&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 将 eth0 的 DNS 指定为 Google DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 8.8.8.8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 指定多个 DNS（主备）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 8.8.8.8 1.1.1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 指定国内 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 223.5.5.5 119.29.29.29
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="验证生效">验证生效&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看当前 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl dns eth0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 测试解析&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl query example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 使用指定 DNS 解析&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl query example.com --interface&lt;span style="color:#f92672">=&lt;/span>eth0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="恢复默认-dns">恢复默认 DNS&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 恢复为空（回退到全局配置）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 恢复为 DHCP 下发的 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl revert eth0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="全局临时指定-dns">全局临时指定 DNS&lt;/h2>
&lt;p>如果需要全局修改（影响所有网卡）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 设置全局 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns 8.8.8.8 1.1.1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 恢复全局 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>⚠️ 全局修改同样会在重启后恢复，但会影响所有网卡的 DNS 解析。&lt;/p>
&lt;/blockquote>
&lt;h2 id="常用国内公共-dns">常用国内公共 DNS&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>DNS 服务商&lt;/th>
&lt;th>地址&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>阿里&lt;/td>
&lt;td>223.5.5.5 / 223.6.6.6&lt;/td>
&lt;td>稳定快速&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>腾讯&lt;/td>
&lt;td>119.29.29.29&lt;/td>
&lt;td>DNSPod&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>百度&lt;/td>
&lt;td>180.76.76.76&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>114 DNS&lt;/td>
&lt;td>114.114.114.114&lt;/td>
&lt;td>老牌公共 DNS&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Google&lt;/td>
&lt;td>8.8.8.8 / 8.8.4.4&lt;/td>
&lt;td>海外推荐&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Cloudflare&lt;/td>
&lt;td>1.1.1.1 / 1.0.0.1&lt;/td>
&lt;td>海外&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="实战场景">实战场景&lt;/h2>
&lt;h3 id="场景一排查域名解析故障">场景一：排查域名解析故障&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 1. 查看当前 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl dns
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 2. 临时切换到公共 DNS 验证&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 223.5.5.5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 3. 测试解析&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl query api.example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 4. 如果公共 DNS 正常，说明内网 DNS 有问题&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 5. 恢复原配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl revert eth0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="场景二测试-dohdot">场景二：测试 DoH/DoT&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看是否支持 DNS over TLS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl status | grep -i tls
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 开启 DNS over TLS（需要 DNS 服务器支持）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns-over-tls eth0 yes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 tls://dns.google
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="场景三多网卡环境指定-dns">场景三：多网卡环境指定 DNS&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># eth0 走内网 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth0 192.168.1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># eth1 走公共 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resolvectl dns eth1 223.5.5.5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查询时指定网卡&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl query internal.example.com --interface&lt;span style="color:#f92672">=&lt;/span>eth0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>resolvectl query www.0niu.cn --interface&lt;span style="color:#f92672">=&lt;/span>eth1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="注意事项">注意事项&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>临时性&lt;/strong>：&lt;code>resolvectl&lt;/code> 的修改在系统重启后会自动恢复为配置文件中的默认值&lt;/li>
&lt;li>&lt;strong>与 NetworkManager 冲突&lt;/strong>：如果使用 NetworkManager 管理 DNS，可能会被 NM 覆盖，可以设置 &lt;code>NM_CONTROLLED=no&lt;/code> 或在 NM 配置中指定 DNS&lt;/li>
&lt;li>&lt;strong>systemd-resolved 必须运行&lt;/strong>：确认服务状态 &lt;code>systemctl status systemd-resolved&lt;/code>&lt;/li>
&lt;li>&lt;strong>域名搜索后缀&lt;/strong>：可以使用 &lt;code>resolvectl domain eth0 example.com&lt;/code> 临时添加搜索域&lt;/li>
&lt;/ol>
&lt;h2 id="总结">总结&lt;/h2>
&lt;p>&lt;code>resolvectl&lt;/code> 是 systemd-resolved 提供的 DNS 管理工具，用于临时切换 DNS 非常方便：&lt;/p>
&lt;ul>
&lt;li>✅ 无需修改配置文件&lt;/li>
&lt;li>✅ 重启自动恢复&lt;/li>
&lt;li>✅ 可按网卡粒度控制&lt;/li>
&lt;li>✅ 支持 DNS over TLS&lt;/li>
&lt;/ul>
&lt;p>下次排查 DNS 问题时，不妨试试 &lt;code>resolvectl&lt;/code>。&lt;/p></content></item></channel></rss>