从 AxonHub 镜像验真到 DNS 污染排查:一次 VPS 部署前检查记录
从 AxonHub 镜像验真到 DNS 污染排查
这次排查最初不是为了研究 DNS,而是为了在一台已经运行 Aurora 的 VPS 上增加 AxonHub。
服务器资源并不宽裕,现有业务也不能因为新增服务受到影响。因此,在编写 Compose 文件和启动容器之前,先进行了三类部署前检查:确认机器是否还有余量、确认计划使用的端口没有冲突、确认准备拉取的 AxonHub 镜像确实来自预期的官方版本。
DNS 问题正是在第三项检查中被发现的。
本文中的服务器地址、网卡 MAC 等信息均已省略或泛化。网络配置与远程服务器强相关,请先确认自己的配置源,并保留控制台或其他恢复通道。
一、部署 AxonHub 的背景
目标是在现有 Aurora 服务旁边运行 AxonHub,而不是替换或修改 Aurora。服务器大致为 2 核、2 GB 内存,已经运行 8 个容器,因此不能把“Docker 能启动”直接等同于“适合继续增加服务”。
部署前首先查看了内存、Swap、磁盘、CPU 状态、现有容器和 Docker 磁盘占用。得到的关键信息是:
| 检查项 | 当时的情况 | 对部署的影响 |
|---|---|---|
| 可用内存 | 约 790 MiB | 可以尝试,但必须限制 AxonHub 内存 |
| Swap | 已使用约 542 MiB | 说明内存余量不算充足 |
| 磁盘 | 约 20 GB 可用 | 镜像和少量运行数据有空间 |
| CPU | 存在较明显的 steal time | 共享宿主机可能存在资源竞争 |
| 现有服务 | Aurora 相关 8 个容器运行中 | 新服务必须与现有业务隔离 |
| 计划端口 | 8090 未被占用 |
端口层面可以继续规划 |
因此,当时的结论不是简单的“可以部署”,而是:
可以继续准备 AxonHub,但需要设置 CPU 和内存限制,并在启动后复查 Aurora 的资源和健康状态。
到这一步为止,没有启动 AxonHub,也没有修改 Aurora。
二、为什么要先验证 AxonHub 镜像
计划使用的版本是:
docker.io/looplj/axonhub:v0.9.43
v0.9.43 可以在 AxonHub 官方 Releases 中核对。
部署时不能只依赖 v0.9.43 这个标签。标签可以移动,而镜像清单的 SHA-256 digest 才是更稳定的内容标识。因此,先从项目发布信息确认版本和官方镜像,再记录对应的 manifest digest:
sha256:6d14085c7729ff534168198d573cf02ba2899cb765e51db3c7540bc976aea9fd
接下来需要让服务器自己访问 Docker Hub,确认它看到的镜像与事先确认的内容一致:
docker buildx imagetools inspect \
docker.io/looplj/axonhub:v0.9.43
如果这一步成功,后续就可以把部署引用固定到 digest,避免仅凭可变标签决定实际运行内容。
但服务器没有返回镜像清单,而是报出:
x509: certificate is valid for *.facebook.com, ...
not registry-1.docker.io
这意味着服务器访问 Docker Hub 时收到了与目标域名不匹配的证书。部署因此暂停;在原因没有查清之前,不继续执行 docker pull 或启动容器。
三、DaoCloud 镜像站解决了什么问题
服务器的 Docker 已经配置了 DaoCloud HTTPS 镜像站。它可以作为一条独立路径,用来回答两个问题:镜像站的 TLS 是否正常,以及镜像站中的 AxonHub 是否与官方镜像一致。
第一次访问 Registry V2 接口时返回:
HTTP 401 Unauthorized
这里的 401 不是服务故障。Docker Registry V2 的标准流程是先返回认证要求,客户端再到响应头指定的认证地址获取 Bearer Token,最后携带 Token 请求镜像清单。Docker 官方的 Registry authentication 文档记录了相同的 401 → WWW-Authenticate → Bearer Token → 重试请求 流程。
手动完成这段只读认证流程后,镜像站返回的 Docker-Content-Digest 是:
sha256:6d14085c7729ff534168198d573cf02ba2899cb765e51db3c7540bc976aea9fd
它与事先确认的官方 digest 完全一致。Registry V2 API 使用 digest 作为内容寻址标识,并通过 Docker-Content-Digest 响应头返回目标实体的摘要:CNCF Distribution HTTP API V2。由此可以确认:
- DaoCloud 镜像站的 HTTPS 证书验证正常;
- 镜像站中的
looplj/axonhub:v0.9.43与预期官方镜像一致; - AxonHub 镜像本身不是这次报错的原因。
但这一步只是完成了备用路径的镜像验真,并没有解释 Docker Hub 直连为什么会收到 Facebook 证书,也没有实际启动 AxonHub。为了避免以后其他镜像和系统组件继续遇到同类问题,仍需要修复服务器的 DNS 链路。
四、为什么证书错误最终指向 DNS
访问 registry-1.docker.io 时,连接会依次经过:
1. DNS 解析 registry-1.docker.io
2. 连接解析结果的 443 端口
3. 完成 TLS 握手并获取证书
4. 验证证书是否属于 registry-1.docker.io
如果第一步返回了错误 IP,客户端就会连接到错误服务器。对方返回自己的合法证书,客户端在第四步发现证书名称不匹配并中止连接。
因此,*.facebook.com 证书并不表示 Facebook 伪造了 Docker 证书。它说明客户端实际连接到了 Meta/Facebook 的服务器,而 TLS 主机名校验正确地阻止了后续通信。接下来需要确认的是:这个错误地址是否来自 DNS。
五、建立 DNS 对照组
1. 查看系统解析结果
先通过系统当前使用的解析链查询:
resolvectl query registry-1.docker.io
异常结果中出现了 31.13.x.x 和 Meta 使用的 IPv6 地址。无论具体地址如何变化,Docker Registry 域名解析到 Meta/Facebook 地址本身就明显不合理。
2. 对比明文 DNS 与 DoH
同一台服务器通过 Cloudflare DNS over HTTPS 查询时,得到的却是 AWS/CDN 地址。于是形成了第一个关键对照:
同一台服务器、同一个域名
明文 DNS(53 端口) ──→ Meta/Facebook 地址 ❌
DoH(HTTPS 443) ──→ AWS/CDN 地址 ✅
这一步把问题范围从“Docker 整体异常”收缩到了“传统明文 DNS 查询路径异常”。DoH 将查询放在 HTTPS 连接中,路径中的普通网络设备无法像处理明文 UDP DNS 那样直接读取或修改查询内容。IETF 的 DNS 隐私分析指出,传统 DNS 通常不加密,即使后续访问使用 HTTPS,前置的 DNS 查询仍可能成为整条链路中较薄弱的一环:RFC 7626。
3. 比较同一解析器的 UDP 与 TCP
接着直接查询服务器原先使用的 DNS,并分别指定 UDP 与 TCP:
dig @223.5.5.5 registry-1.docker.io A +time=3 +tries=1
dig @223.5.5.5 registry-1.docker.io A +tcp +time=3 +tries=1
dig @223.6.6.6 registry-1.docker.io A +time=3 +tries=1
dig @223.6.6.6 registry-1.docker.io A +tcp +time=3 +tries=1
其中最有诊断价值的一组结果是:
| 查询路径 | 结果 | 判断 |
|---|---|---|
223.6.6.6 UDP 53 |
31.13.70.9 |
错误,指向 Meta/Facebook |
223.6.6.6 TCP 53 |
一组 AWS 地址 | 合理 |
223.5.5.5 UDP 53 |
Meta/Facebook 地址 | 错误 |
223.5.5.5 TCP 53 |
连接被重置 | 异常 |
同一个域名、同一个 DNS 服务器,只改变传输协议,答案却完全不同:
VPS ── UDP 53 ──→ 错误的 Facebook 地址
│
└── TCP 53 ────→ 正常的 AWS 地址
如果真是权威数据或递归解析器缓存本身错误,UDP 与 TCP 通常应返回语义一致的记录。现在 UDP 返回错误地址、TCP 返回合理地址,更像是 UDP 53 路径中出现了伪造响应、透明代理或其他网络干预。
DNS 客户端通常会接受首先到达且与查询 ID、端口和问题字段相匹配的响应。如果路径中的设备比真实解析器更早返回伪造答案,后到的真实答案便可能失去作用。DNS 的抗伪造规范专门讨论了这些匹配条件;TCP 还具有连接状态和序列号,因此通常比无连接的 UDP 更难被第三方伪造:RFC 5452。
仅凭这些客户端侧实验,无法精确证明是哪一台中间设备进行了注入,也不能简单归咎于某个公共 DNS 服务商。但已经足够确认:
问题不在 Docker 镜像本身,也不像 TLS 层故障,而是服务器到传统 DNS 解析器之间的明文查询路径异常。
六、公开研究数据提供的补充证据
到这里,UDP 与 TCP 的对照已经强烈指向 DNS 注入。将异常结果与公开研究数据比对后,又得到了一组补充证据。
本次排查先后观察到了这些地址:
31.13.70.9
31.13.69.169
103.252.114.101
其中前两个地址属于 Meta/Facebook。在 NDSS 2025 论文 Wallbleed 附录公布的伪造 DNS 地址池中:
31.13.70.9位于列表第 338 项;103.252.114.101位于第 356 项;31.13.69.169位于第 448 项。
论文研究的设备会观察特定 DNS 查询并伪造响应,错误地址来自一组会循环使用的池。研究者还发现,有些通信虽然起点和终点都不在中国,却因为实际网络路由经过相关边界而收到了注入响应:NDSS 2025 Wallbleed 论文。此前 USENIX Security 的 GFWatch 研究也通过长期、大规模测量确认了此类 DNS 过滤系统会持续伪造响应:GFWatch 项目介绍。
需要注意,该附录记录的是论文实验查询所对应的地址池,论文也提醒不同注入器和不同查询名使用的池可能不同。因此,这三个 IP 的重合是很强的特征匹配,却不能单独完成对具体设备或运营商的归因。
这也解释了为什么会收到 Facebook 证书:注入系统可能只是从预设地址池中选择了一个假答案,而该地址恰好属于 Meta。Docker 连接过去后,对方正常返回自己的证书,TLS 主机名校验才暴露出 DNS 结果有误。
不过,这里必须守住证据边界:
| 结论 | 证据强度 | 原因 |
|---|---|---|
| 明文 UDP DNS 路径返回了错误答案 | 已确认 | 同一域名、同一解析器的 UDP 与 TCP 结果明显冲突 |
| 错误答案具有已知 DNS 注入地址池特征 | 强证据 | 三个观测地址都出现在公开研究的伪造地址池中 |
| 异常可能发生在 VPS 出口或其上游路由 | 高概率推断 | DoH 正常、UDP 53 异常,符合路径中间设备干预特征 |
| VPS 商家主动进行了污染 | 未证实 | 客户端实验无法定位具体是哪台设备或哪个运营主体 |
| AliDNS 自己把 Docker Hub 配成 Facebook | 很不可能 | 同一 AliDNS 地址通过 TCP 能返回合理答案 |
因此,可以把它判断为具有明显 DNS 注入特征的案例,但现有证据不足以归因到某一家 VPS 商家或某一个具体网络设备。
七、小型 VPS 环境中可能出现问题的原因
严格地说,“小厂 VPS”不是一种网络协议,也不是污染的充分条件。大厂同样可能遭遇线路问题,小厂也可以拥有干净稳定的网络。真正增加风险的通常是下面几层因素叠加。
1. 多层转售与上游路由
一些小型商家并不拥有完整的机房和骨干网络,而是转售上游 VPS、租用机柜、购买廉价国际带宽或混合多家线路。数据包从你的虚拟机出发后,可能依次经过宿主机、虚拟交换机、机房出口、上游运营商和跨境网络。
链路越长、控制权越分散,商家自己也未必能准确说明 UDP 53 在哪一跳被处理。论文记录的“通信双方都在境外,但路由经过相关边界仍触发注入”,正说明地理位置标签并不能代表数据包真实走过的路径。
2. 系统模板、DHCP 与 IPv6 RA
VPS 开机后看到的 DNS 不一定是用户亲手设置的。它可能来自预制系统镜像、Cloud-init、Netplan 文件、DHCP 租约或 IPv6 Router Advertisement。Netplan 官方文档明确说明,在 networkd 后端中,DHCP 下发的 DNS 默认会被采用,甚至优先于静态 DNS;IPv6 RA 也能提供 DNS 信息:Netplan DHCP 与 RA 配置。
这不表示 DHCP 本身有问题,但会造成一种常见现象:用户没有手动配置某个解析器,它却在每次重启后重新出现。如果不找到真正的配置来源,只修改 /etc/resolv.conf 通常无法持久生效。
3. 上游可能部署透明 DNS 代理或流量治理设备
机房或运营商可能为了缓存、审计、合规、反滥用或故障处理,对 53 端口流量进行代理或重定向。也可能什么策略都没打算做,只是中间设备配置错误、规则陈旧或多租户网络互相影响。
从 VPS 内部看,这几种情况的表象很相似:你以为请求发给了 8.8.8.8 或 223.6.6.6,真正回答的却未必是那个地址背后的解析器。没有双端抓包、路由侧日志或运营商配合,仅凭客户端不能断言具体机制。
4. 明文 UDP 53 本来就是最容易被看见的一环
传统 DNS 查询通常以明文发送。IETF 在制定 DoT 时直接指出,未加密 DNS 会暴露给能观察网络信道的设备;DoT 使用专用的 TCP 853 端口建立 TLS 通道,以减少窃听和路径中篡改机会:RFC 7858。Cloudflare 对 DoT 与 DoH 的说明也分别给出了 853 和 443 端口,并明确把防止监视和篡改作为加密 DNS 的目标:Cloudflare 加密 DNS 文档。
这也是本案例中 DoH 正常而 UDP 53 异常的意义:不是“Cloudflare 的答案天生更真”,而是查询换了一条中间设备难以直接读写内容的通道。
5. 普通的系统与运维配置错误
不是每个错误解析都是大型网络审查系统造成的。过期镜像、错误的静态 DNS、失效的本地缓存、被遗忘的 Docker daemon 配置、多个网络管理器争夺 /etc/resolv.conf,都可能产生类似症状。
因此,应先完成 UDP/TCP、不同解析器以及 DoH/DoT 的对照,再讨论问题归因。
八、为什么系统和 Docker 都会一起出错
继续检查实际网络配置:
ls -l /etc/netplan
grep -RniE 'nameservers|dhcp4|dhcp6' /etc/netplan 2>/dev/null
networkctl status ens17
结果确认 DNS 并非由 Docker 单独配置,也不是神秘地来自某个临时 DHCP 租约,而是写在 Netplan 配置文件中:
nameservers:
addresses:
- 223.5.5.5
- 223.6.6.6
实际配置链是:
/etc/netplan/50-network.yaml
↓
Netplan
↓
systemd-networkd
↓
systemd-resolved
↓
系统应用与 Docker
systemd-resolved 会综合全局配置、每条网络链路的静态配置以及 DHCP 等来源选择 DNS 服务器。因此,只改 /etc/resolv.conf 往往不是持久修复;下一次网络重载或重启后,它仍可能被真正的配置源覆盖。Ubuntu 的 systemd-resolved 文档也说明了这些 DNS 来源及 /etc/resolv.conf 的多种管理模式:systemd-resolved 手册。
九、先验证 DoT,再改配置
修复方向是让系统使用支持 DNS over TLS 的解析器,避免继续通过异常的明文 UDP 53 路径查询。但在远程服务器上,绝不能先假定 853 端口可用。
先做只读连通性与证书验证:
timeout 10s openssl s_client \
-connect 1.1.1.1:853 \
-servername cloudflare-dns.com \
-brief \
-verify_return_error </dev/null
timeout 10s openssl s_client \
-connect 8.8.8.8:853 \
-servername dns.google \
-brief \
-verify_return_error </dev/null
本次环境中两个端点都返回了 Verification: OK,说明:
- TCP 853 可以从该 VPS 到达;
- TLS 握手成功;
- 服务端证书可以按指定名称验证。
只有得到这组结果后,才进入修改阶段。如果你的服务器连接超时或被重置,应停下来选择可达的方案,例如经过验证的 DoH 本地代理;不要直接启用严格 DoT,否则所有 DNS 请求都可能失败。
十、最小化、可回滚的修复方案
NodeSeek 的 DNS 净化方案提供了“清理冲突 DNS 来源、统一交给 systemd-resolved、启用加密 DNS”的思路。这个方向值得参考,但一键脚本通常需要兼容 Debian、旧式 ifupdown、dhclient、resolvconf 等多种环境,会同时修改很多位置。
本次服务器已经确认使用的是:
Ubuntu + Netplan + systemd-networkd + systemd-resolved
因此无需修改 /etc/dhcp/dhclient.conf、/etc/network/interfaces 或 /etc/network/if-up.d/,也不需要卸载 resolvconf、重启整个 networking.service。最稳妥的方法是只处理已确认的两个配置层。
1. 备份配置
sudo cp -a /etc/netplan/50-network.yaml \
/etc/netplan/50-network.yaml.bak-$(date +%Y%m%d-%H%M%S)
sudo cp -a /etc/systemd/resolved.conf \
/etc/systemd/resolved.conf.bak-$(date +%Y%m%d-%H%M%S)
如果 VPS 提供商有网页控制台或救援模式,修改远程网络前也应确认它可用。
2. 修改 Netplan 中的 DNS 地址
保留原有 IP、路由、网卡匹配等配置,只替换 nameservers:
network:
version: 2
ethernets:
ens17:
# 原有 addresses、routes、match、set-name 等配置保持不变
nameservers:
addresses:
- 1.1.1.1
- 8.8.8.8
不要直接复制本文的完整网卡示例覆盖自己的文件。静态地址、默认网关、接口名称和缩进都必须以当前服务器为准。
3. 为 systemd-resolved 开启严格 DoT
编辑 /etc/systemd/resolved.conf:
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
DNSOverTLS=yes
LLMNR=no
MulticastDNS=no
这里使用 地址#服务器名称,让 systemd-resolved 在建立 TLS 连接时使用对应的 SNI 并验证证书。DNSOverTLS=yes 是严格模式:如果上游不支持 DoT,DNS 查询会失败,而不会静默退回明文。相关行为可见 Ubuntu 的 resolved.conf 手册。
本次没有加入:
DNSSEC=allow-downgrade
因为 DNSSEC 与 DoT 解决的是不同问题。DoT 保护查询到解析器之间的传输;DNSSEC 验证支持签名的 DNS 数据。当前目标是消除明文传输路径这一变量,先保持改动最小更容易验证。
4. 先检查,再试运行
sudo netplan generate
sudo netplan try
netplan try 会临时应用新配置;如果在时限内没有确认,会尝试自动回滚。官方文档特别指出,它适合远程系统,可降低网络配置错误导致管理员永久失联的风险:Netplan Try 文档。
不过自动回滚并不是备份和带外控制台的替代品。Netplan 文档也提醒,超时或取消后仍应检查配置是否确实恢复。
确认 SSH 与网络都正常后,再重启解析服务:
sudo systemctl restart systemd-resolved
十一、如何验证修复真正闭环
不能以“命令没有报错”作为完成标准。DNS 修复本身至少需要验证四层,之后还要单独完成 AxonHub 的部署验收。
1. 配置层
resolvectl status ens17
检查 DNS 服务器是否已变为 1.1.1.1、8.8.8.8,并确认协议状态中 DoT 已启用。
2. 解析层
resolvectl query registry-1.docker.io
返回地址会随 Docker Hub 的调度变化,不能把某一组 IP 写死为永久标准。判断规则是:不应再出现与 Docker Hub 无关的 Meta/Facebook 地址,并应与可信的加密 DNS 查询结果语义一致。
必要时可以清理本地缓存后复查:
sudo resolvectl flush-caches
resolvectl query registry-1.docker.io
3. TLS 层
openssl s_client \
-connect registry-1.docker.io:443 \
-servername registry-1.docker.io \
-verify_return_error </dev/null
确认不再收到 Facebook 证书,证书验证正常。
4. Docker 层
最后重新执行最初失败的命令:
docker buildx imagetools inspect \
docker.io/looplj/axonhub:v0.9.43
只有这一步能正常读取镜像清单,并且 digest 与事先确认的官方值一致,才算完成从 DNS、TLS 到 Docker Registry 的验证闭环。
原排查记录中已经验证了 DoT 可达并形成了上述修复步骤,但没有保留修改后再次执行镜像检查的最终输出。因此本文不把最后一步描述为“已经验证成功”;实际操作时应以你自己的复查结果为准。
5. AxonHub 部署层
Docker Registry 验证通过后,才能回到最初的 AxonHub 部署目标。后续应当:
- 在 Compose 配置中引用已经确认的镜像 digest,而不是只写版本标签;
- 根据前面的资源评估设置 CPU 和内存限制;
- 只启动 AxonHub 相关服务,不修改现有 Aurora 容器;
- 验证
8090端口上的服务是否可访问,并检查启动日志; - 观察 AxonHub 的实际内存、CPU 和重启状态;
- 再次检查 Aurora 各容器的健康状态和服务器可用内存。
这一步属于部署验收,不能由“DNS 已经修复”自动替代。
十二、本次工作的实际完成边界
为了避免把排查过程写成已经完成的部署,下面按原始记录区分已确认事项与待完成事项:
| 状态 | 项目 |
|---|---|
| 已确认 | 服务器可以继续准备 AxonHub,但资源较紧,需要限制 CPU 和内存 |
| 已确认 | 8090 当时未被占用 |
| 已确认 | AxonHub v0.9.43 的官方镜像与目标 digest |
| 已确认 | DaoCloud 镜像站中的 manifest digest 与官方值一致 |
| 已确认 | Docker Hub 直连异常来自明文 DNS 路径,而不是 AxonHub 镜像 |
| 已确认 | Cloudflare 与 Google 的 DoT 端点在该 VPS 上可达且证书验证通过 |
| 已形成方案 | Netplan 与 systemd-resolved 的最小化、可回滚修改步骤 |
| 原记录未验证 | 修改 DNS 后重新访问 Docker Hub 是否成功 |
| 原记录未执行 | 创建并启动 AxonHub 容器 |
| 原记录未执行 | AxonHub 启动后的功能、资源和 Aurora 回归验证 |
因此,这次工作的直接结果是完成了部署前评估、镜像验真和 DNS 根因定位;AxonHub 的正式启动仍应作为后续独立步骤完成。
十三、如果修改后仍然失败
可以按照下面的分支继续判断:
| 现象 | 优先检查 |
|---|---|
resolvectl 仍显示旧 DNS |
Netplan 是否真正应用、是否还有 DHCP 或其他每链路 DNS 来源 |
| DoT 开启后所有解析失败 | 853 端口可达性、上游 DoT 支持、SNI 与证书验证 |
| 系统解析正常,Docker 仍异常 | Docker daemon 的代理、镜像加速器、容器内独立 DNS 配置 |
| DNS 正常,仍收到错误证书 | 实际连接 IP、HTTP/HTTPS 代理、SNI、出口透明代理 |
| 重启后旧 DNS 恢复 | 是否只临时执行了 resolvectl dns,而未修改持久配置源 |
还可以用以下命令确认 /etc/resolv.conf 的管理方式:
ls -l /etc/resolv.conf
cat /etc/resolv.conf
不要看到它指向 127.0.0.53 就认为配置错误。对于 systemd-resolved 的 stub 模式,这通常是预期行为;真正的上游 DNS 应通过 resolvectl status 查看。
十四、这次排查最值得复用的方法
1. 从错误发生的层级往前追
证书错误发生在 TLS 层,但根因可以在 DNS 层。报错位置不等于故障起点。
2. 每次只改变一个变量
这次最关键的实验不是换了多少公共 DNS,而是:
同一域名 + 同一 DNS + UDP/TCP 对照
同一服务器 + 明文 DNS/DoH 对照
对照实验比盲目更换配置更能说明问题。
3. 先找到真正的配置源
现代 Ubuntu 服务器上,DNS 可能来自 Netplan、systemd-networkd、DHCP、systemd-resolved 或其他网络管理器。只改 /etc/resolv.conf,或者运行一个同时修改所有历史配置位置的脚本,都可能掩盖真正的所有权关系。
4. “净化”不是改得越多越好
通用脚本的价值在于覆盖更多发行版和历史环境,但具体到一台服务器,最安全的修复通常是:识别当前网络栈,只修改拥有这项配置的最少文件。
5. TLS 报错是保护,不是麻烦
正是因为客户端严格校验证书,错误的 DNS 结果才没有悄悄变成一次成功连接。遇到域名不匹配时,不应关闭证书验证,而应继续追查为什么连接到了错误地址。
参考资料
- NodeSeek:净化 DNS,抗主机或上游污染,驯服 DHCP
- AxonHub:官方 Releases
- Docker Docs:Registry authentication
- CNCF Distribution:Registry HTTP API V2
- NDSS 2025:Wallbleed——DNS 注入器的测量与伪造地址池
- USENIX Security 2021:GFWatch——中国 DNS 审查的大规模长期测量
- RFC 5452:DNS 伪造响应的原理与防御
- RFC 7626:DNS 隐私问题
- RFC 7858:DNS over TLS
- Cloudflare:加密 DNS 的 DoT、DoH 与 ODoH
- Ubuntu Manpages:systemd-resolved
- Ubuntu Manpages:resolved.conf
- Netplan:DHCP 与 RA 的 DNS 配置来源
- Netplan Documentation:netplan try