全部产品
Search
文档中心

DNS over HTTPs(DoH)

更新时间: 2021-07-01

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

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

接入流程如下:

DOH接入流程https://user_id.alidns.com/dns-query

获取user_id

请在公共DNS控制台查看account_id。如下:

accountid

普通用户配置DoH

假设account_id是9999,用户的DoH接口配置为:

https://9999.alidns.com/dns-query

接下来,将以Firefox(火狐浏览器)为例,介绍如何配置DoH。

第一步:从 Firefox 菜单栏中点击 【选项】设置。

firefox1第二步:搜索框中输入“DNS”,点击【网络设置】中的【设置】按钮。

Firefox2

第三步:在设置页面的底部,找到并勾选“启用基于HTTPS的DNS”,选择“自定义”的提供商,并输入接口地址:https://9999.alidns.com/dns-query,点击【确定】。

Firefox3

开发者使用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://dns.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.223.101", "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://dns.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.203.213
www.taobao.com.danuoyi.tbcache.com.     15      IN      A       221.229.203.214

;; ADDITIONAL SECTION:

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

如果您需要接入免费版,不需要带user_id的方式,接入地址格式如下:

  • https://dns.alidns.com/dns-query

  • https://alidns_ip/dns-query

Firefox的免费接入方式请参考