DNS over HTTPS

介绍如何使用基于DoH协议的DNS解析

在HTTPDNS中开启DoH

请参考《DoH开启与使用

快速验证DoH服务生效

前置条件:

image

  1. 在HTTPDNS的开发配置中启用DoH。

  2. 获得DoH接入点,例如账号id为1xxxx3,则接入点为https://1xxxx3.aliyunhttpdns.com/dns-query

  3. 域名列表中已包含www.aliyun.com

说明

开启/关闭DoH、是否解析所有域名、添加/删除域名黑名单、添加/删除域名列表的操作后,生效会有一定的延时,通常不会超过1分钟。

使用CURL快速验证

  1. 在本地终端触发DoH解析:

curl -H "Content-Type: application/dns-message" "https://1xxxx3.aliyunhttpdns.com/dns-query?dns=8RkBAAABAAAAAAAAA3d3dwZhbGl5dW4DY29tAAABAAE" -o response.bin
  1. 在本地终端使用xxd response.bin读取结果:

image3. 观察结果中包含adns.aliyun.com.gds.alibabadns即可确认成功

在浏览器中使用DoH

Chrome浏览器

  1. 从菜单中进入设置页并在左侧菜单中选择“隐私和安全”,或者在地址栏输入 chrome://settings/security

  2. 在“高级”中打开并使用安全DNS

111111.jpg

  1. 在“输入自定义DNS查询网址”中,输入DoH接入点地址

  2. 地址栏输入需要访问的链接,进行验证

Firefox浏览器

  1. 在菜单中进入设置页,并在左侧菜单中选择“隐私与安全”,或者在地址栏输入about:preferences#privacy

  2. 在“基于 HTTPS 的 DNS”中完成DoH的配置

image

  1. 在“自定义”中,输入DoH接入点地址

  2. 地址栏输入需要访问的链接,进行验证

浏览器中使用DoH服务的常见问题

网页无法打开

image

问题原因

解决方法

没有开启DoH

请参考DoH开启与使用开启相关功能

使用了错误的DoH接入点地址

请参考DoH开启与使用获取正确的DoH接入域名

没有在域名列表中配置主站域名

请参考添加域名在域名列表中添加主站域名。

网页中部分元素无法渲染

image

问题原因

解决方法

没有在域名列表中配置相关域名

请参考添加域名在域名列表中添加相关域名。

说明

通常一个网站能完全渲染可能需要访问多个域名,需要将这些域名都添加到域名列表

开发者使用DoH客户端

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

  • GET请求:将DNS二进制报文进行base64url编码后,赋值给参数"dns"。

  • POST请求:直接将DNS二进制报文作为request body传入。

Python3脚本示例

# -*- coding: utf-8 -*-

import requests
import base64
import dns.message

def query_doh(domain):
    # 创建DNS请求A记录
    request = dns.message.make_query(domain, dns.rdatatype.A)
    request_data = request.to_wire()

    # 将请求编码为base64URL格式
    base64_query = base64.urlsafe_b64encode(request_data).decode().rstrip("=")

    # 使用HTTPDNS的DoH接入点
    url = f"https://1xxxx3.aliyunhttpdns.com/dns-query?dns={base64_query}"

    # 发送GET请求
    headers = {
        "Accept": "application/dns-message"
    }
    response = requests.get(url, headers=headers)

    # 错误检查
    if response.status_code != 200:
        print(f"Error: {response.status_code}")
        return

    # 解析响应
    response_data = response.content
    dns_response = dns.message.from_wire(response_data)

    # 提取和打印IP地址
    for answer in dns_response.answer:
        for item in answer.items:
            print(f"Answer: {item}")

if __name__ == "__main__":
    # 查询的域名
    domain = "www.aliyun.com"
    query_doh(domain)

运行结果如下:

image