使用 Curl 检查 DoH 可用性
简单快速检测、一般 Linux 和 Windows 10 版本 1803 后都自带 Curl。
文末带有示例,复制执行即可。
标准请求
根据 RFC 8484,DNS over HTTPS (DoH)支持通过 HTTP GET 和 POST 两种方法发送请求。
-
GET 请求:
- 在 GET 请求中,DNS 查询被编码为一个查询参数。这个参数使用 Base64URL 编码的 DNS 请求内容,并附加到 URI 上。例如,一个 GET 请求的 URI 可能类似于
https://dnsserver.example.net/dns-query?dns=<base64url-encoded-query>
。 - 使用 GET 请求的优点是它更友好于许多 HTTP 缓存实现,可以利用 HTTP 缓存来缓存响应。
- 在 GET 请求中,DNS 查询被编码为一个查询参数。这个参数使用 Base64URL 编码的 DNS 请求内容,并附加到 URI 上。例如,一个 GET 请求的 URI 可能类似于
-
POST 请求:
- 在 POST 请求中,DNS查询被包含在 HTTP 请求的主体中,媒体类型为
application/dns-message
。例如,POST 请求的内容类型和长度需要在 HTTP 头中指定,且 DNS 查询以 DNS wireformat 编码放在请求体中。 - POST 请求通常比 GET 请求更小,因为不需要将请求内容编码到 URI 中。
- 在 POST 请求中,DNS查询被包含在 HTTP 请求的主体中,媒体类型为
无论是 GET 还是 POST 方法,DoH 服务器都需要实现这两种方法来处理 DNS 查询。
RFC 8484 还规定,DoH 客户端应该包含 HTTP Accept 头字段,以指示可以处理的响应类型,并且必须能够处理 application/dns-message
类型的响应。
请求例如:
curl -vH "accept: application/dns-message" "https://cloudflare-dns.com/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"
你或许尝试过对
AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
进行 Base64URL 解码,但你会得到一些乱码。那是因为这个 Base64URL 是二进制编码转 Base64URL 而不是字符串转 Base64URL,但是我没找到具体定义。(看起来是 RFC 1035 中定义的 DNS wireformat)
而且这种请求返回的响应 application/dns-message
也是一个二进制,该格式在 RFC 1035 中定义,因此标准 DoH 请求非常不利于人类查看和使用。
7.1. Registration of the "application/dns-message" Media Type
Type name: application
Subtype name: dns-message
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: This is a binary format. The contents are a
DNS message as defined in RFC 1035. The format used here is for
DNS over UDP, which is the format defined in the diagrams in
RFC 1035.Security considerations: See RFC 8484. The content is a DNS message
and thus not executable code.Interoperability considerations: None.
Published specification: RFC 8484.
Applications that use this media type:
Systems that want to exchange full DNS messages.
摘自 RFC 8484
所以在我们人类快速检查可用性时,大概应该使用下面的 JSON API 形式。
JSON API
RFC 8427 定义了以下 JSON 对象成员来表示 DNS 消息:
- ID:整数,范围为 0 到 65535。
- QR:布尔值,表示查询或响应。
- Opcode:整数,范围为 0 到 15,表示操作码。
- AA:布尔值,表示是否权威回答。
- TC:布尔值,表示是否被截断。
- RD:布尔值,表示是否递归期望。
- RA:布尔值,表示是否递归可用。
- AD:布尔值,表示是否经过 DNSSEC 验证。
- CD:布尔值,表示是否禁用 DNSSEC 验证。
- RCODE:整数,范围为 0 到 15,表示返回码。
- QDCOUNT:整数,范围为 0 到 65535,表示问题计数。
- ANCOUNT:整数,范围为 0 到 65535,表示回答计数。
- NSCOUNT:整数,范围为 0 到 65535,表示权威记录计数。
- ARCOUNT:整数,范围为 0 到 65535,表示附加记录计数。
然而并没有人在乎 RFC 8427,我也没有看到哪个 RFC 规定了 JSON API 实现方式。
实践中,各大公共 DNS 几乎都支持以如下方式请求:
curl -vH "accept: application/dns-json" "https://cloudflare-dns.com/dns-query?name=example.com&type=A"
但部分公共 DNS 似乎也存在分歧,有的也会要求使用 /resolve
路径:
curl -vH "accept: application/dns-json" "https://dns.google/resolve?name=example.com&type=A"
返回的 JSON 示例如下:
{
"Status":0,
"TC":false,
"RD":true,
"RA":true,
"AD":true,
"CD":false,
"Question":[
{
"name":"example.com",
"type":1
}
],
"Answer":[
{
"name":"example.com",
"type":1,
"TTL":2080,
"data":"93.184.215.14"
}
]
}
与 RFC 8427 定义不同,这似乎是事实标准。
所以也许应该是 Cloudflare Style 和 Google Style?
但即使这样,返回格式也不一定是一样的(比如 dns.sb),所以如果你写程序,最好还是不要用 JSON API 了。
快速检测请使用文末的示例。
Curl 原生
curl 7.62.0 版本中原生支持了 DoH。
请求如:
curl --doh-url https://cloudflare-dns.com/dns-query https://www.example.com
详情请参阅:https://github.com/curl/curl/wiki/DOH-implementation
但我并不推荐使用,因为我们只是测试,而且你的版本不一定达标,而且此命令的目的是通过 DoH 解析后请求目标网址。
那么 DoT 呢?
很遗憾,我并没有找到简单快速且 Linux/Windows 自带的工具。
你也可以尝试这些全平台工具:
或这些 Linux Only 工具:
不过在 Linux 中如果你的 dig (BIND) 版本大于 9.17.10,那么你很可能已经有了 DoH 支持。
请求如:
dig +https @cloudflare-dns.com example.com A
详情请参阅:https://www.isc.org/blogs/bind-doh-update-2021/
JSON API 请求示例
中国大陆
Dnspod 公共 DNS
https://docs.dnspod.cn/public-dns/dot-doh/
虽然有文档,但是完全没说请求方式,相当于没有文档。
地区:CN、有部分全球接入能力
域名
curl -vH "accept: application/dns-json" "https://doh.pub/dns-query?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://1.12.12.12/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://120.53.53.53/dns-query?name=example.com&type=A"
IPv6
看起来没有,2402:4e00::
并不能用。
阿里公共 DNS
https://alidns.com/articles/6018321800a44d0e45e90d71
特别注意,阿里 DNS 的 JSON API 查询路径不是 /dns-query
而是 /resolve
。
地区:CN、有部分全球接入能力
域名
curl -vH "accept: application/dns-json" "https://dns.alidns.com/resolve?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://223.5.5.5/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://223.6.6.6/resolve?name=example.com&type=A"
IPv6
看起来没有,2400:3200::1
和 2400:3200:baba::1
并不能用,但是文档说可以。
curl -vH "accept: application/dns-json" "https://[2400:3200::1]/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://[2400:3200:baba::1]/resolve?name=example.com&type=A"
360安全 DNS
https://sdns.360.net/index.html
IP 有亿点多,但是没有 BGP 和全球接入能力。
地区:CN
域名
curl -vH "accept: application/dns-json" "https://doh.360.cn/resolve?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://180.163.249.75/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://101.198.192.33/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://101.198.191.4/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://101.226.4.6/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://218.30.118.6/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://123.125.81.6/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://140.207.198.6/resolve?name=example.com&type=A"
IPv6
无?
EasyMosdns
个人自建的 DNS,于 2019 启用,仅提供 DoH,仅限研究用途,不承诺 SLA,在 CN 提供无污染 DNS,本质是一个 DNS 转发器。
开源项目 EasyMosdns 官方的 DNS 分流 API。
地区:CN
不支持 JSON API
域名
curl -vH "accept: application/dns-message" "https://doh.apad.pro/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"
IPv4
183.134.17.113
不能用。
IPv6
无
微步 OneDNS
纯净版,不拦截域名。
然而完全没有反应,服务器甚至没有返回 TLS 证书。
估计已被放弃。
域名
curl -vH "accept: application/dns-json" "https://doh-pure.onedns.net/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"
IPv4
我觉得没必要测了。
全球/中国大陆外
Cloudflare 公共 DNS
https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/
地区:Global、CN 除外
域名
curl -vH "accept: application/dns-json" "https://cloudflare-dns.com/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://mozilla.cloudflare-dns.com/dns-query?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://1.1.1.1/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://1.0.0.1/dns-query?name=example.com&type=A"
IPv6
curl -vH "accept: application/dns-json" "https://[2606:4700:4700::1111]/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://[2606:4700:4700::1001]/dns-query?name=example.com&type=A"
Google 公共 DNS
https://developers.google.com/speed/public-dns/docs/doh
特别注意,Goole DNS 的 JSON API 查询路径不是 /dns-query
而是 /resolve
。
地区:Global、CN 除外
域名
curl -vH "accept: application/dns-json" "https://dns.google/resolve?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://8.8.8.8/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://8.8.4.4/resolve?name=example.com&type=A"
IPv6
curl -vH "accept: application/dns-json" "https://[2001:4860:4860::8888]/resolve?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://[2001:4860:4860::8844]/resolve?name=example.com&type=A"
DNS.SB
返回的 JSON 和相比其他家略有不同。
地区:Global(但接入能力比较有限)、CN 除外
域名
curl -vH "accept: application/dns-json" "https://doh.dns.sb/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://doh.sb/dns-query?name=example.com&type=A"
IPv4
curl -vH "accept: application/dns-json" "https://45.11.45.11/dns-query?name=example.com&type=A"
curl -vH "accept: application/dns-json" "https://185.222.222.222/dns-query?name=example.com&type=A"
IPv6
看起来没有,2a09::
和 2a11::
并不能用。
Quad 101
无文档。
返回的 JSON 和相比其他家略有不同。
地区:TW
域名
curl -vH "accept: application/dns-json" "https://dns.twnic.tw/dns-query?name=example.com&type=A"
域名测试我没有成功,IP 倒是可以。
IPv4
curl -vH "accept: application/dns-json" "https://101.101.101.101/dns-query?name=example.com&type=A"
101.102.103.104
不能用。
IPv6
看起来没有,2001:de4::101
及 2001:de4::102
并不能用。
NextDNS
私人定制 DNS,免费每月 3000000 次查询,超过后可以继续应答,但是自定义规则失效。
地区:Global,似乎有 CN 节点。
域名
curl -vH "accept: application/dns-message" "https://dns.nextdns.io/c98785c/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB"
注意:c98785c 是一个临时 ID,一段时间后失效,要测试请访问其网站,获取一个零时 ID 并替换。
不支持 JSON API。
IPv4
似乎要 IP 白名单才能使用,但是并没有 IP 证书,所以不能用。
IPv6
虽然它会根据你的 ID 生成唯一 IPv6,例如 c98785c :2a07:a8c0::c9:785c
和 2a07:a8c1::c9:785c
但是并没有 IP 证书,所以不能用。
无评论