首页
关于本站
私人 DNS 加密设置教程
全部文章
推荐
加密 DNS 服务
DNS 实时战报
过滤规则订阅
搜索
网络与 DNS
加密 DNS 实操
路由器与家庭网络
自建服务
AdGuard Home
服务器运维
开发与工具
安全与隐私
登录
搜索
23-4.CN
累计撰写
59
篇文章
累计收到
3
条评论
首页
分类
网络与 DNS
加密 DNS 实操
路由器与家庭网络
自建服务
AdGuard Home
服务器运维
开发与工具
安全与隐私
页面
关于本站
私人 DNS 加密设置教程
全部文章
推荐
加密 DNS 服务
DNS 实时战报
过滤规则订阅
注册丨登录
搜索到
38
篇
分类为
网络与 DNS
的文章
2026-10-24
加密 DNS 的 ECS 到底传了什么:/24 与 /56 分别暴露你的位置
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报用了加密 DNS,查询内容确实没人能看了。但你有没有想过:你的解析器把什么信息交给了下一跳?这里有个不太被讨论的机制叫 ECS(EDNS Client Subnet)。简单说:你的解析器在向上游权威服务器查询时,可能附带上你的 IP 网段(通常是 /24,IPv6 是 /56),好让 CDN 返回离你最近的节点。它不是泄露——因为接收方是你的解析器指定的上游,不是运营商。但它确实把你的位置信息往下游传了一层,而且大多数人不知道自己用的 DNS 传不传。这篇给一套可执行的判定方法,以及一个反直觉的结论:加密不等于不带 ECS,带了 ECS 也不等于不安全。下面所有输出都是我在一台 Ubuntu 20.04(dig 9.18.30)上实际跑出来的。一、先搞清楚 ECS 想解决什么问题不带 ECS 时,权威服务器只能看到递归解析器的出口 IP。假设你的解析器在 A 地,你在 B 地,那么:权威服务器(比如某个 CDN)认为「请求来自 A 地」;于是返回了 A 地附近的节点;你实际在 B 地,被调度到了一个绕远的节点。这就是「用公共 DNS 后访问变慢」的经典原因之一。带 ECS 时,解析器会告诉权威服务器:「请求来自 1.2.3.0/24 这个网段」。权威服务器就能返回那个网段附近的节点。代价:你的网段信息被传下去了。二、怎么测一个 DNS 到底传不传 ECSdig 有一个 +subnet 参数,可以携带 ECS 选项。如果服务端回显了这个选项,说明它处理了 ECS;如果不回显,说明它忽略了。测本站的加密 DNS(DoT)dig +tls +subnet=1.2.3.0/24 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS"实测输出:; EDNS: version: 0, flags:; udp: 1232只有 EDNS 段,没有 CLIENT-SUBNET 行。 说明这个服务没有回显 ECS——它把我的 /24 丢掉了。作为对照,换一个会回显的公共 DNS:dig +subnet=1.2.3.0/24 @223.5.5.5 example.com | grep -iE "CLIENT-SUBNET|EDNS"实测:; EDNS: version: 0, flags:; udp: 1232 ; CLIENT-SUBNET: 1.2.3.0/24/24多了一行 CLIENT-SUBNET。这一行值得拆开看:1.2.3.0/24/24 是三个字段:字段值含义第 1 段1.2.3.0网段地址(我传进去的)第 2 段/24源前缀长度(我传进去的)第 3 段/24作用域前缀长度(解析器决定往下传多少)第三个数字最关键——它才是解析器「愿意暴露多少」的实际值。你传 /24,它可能只传 /24、也可能截短到 /16,甚至传 /0(等于不带)。这个第三个数字,我实测出了它的真实作用故意传一个更长的前缀,看它会不会被截短:dig +subnet=1.2.3.4/32 @223.5.5.5 example.com | grep CLIENT-SUBNET实测:; CLIENT-SUBNET: 1.2.3.4/32/24我传的是 /32(精确到单个 IP),但回显的第三个字段是 /24。这说明解析器把我的 /32 截短到了 /24 才往下传。 它在保护我——即使客户端(或某个上游)想暴露精确 IP,它也只放行到网段级别。再传一个更短的,看会不会被拉长:dig +subnet=1.2.0.0/16 @223.5.5.5 example.com | grep CLIENT-SUBNET实测:; CLIENT-SUBNET: 1.2.0.0/16/24我传 /16,回显是 /16/24。第三个字段还是 /24——但注意:第二个字段(我传的)是 /16,第三个(作用域)是 /24。这两个数字的含义不同:第 2 段 /16 = 「我告诉你我在 1.2.0.0/16 里」;第 3 段 /24 = 「你可以按 /24 的粒度来对待我」。作用域比源前缀更长(/24 > /16)是合法的——意思是「你可以假设我更精确到这个程度」。真正防止暴露的是源前缀:我传 /16,权威服务器就只知道 /16。⇒ 关键结论:/32 会被截到 /24,但 /16 不会被拉到 /24。所以「传更短的」是安全的,「传更长的」要看解析器是否截断。IPv6 同理:dig +subnet=2001:db8::/56 @223.5.5.5 example.com | grep CLIENT-SUBNET实测:; CLIENT-SUBNET: 2001:db8::/56/64传 /56,作用域是 /64。这说明 /56 是「源前缀」,/64 是「作用域」——和 IPv4 的 /24 是同一个位置的角色。这就是判定 ECS 的可执行判据:同一个参数打两个 DNS,一个回显 CLIENT-SUBNET 一个不回显,差别一目了然,比看任何文档都直接。三、/24 和 /56 分别暴露了什么IPv4 的 /24 是 256 个地址;IPv6 的 /56 是 2^(128-56) = 2^72 个地址。看起来 IPv6 的 /56 大得离谱,但实际上:协议常见 ECS 长度相当于能定位到IPv4/24256 个地址一个小区/一栋楼IPv4/321 个地址你自己IPv6/562^72 个地址一个运营商的一个片区IPv6/642^64 个地址一个子网(通常一户)IPv6/0—不暴露(等于关闭)关键点:/24 和 /56 不是「一样安全」的两种选择,它们定位精度差得很远。IPv4 /24 → 256 个地址,能定位到一个接入点;IPv6 /56 → 虽然地址数巨大,但 IPv6 的分配策略通常按「一个片区一个 /56」,所以它同样能定位到一个片区。所以规范(RFC 7871)给的建议是:ECS 应该使用 /24(IPv4)和 /56(IPv6)作为默认上限,不要传更长的前缀。但现实中也有解析器传 /32——那就是把你的确切 IP 交出去了。想主动关掉,用 /0:dig +tls +subnet=0.0.0.0/0 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS"实测:; EDNS: version: 0, flags:; udp: 1232/0 的语义是「我的网段是 0.0.0.0/0」,等于告诉解析器「别带我的任何前缀」。四、三个常见误解误解 1:「用了加密 DNS 就没有 ECS 了」不成立。 加密和 ECS 是两个正交的维度: 不带 ECS带 ECS明文 DNS运营商能看到全部查询运营商能看到查询 + 你的网段加密 DNS运营商看不到查询运营商看不到查询,但上游能看到你的网段加密解决的是「链路上谁能看到」,ECS 决定的是「下游知道多少」。两者可以任意组合。上面的实测就是证据:dns.23-4.cn 是加密的(DoT),且不带 ECS;223.5.5.5 是明文的,且带 ECS。但也存在加密且带 ECS 的服务,只是我没在这台机器上遇到。误解 2:「ECS 是泄露」不是。 泄露(leak)的定义是「查询到了你没授权的解析器」。ECS 里的接收方是你自己选的解析器的上游,是授权链路的一部分。真正的区别是告知范围:不带 ECS → 上游只知道「某个解析器问了我」;带 ECS → 上游知道「某个解析器替 1.2.3.0/24 问我」。这是精度问题,不是授权问题。把它叫「泄露」会让讨论失焦。误解 3:「关掉 ECS 一定更好」不一定。 关掉 ECS 的代价是调度精度下降:用 CDN 的站点,你可能被调度到远端节点,延迟上升;某些按地域做负载均衡的服务,会给你返回错误的节点。所以选择是:你的优先级建议隐私优先(不想暴露任何位置)关 ECS(/0),接受可能的调度偏差速度优先(CDN 命中率重要)保留 /24 / /56,这是规范推荐的上限折中只在特定域名上带 ECS,其余关掉(需要解析器支持按域名配置)⛔ 绝对不要用 /32 或 /128 ——那等于把你的确切 IP 交出去,没有任何性能收益能抵消这个代价。五、自己验证的三条命令# 1. 你的加密 DNS 传不传 ECS(回显 CLIENT-SUBNET 就是传) dig +tls +subnet=1.2.3.0/24 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS" # 2. 对照组(一个已知会回显的公共 DNS) dig +subnet=1.2.3.0/24 @223.5.5.5 example.com | grep -iE "CLIENT-SUBNET|EDNS" # 3. 主动关闭(/0) dig +tls +subnet=0.0.0.0/0 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS"怎么读结果:出现 CLIENT-SUBNET: x.x.x.0/NN/NN → 服务处理 ECS,看第三个数字判断实际传多长;只有 EDNS 没有 CLIENT-SUBNET → 服务忽略 ECS(你的网段没被传下去);报错或超时 → 该服务不支持 ECS 选项,或者你打错了端口。验证做对了没有:第 1 条和第 2 条的结果必须不同。如果两条输出一模一样,说明你的 dig +subnet 根本没生效(老版本不支持这个参数),换个版本或者用 kdig。六、为什么这件事值得单独讲大部分人配加密 DNS 时只关心一件事:查询内容有没有被看到。这当然重要,但它只是隐私的一个维度。完整的图景是三层:链路层:谁能看到你的查询 → 由加密(DoT/DoH/DoQ)解决;内容层:查询内容被记录多久 → 由服务商的日志政策决定;元数据层:你的位置/网段信息传了多远 → 由 ECS 决定。三层里最容易忽略的是第三层,因为它不体现在任何一个「安全」字样上,也没有任何界面会提示你。但它恰恰是唯一一条能直接把「一个 IP」关联到「一个地理片区」的信息。而它的判定方法简单到只有一条 dig +subnet 命令——这就是为什么值得单独写一篇。相关阅读怎么验证加密 DNS 真的生效:dig +tls / +https 与 curl 四步逐层排查dnsleaktest 显示多个 DNS 服务器?先分清是泄露还是正常现象私人 DNS 是什么、适合谁:一份不带玄学的判断清单
2026年10月24日
38 阅读
0 评论
0 点赞
2026-10-24
dnsleaktest 显示多个 DNS 服务器?先分清是泄露还是正常现象
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报跑完一个 DNS 泄露检测,看到页面上列出四五个 DNS 服务器,位置散落在好几个城市甚至不同国家——第一反应通常是「我明明只配了一个加密 DNS,怎么泄露了这么多?」绝大多数情况下那不是泄露。检测工具列出多个服务器,有三种完全正常的解释,而且这三种的判定方法各不相同。这篇给一套可执行的判定流程,用你自己机器上的命令,不依赖任何第三方页面的结论。下面所有输出都是我在一台 Ubuntu 20.04(dig 9.18.30)上实际跑出来的。一、先搞清楚检测工具在测什么所有 DNS 泄露检测的原理都一样:让你发起 N 次随机子域名的查询,然后问「这些查询最终是谁回答的」。具体做法通常是给你一个独一无二的子域名(比如 abc123.dnsleaktest.com),你查它,它看这次查询从哪个 IP、经过哪台解析器到达。所以它报告的「DNS 服务器列表」,本质是「你的查询最终落到了哪些递归解析器上」。关键点:列表里有多个,只说明你的查询分流到了多台解析器,不说明这些解析器不该看到你的查询。二、三种正常情况,逐个判情况 1:你有多个出口 IP(多网卡 / 双栈 / 多线)这是最常见的一种。一台机器同时有 IPv4 和 IPv6,或者接了多条线路,那么:查 A 记录可能从 IPv4 出口出去;查 AAAA 记录从 IPv6 出口出去;检测工具看到两个来源,就报两台服务器。我手上这台机器就是这样。看它的实际解析路径:dig +tls @dns.23-4.cn example.com实测输出(注意 SERVER 那一行是 IPv6):;; ANSWER SECTION: example.com. 162 IN A 104.20.23.154 example.com. 162 IN A 172.66.147.243 ;; Query time: 28 msec ;; SERVER: 240e:95d:3020:43::4006#853(dns.23-4.cn) (TLS)而如果强制走 IPv4 传输:dig +tls -4 @dns.23-4.cn example.com | grep SERVERSERVER 行会变成 IPv4 地址。两个不同的服务器地址,落在检测工具眼里就是「两个 DNS 服务器」。但它们是同一个服务,只是走了不同协议栈。判定方法:把两条路径分别打出来,看 SERVER 行。echo "--- IPv4 传输 ---" dig +short +tls -4 @dns.23-4.cn example.com echo "--- IPv6 传输 ---" dig +short +tls -6 @dns.23-4.cn example.com实测这台机器两条都通,解析结果完全一致:--- IPv4 传输 --- 104.20.23.154 172.66.147.243 --- IPv6 传输 --- 104.20.23.154 172.66.147.243如果检测工具报的服务器数正好是 2,且你确实是双栈,基本可以判定是这种情况,不是泄露。情况 2:服务端有多台节点(Anycast / 负载均衡)加密 DNS 服务商通常会在多个地点部署节点,用 Anycast 让你的查询落到「网络距离最近」的那台。你从不同时间、不同网络去查,落到的节点会不一样。这类「多个服务器」的特征是:IP 会变,但都属于同一个服务商、同一个域名。判定方法:反复查同一件事,看 IP 是否漂移。for i in 1 2 3 4 5; do dig +short +tls @dns.23-4.cn example.com | head -1 sleep 1 done如果每次拿到的解析结果稳定(这里是 A 记录,跟解析器 IP 无关),说明服务本身没问题;要判断节点是否漂移,得看 SERVER 行:for i in 1 2 3 4 5; do dig +tls @dns.23-4.cn example.com 2>/dev/null | grep -oP 'SERVER: \K[^#]+' done | sort | uniq -c出现多个 IP 但都在同一个网段/同一家,就是 Anycast 正常表现。情况 3:你的设备根本没在用你以为的那个 DNS这一种确实是问题,但它不是「泄露」,而是「没生效」。典型场景:你在路由器上配了加密 DNS,但设备的 DHCP 又下发了一个 DNS;或者系统里同时有 systemd-resolved 的 stub 和上游配置。这时不同程序的查询走不同路径。判定方法:看系统实际在用什么。# 现代 Ubuntu / Debian resolvectl status | grep -E "Current DNS|DNS Servers" # 看 stub 监听(127.0.0.53 说明走的是 systemd-resolved) ss -tlnp | grep ':53 '实测我这台机器,两条输出放一起看很有意思: Current DNS Server: 2400:3200::1 DNS Servers: 114.114.114.114 LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=895990,fd=13))这台机器实际在用 114.114.114.114——明文 UDP DNS,不是加密 DNS。 我在这台机器上用 dig +tls @dns.23-4.cn 测得很通,但那只证明「命令行能连上」,完全不代表这台机器在用它。这两个事实同时成立,一点都不矛盾。/etc/resolv.conf 里写着 nameserver 127.0.0.53——这只是指向本机 stub,真正的上游在 resolvectl status 里。很多人看到 127.0.0.53 就以为「没配加密 DNS」,其实那只是中间层;反过来,也有人看到 dig 能通就以为配好了,其实上游还是明文。这两件事必须分开查,这也是「检测工具报多个服务器」最常见的一个真实来源。三、什么时候才是真泄露真泄露的定义很明确:你的查询在你没有授权的地方被解析了。特征是这样的:特征说明检测工具报的服务器里,有运营商/ISP 的 IP说明部分查询走了明文 UDP 53用加密 DNS 和不加密时,报的服务器不一样说明加密 DNS 只覆盖了部分查询你在设备上抓包,能看到发往 53 端口的明文查询最硬的证据同一个域名,不同时刻解析结果不同(且不是 TTL 到期)可能被不同解析器分流最可靠的一条是抓包。在设备上(不是服务器上)跑:sudo tcpdump -i any -n 'udp port 53 or tcp port 53' -c 20然后访问几个网站。如果一条都抓不到,说明明文 DNS 完全没流量,加密 DNS 是全覆盖的。如果抓到了,看 dst 是哪个 IP——那就是真实泄露的出口。踩坑点:tcpdump 抓不到不代表没泄露,可能是:抓的是 any,但流量走了 VPN/容器网络,不在这个 namespace 里;查询已经被系统缓存,根本没发出去(先 resolvectl flush-caches);设备用了 mDNS/LLMNR 之类的本地解析,那不走 53。先清缓存再抓:sudo resolvectl flush-caches sudo tcpdump -i any -n 'udp port 53' -c 20四、一个容易搞混的概念:ECS 不等于泄露加密 DNS 里还有一个东西叫 EDNS Client Subnet(ECS):你的解析器把你的 IP 前缀(通常是 /24)带给权威服务器,让 CDN 能返回「离你近」的节点。它不是泄露——因为接收方是你的解析器,不是运营商;但它确实把你的位置信息往下游传了一层。要不要开 ECS,取决于服务。可以用 dig +subnet 直接看服务端到底传不传:dig +tls +subnet=1.2.3.0/24 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS"实测本站(不传 ECS):; EDNS: version: 0, flags:; udp: 1232作为对照,直接问一个会回显 ECS 的公共 DNS:dig +subnet=1.2.3.0/24 @223.5.5.5 example.com | grep -iE "CLIENT-SUBNET|EDNS"实测:; EDNS: version: 0, flags:; udp: 1232 ; CLIENT-SUBNET: 1.2.3.0/24/24同一个参数,一个回显 CLIENT-SUBNET,一个不回。这就是「这个服务传不传你的网段」的可执行判据,比看任何说明文档都直接。想主动关掉 ECS,用 /0:dig +tls +subnet=0.0.0.0/0 @dns.23-4.cn example.com/0 的意思是「我的网段是 0.0.0.0/0」,等于告诉解析器「别带我的任何前缀」。五、判定流程(按顺序走)# 1. 你的设备实际在用哪个 DNS resolvectl status | grep -E "Current DNS|DNS Servers" # 2. 有没有本机 stub 在中间 ss -tlnp | grep ':53 ' # 3. 加密 DNS 本身通不通(端口 443/853 应开,53 通常关) for p in 53 443 853; do printf "%-4s " $p; timeout 4 nc -z dns.23-4.cn $p >/dev/null 2>&1 && echo open || echo closed; done # 4. 双栈是否各走一路(能解释"两个服务器") dig +short +tls -4 @dns.23-4.cn example.com dig +short +tls -6 @dns.23-4.cn example.com # 5. 节点是否漂移(能解释"多个服务器") for i in 1 2 3; do dig +tls @dns.23-4.cn example.com 2>/dev/null | grep -oP 'SERVER: \K[^#]+'; done | sort -u # 6. 最硬的一条:抓包看有没有明文 53 流量 sudo resolvectl flush-caches sudo tcpdump -i any -n 'udp port 53' -c 20第 1、2 步解决「有没有生效」,第 4、5 步解决「多个服务器是不是正常」,第 6 步才是「有没有真泄露」。六、结论看到检测工具报多个 DNS 服务器,先别慌,按这个顺序排除:多个 IP 但都是同一个服务/同一家 → Anycast 或负载均衡,正常;正好两个,且你双栈 → IPv4/IPv6 各一路,正常;有 ISP 的 IP,或者抓包看到明文 53 → 这才是泄露,去查设备/路由器的 DNS 配置。「多个服务器」是现象,「泄露」是结论。中间隔着至少三步验证,跳过它们直接下结论,会把自己吓到,也会把时间浪费在不存在的问题上。相关阅读怎么验证加密 DNS 真的生效:dig +tls / +https 与 curl 四步逐层排查私人 DNS 是什么、适合谁:一份不带玄学的判断清单在路由器上设置加密 DNS,以及那个「路由器把 DNS 又改回去」的坑
2026年10月24日
5 阅读
0 评论
0 点赞
2026-10-24
怎么验证加密 DNS 真的生效:dig +tls / +https 与 curl 四步逐层排查
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报配完加密 DNS,多数人做的第一件事是 dig @dns.xxx example.com,然后看到 connection refused,就以为没配好或者服务挂了。其实那一步从一开始就问错了对象。加密 DNS 只监听 443(DoH)和 853(DoT),明文 53 端口是故意关掉的。你用只走 53 的 dig 去问,得到的必然是拒绝——那不是故障,那正是它生效的证据之一。这篇给一套按顺序执行的验证流程,四个步骤,每一步都能独立得出结论。下面所有输出都是我在一台 Ubuntu 20.04(dig 9.18.30)上实际跑出来的,域名用的是本站的 dns.23-4.cn,换成你的服务地址同样适用。一、第 0 步:先确认端口开着哪几个在怀疑配置之前,先确认网络层。这一步能把「服务没起」「防火墙挡了」「端口根本不监听」三种情况分开。for p in 53 443 853 784; do printf "port %-4s " "$p" timeout 4 nc -z dns.23-4.cn "$p" >/dev/null 2>&1 && echo open || echo closed done实测输出:port 53 closed port 443 open port 853 open port 784 closed四个端口的含义:端口用途说明53明文 DNS(UDP/TCP)加密 DNS 一般不开放;开放反而说明没配好443DoH(DNS over HTTPS)和普通 HTTPS 共用端口,防火墙最难拦853DoT(DNS over TLS)独立端口,很多企业网会封它784DoQ(DNS over QUIC)支持的服务很少,先别指望没有 nc 的话,用 curl 的 telnet 模式也能测,效果一样:timeout 4 curl -sS -v telnet://dns.23-4.cn:853 2>&1 | grep -E "Connected|refused"踩坑点:nc -z 在部分发行版(尤其是 BusyBox 的 nc)不支持 -z,会静默返回失败,让你误判成「端口关闭」。BusyBox 环境改用 nc -w 3 host port </dev/null 看退出码,或者直接用上面的 curl 写法。二、第 1 步:dig +tls 走 DoTDoT 是最容易验证的一条,因为 dig 原生支持。dig +short +tls @dns.23-4.cn example.com实测输出:104.20.23.154 172.66.147.243有 A 记录出来,就说明 TLS 握手成功、证书校验通过、查询也确实被加密服务应答了。按 man dig,+tls 的语义是:+tls, +notls This option indicates whether to use DNS over TLS (DoT) when querying name servers. When this option is in use, the port number defaults to 853.端口默认 853,所以 @ 后面只写主机名,不要带端口。要换端口用 -p:dig +short +tls @dns.23-4.cn -p 8853 example.com踩坑点:如果你的 dig 报 unknown option +tls 之类,说明版本太老。+tls / +https 是较新版本才有的选项,CentOS 7 自带的 9.11 就不认识。先 dig -v 看一眼,老版本要么升级,要么用 kdig(Knot DNS 的工具,DoT/DoH 支持更早)。还有一点几乎所有人都会误读:dig +tls 默认不校验服务端证书。这不是猜测,有干净的对照实验。这个服务的证书是 *.23-4.cn,用 IP 直接连必然对不上。先只用 +tls:dig +short +tls @160.202.238.204 example.com实测——居然通了:104.20.23.154 172.66.147.243再补上 +tls-ca(按 man dig:This option enables remote server TLS certificate validation):dig +short +tls +tls-ca @160.202.238.204 example.com实测——这次失败了:;; TLS peer certificate verification for 160.202.238.204#853 failed: IP address mismatch同一台服务器、同一个端口、同样的报文,只是多了一个 +tls-ca,结论就从「通」变成「证书不匹配」。这说明:只加 +tls,你验证的是「链路被加密了」,不是「对方身份可信」。 两者不是一回事。做安全评估、或者怀疑被中间人劫持时,必须用 +tls-ca,否则你连自己是不是连到了一个伪造的同名服务都发现不了。用正确的主机名时两者都通:dig +short +tls +tls-ca @dns.23-4.cn example.com172.66.147.243 104.20.23.154三、第 2 步:dig +https 走 DoHDoH 有三种写法,效果一样,但请求方式不同。# A. 默认:POST,路径用服务端默认 dig +short +https @dns.23-4.cn example.com # B. 显式指定 HTTP 路径(POST) dig +short +https=/dns-query @dns.23-4.cn example.com # C. 强制用 GET(报文塞在 ?dns= 里,可被中间层缓存) dig +short +https-get=/dns-query @dns.23-4.cn example.com三种写法我都跑过,返回完全一致:104.20.23.154 172.66.147.243手册原文对应关系:+https[=value] DoH,端口默认 443,发送查询时用 **POST** 模式; value 指定时,作为 HTTP endpoint 使用 +https-get[=value] 与 +https 相同,但用 **GET** 模式 +https-post[=value] 同 +https这里有个几乎人人都会踩的写法错误。 很多人会照着 DoH 地址直接写:dig +short +https @https://dns.23-4.cn/dns-query example.com实测报错:dig: couldn't get address for 'https://dns.23-4.cn/dns-query': not found原因是 @ 后面只接受主机名,dig 会拿它去做地址解析——把一个 URL 交给它,自然解析不出来。URL 要用 +https= 传,主机名单独放在 @ 后面。踩坑点:GET 模式(+https-get)的报文进了 URL 的 query string,理论上会被中间代理缓存。查有敏感性的域名时用 POST,别用 GET。补一句 +http-plain:手册里它是同族选项,走明文 HTTP、端口默认 80。别拿它当验证手段——我实测对本站跑出来是 end of file / no servers could be reached,因为 80 端口根本没有 DoH 服务。它存在只是为了调试反向代理,不是给你日常用的。看到有人推荐 +http-plain 来「测 DoH 通不通」,那是个误解:明文 HTTP 上跑的 DoH 已经没有任何加密意义,测通了也不能说明加密链路可用。四、第 3 步:curl 直接看 HTTP 层前两步验证的是「协议能用」。如果你还想确认 HTTP 层面到底返回了什么(状态码、Content-Type、报文长度),curl 是最直接的。DoH 的协议很简单:把一个 DNS 查询报文(二进制)用 HTTP 发过去,服务端返回一个 DNS 应答报文(二进制)。构造 example.com A 查询报文,标准做法是手工拼 header + question:import base64, struct def build_query(name, qtype=1): # 12 字节 header:ID=0, flags=0x0100(RD=1), QDCOUNT=1, 其余 0 header = struct.pack('!HHHHHH', 0x0000, 0x0100, 1, 0, 0, 0) q = b'' for label in name.split('.'): q += bytes([len(label)]) + label.encode('ascii') q += b'\x00' + struct.pack('!HH', qtype, 1) # QTYPE=A, QCLASS=IN return header + q q = build_query('example.com') print(len(q), q.hex()) print(base64.urlsafe_b64encode(q).rstrip(b'=').decode())实测输出:29 000001000001000000000000076578616d706c6503636f6d0000010001 AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAEAAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE 这串就是可以直接贴进 URL 的 base64url 形式(注意要去掉 = 填充、并把 +/ 换成 -_)。拿它去请求:curl -sS -o /dev/null -w 'code=%{http_code} type=%{content_type}\n' \ -H 'accept: application/dns-message' \ 'https://dns.23-4.cn/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE'实测:code=200 type=application/dns-messagePOST 也一样:python3 -c "import sys,struct;sys.stdout.buffer.write(struct.pack('!HHHHHH',0,0x0100,1,0,0,0)+b'\x07example\x03com\x00'+struct.pack('!HH',1,1))" \ | curl -sS -o /dev/null -w 'code=%{http_code} type=%{content_type}\n' \ -H 'content-type: application/dns-message' \ --data-binary @- \ https://dns.23-4.cn/dns-query实测:code=200 type=application/dns-message三个必须对上的点:Content-Type(请求)和 Accept(响应)都必须是 application/dns-message。写成 application/json 会直接 400。GET 模式下参数名固定是 dns,值是 base64url(不是标准 base64)——+ 和 / 在 URL 里会被解释成别的意思。响应体是二进制报文,不是 JSON。想看到解析结果得自己解码,或者用第 1、2 步的 dig。五、四个常见误判,对照一下你看到的可能的真相怎么确认dig @host 报 connection refused明文 53 被故意关闭,正常第 0 步查端口dig +tls 能出结果但浏览器还是走明文只是命令行验证通过,系统/浏览器还没配查 /etc/resolv.conf 或系统 DNS 设置curl 返回 400Content-Type 或报文格式不对看响应体的错误文字dig +https 报 couldn't get address把 URL 写在了 @ 后面用 +https=/path 传路径还有一类更隐蔽的:验证通了,但实际没生效。因为命令行工具用的是你显式指定的 @host,而系统其它程序用的是 resolv.conf 里的配置。这两条路径完全独立——dig 通了不代表浏览器在走加密 DNS。要确认系统层面,得看 resolv.conf、或者抓包看 53 端口有没有流量出去。如果 +tls 或 +https 直接报错而不是返回记录,按这个顺序缩小范围:报 unknown option → dig 版本太老,换 kdig 或升级;报 connection refused → 端口没开,回到第 0 步;报 network unreachable / 超时 → 路径被拦。853 在不少企业网和公共 WiFi 上是被封的,这时改测 443(DoH)——它和普通 HTTPS 同端口,最难拦;报证书相关错误 → 你加了 +tls-ca 但主机名和证书 SAN 对不上,检查 @ 后面写的是不是证书覆盖的那个名字。第 3 条值得单独说:DoT 被封、DoH 还能用是很常见的网络环境。这也是为什么公开服务通常两个都提供——不是重复建设,是给不同网络条件下留退路。六、一页验证清单# 0. 端口:443/853 应为 open,53 通常为 closed for p in 53 443 853; do printf "%-4s " $p; timeout 4 nc -z dns.23-4.cn $p >/dev/null 2>&1 && echo open || echo closed; done # 1. DoT dig +short +tls @dns.23-4.cn example.com # 2. DoH(POST) dig +short +https @dns.23-4.cn example.com # 3. DoH(GET) dig +short +https-get=/dns-query @dns.23-4.cn example.com # 4. HTTP 层:应为 200 + application/dns-message curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' \ -H 'accept: application/dns-message' \ 'https://dns.23-4.cn/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE'四步全过,说明服务端是好的。至于你这台机器实际有没有在用它,那是另一个问题——那要看 resolv.conf 和抓包,不是看 dig。相关阅读私人 DNS 是什么、适合谁:一份不带玄学的判断清单在路由器上设置加密 DNS,以及那个「路由器把 DNS 又改回去」的坑dnsleaktest 显示多个 DNS 服务器?先分清是泄露还是正常现象加密 DNS 的 ECS 到底传了什么:/24 与 /56 分别暴露你的位置安卓「私人 DNS」为什么只能填主机名、不能填 IP(附 iOS 描述文件做法)
2026年10月24日
2 阅读
0 评论
0 点赞
2026-10-04
安卓「私人 DNS」为什么只能填主机名、不能填 IP(附 iOS 描述文件做法)
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报安卓 9 以上的「私人 DNS」只有三个选项:关闭、自动、以及私人 DNS 提供商主机名。很多人第一次配的时候会想当然地填一个 IP,结果要么保存后显示「无法连接」,要么看着像保存成功了、实际上网全挂。这不是设置藏得深,是协议决定的。下面把原因讲清楚,再给一份安卓和 iOS 都能照抄的配置。一、安卓的「私人 DNS」是 DoT,不是「换一个 DNS 服务器」安卓从 9.0 起内置的私人 DNS,走的是 DNS over TLS(DoT),固定 853 端口。它和「把 DNS 换成别人的 IP」是两件不同的事:你以为在做的实际在做的把 DNS 服务器从运营商换成别人的先和 DNS 服务器建立一条 TLS 加密连接,再在这条连接里查域名填一个 IP 就行要校验服务器证书,而证书必须和填写的域名对得上关键在第二行:TLS 握手要验证服务器证书,验证的前提是「我知道我在连谁」。这个「谁」只能由主机名提供。IP 地址本身不携带任何身份信息,证书也没法证明「8.160.173.68 就是 8.160.173.68」。所以安卓在这里只接受主机名。填 IP 的后果分两种:严格的 ROM(原生 Android、Pixel)直接判定配置无效,私人 DNS 那一栏显示「无法连接」,并且所有域名解析都失败——表现就是「开了私人 DNS 之后整个手机没网」;宽松的 ROM 会把它保存下来,但内部仍然完不成校验,实际静默回退到明文 DNS。你以为开了加密,其实没开。这也是为什么有些国产 ROM 上「填 IP 好像能用」——那不是能用,是它悄悄没用你的配置。二、正确填法设备填什么位置安卓 / 鸿蒙dns.23-4.cn设置 → 网络和互联网 → 私人 DNS → 私人 DNS 提供商主机名iPhone / iPad装描述文件用 Safari 打开 https://www.23-4.cn/ios-dns.mobileconfig安卓各家入口略有差别(小米在「连接与共享」,华为在「更多连接」,三星在「连接 → 更多连接设置」,OPPO / vivo / 荣耀在「其他网络连接」一类的位置),但填的内容完全一样:只有主机名,没有端口,没有 https://,没有斜杠。常见错法:❌ 8.160.173.68 —— IP,安卓不接受❌ dns.23-4.cn:853 —— 端口是隐含的,写上去会被当成主机名的一部分❌ https://dns.23-4.cn/dns-query —— 这是 DoH 地址,属于浏览器和 Windows 的填法✅ dns.23-4.cn顺带说一句:安卓的私人 DNS 是系统级的,一旦开启,会覆盖路由器通过 DHCP 下发的 DNS。也就是说,路由器没配好也不影响手机——这一点在排查时很有用。三、iPhone 为什么没有这一栏iOS 不在设置里开放这个开关,只能用描述文件(mobileconfig)。原理一样,也是 DoT:<key>DNSSettings</key> <dict> <key>DNSProtocol</key> <string>TLS</string> <key>ServerName</key> <string>dns.23-4.cn</string> </dict>用 Safari 打开 https://www.23-4.cn/ios-dns.mobileconfig,系统提示「已下载描述文件」,然后到 设置 → 通用 → VPN与设备管理 里点安装。想撤销就在同一个地方删除,文件里 PayloadRemovalDisallowed 是 false,不需要密码,也不会锁住设备。两个容易踩的点:必须用 Safari 打开。Chrome、微信内置浏览器不会把文件交给系统安装,只会显示一堆 XML;装完如果没生效,检查 设置 → 通用 → VPN与设备管理 里描述文件是不是「已安装」状态,而不是只下载了。四、配完怎么确认真的生效了安卓私人 DNS 那一栏会显示「已连接」而不是「无法连接」。想更确定,访问 https://1.1.1.1/help,看 DoT 那一行是不是 Yes。如果显示「无法连接」,按这个顺序查:主机名有没有拼错、有没有多打空格;当前网络能不能出 853 端口——部分公司网、校园网会封非 443 端口;换一个网络(比如切到手机流量)再试,先区分是设备问题还是网络问题;都不行就先切回「自动」,然后去 战报页 看有没有你自己的解析记录——有记录说明流量已经走过来了,问题在别处。相关阅读一个免费的加密 DNS(dns.23-4.cn):全平台去广告与隐私保护私人 DNS 加密设置教程私人 DNS 是什么、适合谁:一份不带玄学的判断清单私人DNS不生效怎么办?多设备通用排查方法与常见原因
2026年10月04日
100 阅读
0 评论
0 点赞
2026-10-04
GitHub 和 Cloudflare 有没有被加速?说清「DNS 加速」能做什么、不能做什么
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报「换了你们的 DNS,GitHub 是不是就变快了?」「Cloudflare 有没有被加速?」这两个问题背后是同一个误解:以为 DNS 能加速网络。DNS 只负责把域名翻译成 IP,它决定你连到哪台机器,不决定你连过去有多快。但这不代表换 DNS 对 GitHub 没用。下面把「能做什么」和「不能做什么」分开说。一、DNS 唯一能改变的两件事换一个解析器,物理上只可能改变两件事:返回的 IP 不一样了。 同一个域名,不同解析器可能返回不同的 IP(多机房、CDN 调度、或其中一方被污染)。返回的 IP 是对的还是错的。 明文 DNS 在链路上可以被篡改,加密 DNS 不能。速度只可能通过第 1 条间接变化:如果新返回的 IP 恰好是离你更近的节点,那确实会更快。但这是「换了一个更好的节点」,不是「DNS 加了速度」。而且如果原来的解析器已经返回了最优节点,换谁都不会变快。二、GitHub 的实际情况GitHub 相关的域名不是一个,而是一串,各自的情况完全不同:域名用途换 DNS 有没有用github.com主站页面、Git 操作一般没明显变化,瓶颈在跨境线路api.github.comAPI、CI、部分客户端同上codeload.github.com下载仓库压缩包同上raw.githubusercontent.com原始文件、脚本、图片可能有明显变化——这个域名经常被返回错误/不可达的 IP,换一个能返回正确 IP 的解析器,从「完全打不开」变成「能打开」objects.githubusercontent.comRelease 附件下载有可能变化,同样是「修好 vs 打不开」*.githubassets.com页面静态资源有可能变化所以准确的说法是:换 DNS 不会让 GitHub 变快。 跨境带宽和路由质量不是 DNS 能改的。换 DNS 可能让 GitHub 从「打不开」变成「能打开」。 这是修错,不是加速。典型症状是页面样式全丢、Release 下载 404、raw 链接超时——这些多半是解析结果错了。想要真的「快」,需要的是代理 / CDN / 中继,不是 DNS。顺便说一句:如果你看到某个「DNS 加速」服务声称能把 GitHub 下载速度提到几 MB/s,它多半在做 HTTP 代理或反向代理,而不是在做 DNS。这两件事经常被打包成一个产品卖,但技术上是两回事。三、Cloudflare 的实际情况Cloudflare 的情况和 GitHub 相反:Cloudflare 大量使用任播(anycast)。同一个 IP 在全球很多机房都有,用户连上去之后由 BGP 路由决定落到哪个机房;这意味着 DNS 返回哪个 Cloudflare IP 其实不太重要——反正是同一批任播地址,路由会把你带到最近的可用机房;所以「换 DNS 让 Cloudflare 变快」基本是无效的。真正影响速度的是你的运营商到 Cloudflare 机房的互联质量,这跟 DNS 无关;1.1.1.1 这个地址本身是个特例:它在部分网络下确实比运营商 DNS 响应更快,但那是「解析器本身快」,不是「被加速」。一个实测办法,把「解析」和「连接」分开量:# 1. 解析耗时:只测 DNS,不测连接 dig github.com | grep -i "Query time" # 2. 连接耗时:解析到一个固定 IP 之后,测 TCP/TLS 握手 curl -o /dev/null -s -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n" https://github.com # 3. 下载速度:和 DNS 完全无关 curl -o /dev/null -s -w "speed=%{speed_download} bytes/s\n" https://github.com/看 time_namelookup(DNS)和 time_connect(连接)的比例。如果 DNS 只占几十毫秒、而 connect 要几百毫秒,那就说明瓶颈在线路,换 DNS 没有任何意义。四、那这台站的服务对 GitHub 到底有没有帮助诚实回答:✅ 可能修好「打不开」:如果运营商 DNS 对某些 GitHub 子域返回了错误结果,加密 DNS 能给出正确结果;✅ 顺带拦截部分广告和跟踪器,让页面加载少几个请求;❌ 不会提高下载速度:本站不做任何 HTTP 代理、中继或 CDN 回源,它只解析域名;❌ 不改变你的出口 IP:所有流量还是从你自己的线路出去。如果你的诉求是「GitHub 下载要快」,DNS 不是答案,你需要的是代理或镜像。如果你的诉求是「GitHub 有些页面打不开」,那换一个能给出正确解析的 DNS 值得一试。五、一张表说清边界你想要的效果DNS 能做到吗该用什么修好被污染 / 被劫持的解析✅ 能加密 DNS在多个 CDN 节点里选一个更近的⚠️ 间接,且不保证就近的解析器提高跨境下载速度❌ 不能代理 / 中继 / CDN隐藏你访问了哪些站点❌ 不能VPN / Tor拦掉 DNS 层的广告域名✅ 能带过滤的 DNS改变游戏对局延迟❌ 不能优化线路相关阅读一个免费的加密 DNS(dns.23-4.cn):全平台去广告与隐私保护私人 DNS 是什么、适合谁:一份不带玄学的判断清单公共DNS服务商对比:Cloudflare/Google/阿里/腾讯/114 哪个更适合你?私人DNS速度怎么样?DNS延迟测速方法与工具推荐
2026年10月04日
23 阅读
0 评论
0 点赞
1
2
...
8