C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容

2024-06-20 08:36

本文主要是介绍C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

它主要是提取DNS数据包之中查询问题的信息,如:问题类型、问题类别、问题内容(域/IP),我们如果想要对于某个DNS数据包需要进行遥测的时,或者进行NS缓存生命周期管理,那么就需要类似这样的函数实现了。

例子:

                uint16_t queries_type = 0;uint16_t queries_clazz = 0;ppp::string domain = ppp::net::native::dns::ExtractHostY((Byte*)packet, packet_length,[&queries_type, &queries_clazz](ppp::net::native::dns::dns_hdr* h, ppp::string& domain, uint16_t type, uint16_t clazz) noexcept -> bool {queries_type = type;queries_clazz = clazz;return true;});

源声明:

#pragma pack(push, 1)struct dns_hdr {uint16_t                                                                usTransID;         // 标识符uint16_t                                                                usFlags;           // 各种标志位uint16_t                                                                usQuestionCount;   // Question字段个数 uint16_t                                                                usAnswerCount;     // Answer字段个数uint16_t                                                                usAuthorityCount;  // Authority字段个数uint16_t                                                                usAdditionalCount; // Additional字段个数};
#pragma pack(pop)static constexpr int MAX_DOMAINNAME_LEN                                     = 255; /* MAX: 253 +. ≈ 254 BYTE or 254 CHAR+. ≈ 255 BYTE */static constexpr int DNS_PORT                                               = PPP_DNS_SYS_PORT;static constexpr int DNS_TYPE_SIZE                                          = 2;static constexpr int DNS_CLASS_SIZE                                         = 2;static constexpr int DNS_TTL_SIZE                                           = 4;static constexpr int DNS_DATALEN_SIZE                                       = 2;static constexpr int DNS_TYPE_A                                             = 0x0001; //1 a host addressstatic constexpr int DNS_TYPE_AAAA                                          = 0x001c; //1 a host addressstatic constexpr int DNS_TYPE_CNAME                                         = 0x0005; //5 the canonical name for an aliasstatic constexpr int DNS_CLASS_IN                                           = 0x0001;static constexpr int DNS_PACKET_MAX_SIZE                                    = (sizeof(struct dns_hdr) + MAX_DOMAINNAME_LEN + DNS_TYPE_SIZE + DNS_CLASS_SIZE);ppp::string                                                                 ExtractHost(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength) noexcept;ppp::string                                                                 ExtractHostX(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB) noexcept;ppp::string                                                                 ExtractHostY(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept;ppp::string                                                                 ExtractHostZ(const Byte*                                                             szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept;

源实现:

                static bool ExtractName(char* szEncodedStr, uint16_t* pusEncodedStrLen, char* szDotStr, uint16_t nDotStrSize, char* szPacketStartPos, char* szPacketEndPos, char** ppDecodePos) noexcept{if (NULL == szEncodedStr || NULL == pusEncodedStrLen || NULL == szDotStr || szEncodedStr >= szPacketEndPos){return false;}char*& pDecodePos = *ppDecodePos;pDecodePos = szEncodedStr;uint16_t usPlainStrLen = 0;uint8_t nLabelDataLen = 0;*pusEncodedStrLen = 0;while ((nLabelDataLen = *pDecodePos) != 0x00){// Normal Format,LabelDataLen + Labelif ((nLabelDataLen & 0xc0) == 0) {if ((usPlainStrLen + nLabelDataLen + 1) > nDotStrSize || (pDecodePos + nLabelDataLen + 1) >= szPacketEndPos){return false;}memcpy(szDotStr + usPlainStrLen, pDecodePos + 1, nLabelDataLen);memcpy(szDotStr + usPlainStrLen + nLabelDataLen, ".", 1);pDecodePos += (nLabelDataLen + 1);usPlainStrLen += (nLabelDataLen + 1);*pusEncodedStrLen += (nLabelDataLen + 1);}else  {// Message compression format is 11000000 00000000, consisting of two bytes. // The first two bits are the jump flag, and the last 14 bits are the offset of the jump。if (NULL == szPacketStartPos){return false;}uint16_t usJumpPos = ntohs(*(uint16_t*)(pDecodePos)) & 0x3fff;uint16_t nEncodeStrLen = 0;if (!ExtractName(szPacketStartPos + usJumpPos, &nEncodeStrLen, szDotStr + usPlainStrLen, nDotStrSize - usPlainStrLen, szPacketStartPos, szPacketEndPos, ppDecodePos)){return false;}else{*pusEncodedStrLen += 2;return true;}}}++pDecodePos;szDotStr[usPlainStrLen - 1] = '\0';*pusEncodedStrLen += 1;return true;}static bool ExtractHost_DefaultPredicateB(dns_hdr* h) noexcept{uint16_t usFlags = htons(h->usFlags) & htons(DNS_TYPE_A);return usFlags != 0;}ppp::string ExtractHost(const Byte* szPacketStartPos, int nPacketLength) noexcept{ppp::function<bool(dns_hdr*)> predicate = ExtractHost_DefaultPredicateB;return ExtractHostX(szPacketStartPos, nPacketLength, predicate);}ppp::string ExtractHostX(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*)>& fPredicateB) noexcept{ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)> fPredicateE =[](dns_hdr* h, ppp::string& domain, uint16_t type, uint16_t clazz) noexcept -> bool{return true;};return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);}ppp::string ExtractHostY(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept{ppp::function<bool(dns_hdr*)> fPredicateB = ExtractHost_DefaultPredicateB;return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);}ppp::string ExtractHostZ(const Byte*                                        szPacketStartPos, int                                                                     nPacketLength, const ppp::function<bool(dns_hdr*)>&                                    fPredicateB, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>&  fPredicateE) noexcept{static constexpr int MAX_DOMAINNAME_LEN_STR = MAX_DOMAINNAME_LEN + 1;if (NULL == fPredicateB || NULL == fPredicateE){return ppp::string();}struct dns_hdr* pDNSHeader = (struct dns_hdr*)szPacketStartPos;if (NULL == pDNSHeader || nPacketLength < sizeof(pDNSHeader)){return ppp::string();}if (!fPredicateB(pDNSHeader)){return ppp::string();}int nQuestionCount = htons(pDNSHeader->usQuestionCount);if (nQuestionCount < 1){return ppp::string();}std::shared_ptr<Byte> pioBuffers = make_shared_alloc<Byte>(MAX_DOMAINNAME_LEN_STR);if (NULL == pioBuffers) {return ppp::string();}uint16_t pusEncodedStrLen = 0;char* pDecodePos = NULL;char* szDomainDotStr = (char*)pioBuffers.get();if (!ExtractName((char*)(pDNSHeader + 1), &pusEncodedStrLen, szDomainDotStr,(uint16_t)MAX_DOMAINNAME_LEN_STR, (char*)szPacketStartPos, (char*)szPacketStartPos + nPacketLength, &pDecodePos)){return ppp::string();}while (pusEncodedStrLen > 0 && szDomainDotStr[pusEncodedStrLen - 1] == '\x0'){pusEncodedStrLen--;}if (pusEncodedStrLen == 0){return ppp::string();}uint16_t* pusDecodePos = (uint16_t*)pDecodePos;uint16_t usQueriesType = ntohs(pusDecodePos[0]);uint16_t usQueriesClass = ntohs(pusDecodePos[1]);ppp::string strDomianStr(szDomainDotStr, pusEncodedStrLen);if (!fPredicateE(pDNSHeader, strDomianStr, usQueriesType, usQueriesClass)){return ppp::string();}return strDomianStr.data();}

这篇关于C/C++ 提取DNS请求/响应数据包之中的 Quesion 内容的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077634

相关文章

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)