我想在C或CGO中缝合GNU GPL许可的Knot Resolver模块,该模块将检查客户端的查询和相应的已解决答案,目的是查询提供恶意软件感染主机名的知识库的外部API和IP地址(例如GNU AGPL v3 IntelMQ)。
如果与已解析的A(AAAA)的IP地址匹配,则应记录它,同样应记录与查询的主机名的匹配或(可选)它可能导致向客户端发送一个下沉的IP地址而不是已解决的那个。
我研究了the layers,我得出结论,我感兴趣的阶段是consume
。我不想影响解决过程,我只是想在最后一刻介入并检查结果并可能修改它们。
我冒昧地注册了一个consume功能 与
static knot_layer_api_t _layer = {
.consume = &consume,
};
但我不确定这是否适合做这件事。
此外,我还研究了模块hints.c,特别是它的query
方法
和模块stats.c用于其_to_wire
函数用法。
何时是在发送给客户端之前介入并读取/写入查询的答案的正确时间?我在消费层中的正确位置吗?
如果以下尝试获取已解析的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地址和CNAME,并查看它们被解析的IP地址。
如果模块设置需要它,我希望能够“抛弃”已解决的答案,并提供一个新的,包括指向下沉的A记录。
如何准备记录,以便在正确的阶段将记录从char*
转换为Knot的有线格式以及正确的上下文中的正确结构?
我想它可能会出现knot_rrset_init
和knot_rrset_add_rdata
这样的功能,但我无法获得任何成功的结果。
指示和建议的THX。
答案 0 :(得分:3)
如果您想在最后确定响应但尚未发送给请求者的最后时刻,那么正确的位置是finish
。您也可以在consume
中执行此操作,但是您将在此处覆盖权威服务器的响应,而不是对请求者的汇总响应(这意味着DNSSEC验证程序可能会停止您的重写答案)。
免责声明:Go界面粗糙,需要大量CGO代码才能访问内部结构。您可能更适合LuaJIT模块,您可以将另一个模块doing something similar作为示例,它还具有用于从文本等创建记录的包装器。如果您仍想要这样做,欢迎阅读Go界面的精彩和改进。
您需要做的大致是this(作为CGO)。
这将引导您完成数据包中的RR集(C.knot_rrset_t
),
您可以在其中匹配类型(rr.type
)和内容(rr.rdata
)。
内容以DNS有线格式存储,对于地址记录,它是网络字节顺序的地址,例如, {0x7f, 0, 0, 1}
。
您必须将其与您在C代码中寻找的地址/子网进行比较 - example。
当您找到匹配项时,您希望清除整个数据包并插入sinkhole记录(您无法有选择地删除记录,因为该数据包仅出于性能原因而附加。)这相对容易,因为a helper就是这样。来自policy
模块的code in LuaJIT,您必须使用上面提到的所有函数并使用A / AAAA sinkhole记录而不是SOA来在Go中重写它。祝你好运!