文档

DNS over HTTPs (DoH)

更新时间:
重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

本章节介绍DoH的接入过程。

阿里公共DNS通过RFC 8484指定的经过TLS加密的HTTP连接提供DNS解析。

接入流程

DOH接入流程

获取user_id

请在云解析DNS产品控制台 > 递归解析(公共DNS) > 接入配置 路径下查看 专属配置ID(Account ID)

Snipaste_2024-07-18_15-20-19.png

打开DoH接入开关

  1. 递归解析(公共DNS) 页面选择 接入配置 页签。

  2. 单击 接入指引 栏下的 启用状态 开关按钮,将开关打开。Snipaste_2024-07-18_15-24-28.png

    警告
    • 若您决定弃用DoH方式接入公共DNS,可以将启用状态设置为关闭。

    • 请慎重操作停服功能。停服后将降级为免费用户,即停止计费、停止控制台报表展示和其他功能操作。您的公共DNS服务也将不再有SLA保证,且会被限速和拒绝解析应答。

    • 停服之后支持重启服务。重启后,服务恢复原来的配置,并重新开始计费。

普通用户使用DoH服务

假设Account_ID是9**9,则用户的DoH接口配置为:https://9**9.alidns.com/dns-query

本文以Chrome为例,介绍如何配置DoH。

  1. 打开Chrome浏览器,从 Chrome 菜单栏中点击 【设置】选项。

    1599813826622-5e23172a-3595-42ee-b1be-8359ad781892

  2. 在搜索框中输入“DNS”,在下方的检索结果中,点击【安全】右侧的展开箭头。

    1599813913378-46376364-4ff3-40d1-8da0-f0909f4ba1c6

  3. 页面下拉到最下方,在【高级】选项中,开通“使用安全DNS”功能,并在【使用】-【自定义】框中输入“https://9**9.alidns.com/dns-query”即可完成配置。

    image

开发者使用DoH服务

对开发者,需要按照RFC8484中的标准要求生成DoH的 HTTP request请求发送给DoH服务地址。

DoH可以同时用GET和POST两种方法。当使用POST方法,DNS查询消息被包含在HTTP 请求的message body中。当使用GET方法,唯一的变量"dns"被赋值为base64url编码的DNS请求内容。

开发者案例 (附python和Golang代码示例)

例如用GET方式发起DoH查询,先将DNS二进制报文经过base64url的处理得到DNS参数,生成完整的DoH HTTP URL,再发起HTTP请求,获得DNS应答报文。

下面是一段python的代码,演示开发者如何使用DoH查询域名alibaba.com。

import dns.message
import requests
import base64
import json

doh_url = "https://9**9.alidns.com/dns-query"
domain = "alibaba.com"
rr = "A"
result = []

message = dns.message.make_query(domain, rr)
dns_req = base64.b64encode(message.to_wire()).decode("UTF8").rstrip("=")
r = requests.get(doh_url + "?dns=" + dns_req,
                 headers={"Content-type": "application/dns-message"})
for answer in dns.message.from_wire(r.content).answer:
    dns = answer.to_text().split()
    result.append({"Query": dns[0], "TTL": dns[1], "RR": dns[3], "Answer": dns[4]})
    print(json.dumps(result))

运行结果如下:

$ python test_doh.py
[{"Answer": "106.11.XXX.XXX", "Query": "alibaba.com.", "RR": "A", "TTL": "133"}]

下面是一段Golang的代码,演示开发者如何使用DoH查询域名alibaba.com。

package main

import (
        "encoding/base64"
        "fmt"
        "github.com/miekg/dns"
        "io/ioutil"
        "net/http"
        "os"
)

func main() {
       query := dns.Msg{}
       query.SetQuestion("www.taobao.com.", dns.TypeA)
       msg, _ := query.Pack()
       b64 := base64.RawURLEncoding.EncodeToString(msg)
       resp, err := http.Get("https://9**9.alidns.com/dns-query?dns=" + b64)
       if err != nil {
            fmt.Printf("Send query error, err:%v\n", err)
            os.Exit(1)
       }
       defer resp.Body.Close()
       bodyBytes, _ := ioutil.ReadAll(resp.Body)
       response := dns.Msg{}
       response.Unpack(bodyBytes)
       fmt.Printf("Dns answer is :%v\n", response.String())
}

运行结果如下:

Sent Get query https://dns.alidns.com/dns-query?dns=xzEBAAABAAAAAAAAA3d3dwZ0YW9iYW8DY29tAAABAAE
Dns answer is :;; opcode: QUERY, status: NOERROR, id: 50993
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;www.taobao.com.        IN       A

;; ANSWER SECTION:
www.taobao.com. 15      IN      CNAME   www.taobao.com.danuoyi.tbcache.com.
www.taobao.com.danuoyi.tbcache.com.     15      IN      A       221.229.XXX.XXX
www.taobao.com.danuoyi.tbcache.com.     15      IN      A       221.229.XXX.XXX

;; ADDITIONAL SECTION:

;; OPT PSEUDOSECTION:
; EDNS: version 0; flags: ; udp: 4096