Dns 结解析:如何在正确的时间观察和修改已解析的答案 目标

Dns 结解析:如何在正确的时间观察和修改已解析的答案 目标,dns,Dns,我想在C或CGO中缝合一个GNU GPL许可的结解析程序模块,该模块将检查客户端的查询和相应的解析答案,目的是查询提供恶意软件感染主机名和ip地址知识库的外部API(例如GNU AGPL v3) 如果与要记录的已解析a(AAAA)IP地址匹配,则同样应记录与查询主机名的匹配,或者(可选)可能导致向客户端发送一个灰坑的IP地址,而不是解析的IP地址 方法 我研究并得出结论,我感兴趣的阶段是消费。我不想影响解决过程,我只想在最后一刻介入,检查结果,并可能修改它们 我大胆地注册了a函数 与 但我不确定

我想在C或CGO中缝合一个GNU GPL许可的结解析程序模块,该模块将检查客户端的查询和相应的解析答案,目的是查询提供恶意软件感染主机名和ip地址知识库的外部API(例如GNU AGPL v3)

如果与要记录的已解析a(AAAA)IP地址匹配,则同样应记录与查询主机名的匹配,或者(可选)可能导致向客户端发送一个灰坑的IP地址,而不是解析的IP地址

方法 我研究并得出结论,我感兴趣的阶段是消费。我不想影响解决过程,我只想在最后一刻介入,检查结果,并可能修改它们

我大胆地注册了a函数 与

但我不确定这是个合适的地方

此外,我还研究了这个模块,特别是它的
query
方法 以及用于其
\u至\u线
功能使用的模块

问题: 相位(层?) 在将查询发送到客户端之前,什么时候是介入并读取/写入查询答案的正确时间?我在消费层的位置对吗

回答部分 如果以下获取解析IP地址的尝试为我提供了名称服务器地址:

char addr_str[INET6_ADDRSTRLEN];
memset(addr_str, 0, sizeof(addr_str));
const struct sockaddr *src = &(req->answer->sections);
inet_ntop(qry->ns.addr[0].ip.sa_family, kr_inaddr(src), addr_str, sizeof(addr_str));
DEBUG_MSG(NULL, "ADDR: %s\n", addr_str);
如何获取查询主机名的解析(A,AAAA)IP地址?我想在答案中重复A/AAAA IP地址和CNAMEs,并查看它们解析到的IP地址

修改答案 如果模块设置需要,我希望能够“抛弃”已解决的答案,并提供一个新的答案,包括指向落水坑的a记录

如何准备记录,以便将其从
char*
转换为Knot的wire格式,并在正确的阶段在正确的上下文中转换为正确的结构

我想它可能会使用诸如
knot\rrset\u init
knot\rrset\u add\u rdata
之类的函数,但我无法获得任何成功的结果


THX用于指针和建议。

如果您想在响应完成但尚未发送给请求者的最后时刻介入,正确的位置是
finish
。您也可以在
consume
中执行此操作,但您将覆盖来自权威服务器的响应,而不是对请求者的组合响应(这意味着DNSSEC validator可能会停止您重写的答案)

免责声明:Go界面粗糙,需要大量CGO代码才能访问内部结构。LuaJIT模块可能更适合您,您可以以另一个模块为例,它还具有用于从文本等创建记录的包装器。如果您仍然想这样做,那太棒了,欢迎改进to Go界面,请继续阅读

您需要做的大致是(作为CGO)。 这将引导您遍历数据包中的RR集(
C.knot\u rrset\u t
), 您可以在其中匹配类型(
rr.type
)和内容(
rr.rdata
)。 内容以DNS wire格式存储,对于地址记录,它是网络字节顺序的地址,例如
{0x7f,0,0,1}
。 您必须将其与您正在寻找的地址/子网进行比较-在C代码中


当您找到匹配项时,您希望清除整个数据包并插入陷穴记录(您不能有选择地删除记录,因为数据包只是出于性能原因而附加的)。这是相对容易的,因为这是有。这是来自
policy
模块的,您必须在Go中重写它,使用上面提到的所有函数,并使用/AAAA天坑记录而不是SOA。祝你好运

如果您想在响应完成但尚未发送给请求者的最后时刻介入,正确的位置是
finish
。您也可以在
consume
中执行此操作,但您将覆盖来自权威服务器的响应,而不是对请求者的组合响应(这意味着DNSSEC validator可能会停止您重写的答案)

免责声明:Go界面粗糙,需要大量CGO代码才能访问内部结构。LuaJIT模块可能更适合您,您可以以另一个模块为例,它还具有用于从文本等创建记录的包装器。如果您仍然想这样做,那太棒了,欢迎改进to Go界面,请继续阅读

您需要做的大致是(作为CGO)。 这将引导您遍历数据包中的RR集(
C.knot\u rrset\u t
), 您可以在其中匹配类型(
rr.type
)和内容(
rr.rdata
)。 内容以DNS wire格式存储,对于地址记录,它是网络字节顺序的地址,例如
{0x7f,0,0,1}
。 您必须将其与您正在寻找的地址/子网进行比较-在C代码中


当您找到匹配项时,您希望清除整个数据包并插入陷穴记录(您不能有选择地删除记录,因为数据包只是出于性能原因而附加的)。这是相对容易的,因为这是有。这是来自
policy
模块的,您必须在Go中重写它,使用上面提到的所有函数,并使用/AAAA天坑记录而不是SOA。祝你好运

马瑞克,你能给我一个提示吗,你是否应该清除整个包
knot\u pkt\u clear
(记住msgid
knot\u wire\u get\u id
),或者只清除
knot\u rdataset\u clear
?考虑到以下顺序是有意义的:
knot\u pkt\u begin
knot\u rdata\u init
knot\u wire\u set\u rcode
not\u wire\u set\u nscount
knot\u wire\u add\u ancount
kr\u pkt\u put
。插入libknot(和kresd)中的数据包中的记录将被串行化,以避免丢失
char addr_str[INET6_ADDRSTRLEN];
memset(addr_str, 0, sizeof(addr_str));
const struct sockaddr *src = &(req->answer->sections);
inet_ntop(qry->ns.addr[0].ip.sa_family, kr_inaddr(src), addr_str, sizeof(addr_str));
DEBUG_MSG(NULL, "ADDR: %s\n", addr_str);