阿里公共DNS

1. DNS over HTTPs(DoH)

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

DNS over HTTPs(DoH)的URI接口 :(仅提供TLS API)

请求方式: GET
请求参数 :

请求示例 https://dns.alidns.com/dns-query?dns=uGkBAAABAAAAAAAAB2FsaWJhYmEDY29tAAABAAE
返回的DNS二进制数据 

b869 8180 0001 0004 0000 0001 0761 6c69
6261 6261 0363 6f6d 0000 0100 0107 616c
6962 6162 6103 636f 6d00 0001 0001 0000
012c 0004 6a0b d097 0761 6c69 6261 6261
0363 6f6d 0000 0100 0100 0001 2c00 04cb
77d7 5207 616c 6962 6162 6103 636f 6d00
0001 0001 0000 012c 0004 6a0b df65 0761
6c69 6261 6261 0363 6f6d 0000 0100 0100
0001 2c00 04cb 7781 6d00 0029 1000 0000
0000 000c 0008 0008 0001 2018 6a0b 22e6


注:根据RFC8484的定义,DoH服务适用于两类场景:一种是DNS HTTPS隧道,一种是应用层访问DNS数据。DNS wireformat二进制格式对应用不够友好,比如要处理DNS名字压缩机制等。DNS Json的API是为了提供给应用更友好的接入方式。

2. DNS JSON API

DNS JSON API的URL 接口 (提供TLS和非TLS API)

请求方式 : GET
请求参数 

**
关于edns_client_subnet参数 :

edns_client_subnet是为了支持DNS ECS功能(RFC7871),将用户的子网信息传递给权威DNS,做更精确的DNS解析和流量调度。其中掩码越长地址信息越精确,掩码越短用户隐私效果越好。建议使用"/24" 掩码长度

注:该参数是特地为DNS代理(proxy)使用DNS JSON API场景设计,即用户发送DNS查询给DNS代理,DNS代理通过该参数携带用户的子网信息传递给阿里公共DNS,最后传递到权威DNS服务器。

例如edns_client_subnet=1.2.3.4/24,权威服务器会收到基于1.2.3.0/24地址前缀信息来帮助用户选择DNS链路。

关于type参数支持类型

请求示例:
http://dns.alidns.com/resolve?name=www.taobao.com.&type=1
返回示例:

{
    "Status":0,  
    "TC":false,
    "RD":true,
    "RA":true,
    "AD":false,
    "CD":false,
    "Question":{       // 请求段
        "name":"www.taobao.com.",
        "type":1
    },
    "Answer":[         // 应答段
        {
            "name":"www.taobao.com.",
            "TTL":45,
            "type":5,
            "data":"www.taobao.com.danuoyi.tbcache.com."
        },
        {
            "name":"www.taobao.com.danuoyi.tbcache.com.",
            "TTL":45,
            "type":1,
            "data":"47.246.24.234"
        },
        {
            "name":"www.taobao.com.danuoyi.tbcache.com.",
            "TTL":45,
            "type":1,
            "data":"47.246.24.233"
        }
    ]
    //"Authority" 权威段, 如果有数据与Answer字段一致 
    //"Additional" 附加段, 如果有数据与Answer字段一致
    // 可选 "edns_client_subnet":"1.2.3.4/24"  
}

 C#代码

        private static string GetJsonIp(string dnsInfo)
        {
            string ret = string.Empty;
            // 解析 JSON 数据
            JObject jsonResponse = JObject.Parse(dnsInfo);

            // 获取 Answer 数组
            JArray answerArray = (JArray)jsonResponse["Answer"];

            // 查找 A 记录并提取 IP 地址
            string ipAddress = null;
            foreach (JObject answer in answerArray)
            {
                if ((int)answer["type"] == 1) // A 记录类型为 1
                {
                    ipAddress = (string)answer["data"];
                    break;
                }
            }

            if (ipAddress != null)
            {
                Console.WriteLine($"IP Address: {ipAddress}");
                ret = ipAddress;
            }
            else
            {
                Console.WriteLine("No A record found.");
            }
            return ret;
        }

        /// <summary>
        /// 特殊方式获取域名IP ,DOH,默认使用阿里
        /// </summary>
        /// <param name="hostname"></param>
        /// <param name="dnsserver"></param>
        /// <param name="dnsport"></param>
        /// <returns></returns>
        public static async Task<string> GetSpecialDns(string hostname)
        {
            string ret = string.Empty;
            var domain = hostname;
            var type = 1; // A 记录类型
            var uri = new Uri($"http://dns.alidns.com/resolve?name={Uri.EscapeDataString(domain)}&type={type}");

            // 创建 HttpClient 实例
            using (var httpClient = new HttpClient())
            {
                // 设置 Accept
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // 发送 GET 请求
                HttpResponseMessage response = await httpClient.GetAsync(uri);

                if (response.IsSuccessStatusCode)
                {
                    // 读取响应体
                    var responseContent = await response.Content.ReadAsStringAsync();
                    
                    ret = GetJsonIp(responseContent);
                    Console.WriteLine("Response: " + responseContent);
                }
                else
                {
                    Console.WriteLine($"DOH query failed with status code: {response.StatusCode}");
                    // 如果可能,获取错误详情
                    var errorDetails = await response.Content.ReadAsStringAsync();
                    Console.WriteLine($"Error details: {errorDetails}");
                }
            }

            return ret;
        }

09-08 19:04