C++使用WINAPI查询DNS解析记录

C++使用WINAPI查询DNS解析记录

KaguraiYoRoy
2025-03-20 / 0 评论 / 19 阅读 / 正在检测是否收录...

这篇文章是古早时期的博客上迁移过来的(什么赛博秽土转生),如有错误欢迎指正

背景

为API配置了多条访问线路,以应对部分地区无法访问导致服务不可用的情况。开始是想到在网站里新建一个文件保存节点信息,发现行不通,联不通的地区根本无法获知其他线路;于是想到用DNS解析记录,用一个TXT解析记录来保存相应的节点数据,以备查询

实战

查询资料

一番Bing下来,发现大部分现有的文章都是使用socket来直接发送查询数据包,获取到的也都是A和CNAME类型的记录,方案不可行。最后,把目光锁定到了MSDN上的DnsQuery函数上,同时找到一篇样例:使用DnsQuery解析主机名

函数分析

从官方文档上得知,函数所需头文件为windns.h,需要包含引入库文件Ws2_32.lib和Dnsapi.lib,函数的参数如下:

DNS_STATUS DnsQuery_A(
  [in]                PCSTR       pszName,
  [in]                WORD        wType,
  [in]                DWORD       Options,
  [in, out, optional] PVOID       pExtra,
  [out, optional]     PDNS_RECORD *ppQueryResults,
  [out, optional]     PVOID       *pReserved
);

参数解释:

  • pszName是要查询的主机名;
  • wType是查询类型,如A记录,CNAME,TXT等,具体的MSDN官方给出了文档:DNS Constants
  • Options字面意思上理解是查询方式,我直接使用DNS_QUERY_STANDARD,具体也可以查询文档:DNS Constants
  • pExtrapReserved直接给NULL就行
  • ppQueryResults传入查询结果的指针,类型是PDNS_RECORD,这个需要传入变量值的引用。
  • 返回值,DNS_STATUS类型,如果查询失败会返回Winerror.h中的相应错误码

使用

明白了使用方法,那就简单了:
我的TXT记录域名为test.iyoroy.cn,查询部分代码如下:

PDNS_RECORD pDnsRecord;
DNS_STATUS QueryRet = DnsQuery(L"test.iyoroy.cn", DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &pDnsRecord, NULL);
if (QueryRet) {
    MessageBox(GhWnd, L"DNS查询失败!\r\n将使用默认节点", L"Warning", MB_ICONERROR | MB_OK); 
}
std::wstring strQueryRes = *pDnsRecord->Data.TXT.pStringArray;//这个就是查询结果

成功实现功能

后记

TXT记录会自动过滤掉空格、换行,因此我选择记录base64编码,使用时再解码并使用stringstream拆分空格。Base64解码我借鉴了这篇文章:C++进行base64编码和解码,以下是我用宽字节重写的解码函数

之后再选择可用节点就行


参考文章:

1

评论 (0)

取消