DNS-over-HTTP/3 和 DNS-over-QUIC 两种协议都基于 UDP,且传输数据都经过 TLS 加密,但是这两种协议是完全不同的。
先来简单了解下 QUIC 协议:
QUIC 和 TCP、UDP 一样,是传输层协议,不过 QUIC 协议是基于加密 UDP 的(使用 TLS 1.3 来加密),QUIC 还具有 TCP 的一些优点。
DNS-over-QUIC:
DNS-over-QUIC 是通过 QUIC 加密的 DNS 协议,有时会被简写为 DoQ,这个协议于 2022 年 5 月 发布为 RFC 9250,它比较类似 DNS-over-TLS,但是 DNS-over-QUIC 会比 DNS-over-TLS 更快一些。可以看到握手成功,服务器返回了 HTTP 状态码 400(这是正常的。为什么?因为 dns-query 没有提供 DNS 查询的参数,所以服务器返回了 Bad Request)
curl 无法与 DNS-over-QUIC 服务器进行握手和数据交换,因为 DNS-over-QUIC 只是经过 QUIC 封装的原生 DNS,并不能处理 HTTP 请求。
尝试使用 curl 来连接 DNS-over-QUIC 服务器,得到的输出如下:
$ curl https://dns.mbrjun.cn:784 --http3 -v
* Trying 127.0.0.1:784...
* Connect socket 5 over QUIC to 127.0.0.1:784
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* ngtcp2_conn_handle_expiry returned error: ERR_HANDSHAKE_TIMEOUT
* connect to 127.0.0.1 port 784 failed: Failed sending data to the peer
* Failed to connect to dns.mbrjun.cn port 784 after 10050 ms: Failed sending data to the peer
* Closing connection 0
curl: (55) ngtcp2_conn_handle_expiry returned error: ERR_HANDSHAKE_TIMEOUT
````
可以看到 QUIC 套接字已经创建完成,但是服务器并不响应这个 HTTP 请求:
DNS-over-QUIC = QUIC + DNS
### DNS-over-HTTP/3:
DNS-over-HTTP/3,有时也会被称作 DoH3,也是一种加密的 DNS 协议,这种协议在 Android 11 中通过增量更新得到了 Android 的原生支持。
DNS-over-HTTP/3 使用 HTTP 作为传输层协议,本质上是 DNS-over-HTTPS 的一种。
DNS-over-HTTPS 允许使用 HTTP/3、HTTP/2、HTTP/1.1、HTTP/1.0、HTTP/0.9 作为底层协议(实际上,只有前种常被使用),而 DNS-over-HTTP/3 是指使用 HTTP/3 做底层协议的 DNS-over-HTTPS
HTTP/3 协议基于 QUIC,因此可以说 HTTP/3 = QUIC + HTTP
DNS-over-HTTP/3 = QUIC + HTTP + DNS
curl 可以和 DNS-over-HTTP/3 服务器进行握手和数据交换,因为 DNS-over-HTTP/3 是经过 QUIC 封装的 HTTP,在 HTTP 上提供 DNS 查询的功能,因此可以处理 HTTP 请求。
尝试使用 curl 来连接 DNS-over-HTTP/3 服务器,得到的输出如下:
$ curl https://dns.mbrjun.cn/dns-query --http3 -vI
- Trying 127.0.0.1:443...
- Connect socket 5 over QUIC to 127.0.0.1:443
- CAfile: /etc/ssl/certs/ca-certificates.crt
- CApath: none
- subjectAltName: host "dns.mbrjun.cn" matched cert's "*.mbrjun.cn"
- Verified certificate just fine
- Connected to dns.mbrjun.cn (127.0.0.1) port 443 (#0)
- h2h3 [:method: HEAD]
- h2h3 [:path: /dns-query]
- h2h3 [:scheme: https]
- h2h3 [:authority: dns.mbrjun.cn]
- h2h3 [user-agent: curl/7.87.1-DEV-MBRjun]
- h2h3 [accept: /]
Using HTTP/3 Stream ID: 0 (easy handle 0x5612c27f71b0)
HEAD /dns-query HTTP/3
Host: dns.mbrjun.cn
user-agent: curl/7.87.1-DEV-MBRjun
accept: /- ngh3_stream_recv returns 0 bytes and EAGAIN
- ngh3_stream_recv returns 0 bytes and EAGAIN
- ngh3_stream_recv returns 0 bytes and EAGAIN
< HTTP/3 400
HTTP/3 400
< (headers)
(headers)
...
可以看到握手成功,服务器返回了 HTTP 状态码 400(这是正常的。为什么?因为 dns-query 没有提供 DNS 查询的参数,所以服务器返回了 Bad Request)
## 对比和总结
DNS-over-QUIC = QUIC + DNS
DNS-over-HTTP/3 = QUIC + HTTP + DNS
DoH3 比 DoQ 多了一层 HTTP 封装,因此可以使用类似 curl 的工具进行查询。
由于 DoH3 有一层 HTTP 封装,所以它在传输时会带上 Request Header 和 Response Header,这其中可能包含了 User-Agent 之类的信息,这种信息对于 DNS 来说通常是毫无作用的,理论上,DoH3 会比 DoQ 更慢,但实际上带来的影响是极其少的(可能只会慢个 1-2ms)。
端口号:DoQ 更类似于 DoT,通常使用端口号 443、784 和 853,而 DoH3 是 DoH 的一种,通常使用端口 443。
兼容性:从 Android 11 开始,DoH3 得到了部分支持(谷歌设置了白名单,只有少数公共 DNS 服务器会启用 DoH3),从 iOS 15 (macOS Monterty)开始,Apple 设备支持了 DoQ(仅可通过 iCloud Private Relay 开启,不支持自定义服务器),现在 DoH3 的用户数量和 DoQ 的差不多。
---
附:AdGuard 认为使用 HTTP 作为传输层协议会引起很多不必要的风险,使用 HTTP 发送 DNS 请求会导致下列结果:
* HTTP cookies
* 其他 HTTP 消息头(HTTP headers)(包括 Authentication, User-Agent, Accept-Language)
* 给预谋犯更多机会
* Tracking using ETag
支持使用 Tab 键浏览评论操作;进入回复状态后,按 Esc 可以取消回复并返回原位置。
评论