DoH(DNS on HTTPS)和DoT(DNS on TLS)协议详解
目录[*]目录
[*]简介
[*]详情
[*]请求
[*]DoH
[*]DoT
[*]返回
[*]DoH
[*]DoT
[*]c-ares的使用
[*]打包
[*]解析
简介
DNS over HTTPS利用HTTP协议的GET命令发出经由JSON等编码的DNS解析请求。较于传统的DNS协议,此处的HTTP协议通信处于具有加密作用的SSL/TLS协议(两者统称作HTTPS)的保护之下。但是,由于HTTPS本身需要经由多次数据来回传递才能完成协议初始化,其域名解析耗时较原DNS协议会显著增加。DNS over TLS(缩写:DoT)是通过传输层安全协议(TLS)来加密并打包域名系统(DNS)的安全协议。本文基于RFC 8484 - DNS Queries over HTTPS (DoH)介绍DoH协议的详情。
此外,本文还基于Boost的Asio、Beast实现了DoH和DoT的解析器ink19/Boost.dns。
详情
DoH和DoT的请求包编码方式就是基于普通的DNS编码,具体可以参考这一篇博文。为了简便,本文使用了c-ares,对DNS的请求和回包进行解析。
请求
DoH
DoH的请求基于HTTPS,其将DNS的请求包使用base64编码,放在了dns参数上,如:
GET /dns-query?dns=BAABAAABAAAAAAABBGhvbWUFaW5rMTkCY24AAAEAAQAAKQIAAAAAAAAA HTTP/1.1Host: doh.pubUser-Agent: Boost.Beast/347Accept: application/dns-message其中需要注意的是Accept为application/dns-message。
DoT
DoT是直接数据流传输,因此不需要使用base64编码,但是为了方便读写,需要在请求包前增加两个字节的请求长度。如:
std::vector<boost::asio::const_buffer> req_buff;uint16_t send_len = req.size();send_len = htons(send_len);req_buff.push_back(asio::buffer(&send_len, sizeof(send_len)));req_buff.push_back(asio::buffer(req.data(), req.size()));返回
DoH
DoH的回包放在body中,为二进制。直接读取解析即可。
DoT
DoT的回包和请求包类似,使用二进制,并有两个字节为前导长度。
c-ares的使用
打包
打包使用函数ares_create_query,签名为
#include <ares.h> int ares_create_query(const char *name, int dnsclass, int type, unsigned short id, int rd, unsigned char **buf, int *buflen, int max_udp_size);获取的buf,使用结束后需要使用ares_free_string释放。
dnsclass和type在<arpa/nameser.h>中定义;id为16位,用于标记请求id;rd用于标识是否需要递归解析。
解析
解析使用ares_parse_xxxx_reply函数,比如A类型解析的签名为
#include <ares.h> int ares_parse_a_reply(const unsigned char *abuf, int alen, struct hostent **host, struct ares_addrttl *addrttls, int *naddrttls);其中host需要使用ares_free_hostent进行释放。
使用方法为(注:该函数的使用方法在官方文档中描述的比较模糊,本文是在github中搜索ares_parse_a_reply后,找到了node库使用该函数的方法)
struct hostent *hosts;int ret = ares_parse_a_reply((const unsigned char *)rsp.data(), rsp.size(), &hosts, NULL, NULL);for (int i = 0; hosts->h_addr_list != NULL; ++i) {uint32_t ip = ntohl(*(uint32_t *)hosts->h_addr_list))}ares_free_hostent(hosts);
[*]DNS over HTTPS - 维基百科,自由的百科全书 ↩︎
[*]DNS over TLS - 维基百科,自由的百科全书 ↩︎
[*]自己动手实现DNS协议 - 苍青浪 - 博客园 ↩︎
[*]c-ares documentation | c-ares: a modern asynchronous DNS resolver ↩︎
[*]node/src/node_cares.cc at 496be457b6a2bc5b01ec13644b9c9783976159b2 · kuno/node ↩︎
页:
[1]