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