当前位置:   article > 正文

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

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

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

例子:

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

源声明:

  1. #pragma pack(push, 1)
  2. struct dns_hdr {
  3. uint16_t usTransID; // 标识符
  4. uint16_t usFlags; // 各种标志位
  5. uint16_t usQuestionCount; // Question字段个数
  6. uint16_t usAnswerCount; // Answer字段个数
  7. uint16_t usAuthorityCount; // Authority字段个数
  8. uint16_t usAdditionalCount; // Additional字段个数
  9. };
  10. #pragma pack(pop)
  11. static constexpr int MAX_DOMAINNAME_LEN = 255; /* MAX: 253 +. ≈ 254 BYTE or 254 CHAR+. ≈ 255 BYTE */
  12. static constexpr int DNS_PORT = PPP_DNS_SYS_PORT;
  13. static constexpr int DNS_TYPE_SIZE = 2;
  14. static constexpr int DNS_CLASS_SIZE = 2;
  15. static constexpr int DNS_TTL_SIZE = 4;
  16. static constexpr int DNS_DATALEN_SIZE = 2;
  17. static constexpr int DNS_TYPE_A = 0x0001; //1 a host address
  18. static constexpr int DNS_TYPE_AAAA = 0x001c; //1 a host address
  19. static constexpr int DNS_TYPE_CNAME = 0x0005; //5 the canonical name for an alias
  20. static constexpr int DNS_CLASS_IN = 0x0001;
  21. static constexpr int DNS_PACKET_MAX_SIZE = (sizeof(struct dns_hdr) + MAX_DOMAINNAME_LEN + DNS_TYPE_SIZE + DNS_CLASS_SIZE);
  22. ppp::string ExtractHost(
  23. const Byte* szPacketStartPos,
  24. int nPacketLength) noexcept;
  25. ppp::string ExtractHostX(
  26. const Byte* szPacketStartPos,
  27. int nPacketLength,
  28. const ppp::function<bool(dns_hdr*)>& fPredicateB) noexcept;
  29. ppp::string ExtractHostY(
  30. const Byte* szPacketStartPos,
  31. int nPacketLength,
  32. const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept;
  33. ppp::string ExtractHostZ(
  34. const Byte* szPacketStartPos,
  35. int nPacketLength,
  36. const ppp::function<bool(dns_hdr*)>& fPredicateB,
  37. const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept;

源实现:

  1. static bool ExtractName(char* szEncodedStr, uint16_t* pusEncodedStrLen, char* szDotStr, uint16_t nDotStrSize, char* szPacketStartPos, char* szPacketEndPos, char** ppDecodePos) noexcept
  2. {
  3. if (NULL == szEncodedStr || NULL == pusEncodedStrLen || NULL == szDotStr || szEncodedStr >= szPacketEndPos)
  4. {
  5. return false;
  6. }
  7. char*& pDecodePos = *ppDecodePos;
  8. pDecodePos = szEncodedStr;
  9. uint16_t usPlainStrLen = 0;
  10. uint8_t nLabelDataLen = 0;
  11. *pusEncodedStrLen = 0;
  12. while ((nLabelDataLen = *pDecodePos) != 0x00)
  13. {
  14. // Normal Format,LabelDataLen + Label
  15. if ((nLabelDataLen & 0xc0) == 0)
  16. {
  17. if ((usPlainStrLen + nLabelDataLen + 1) > nDotStrSize || (pDecodePos + nLabelDataLen + 1) >= szPacketEndPos)
  18. {
  19. return false;
  20. }
  21. memcpy(szDotStr + usPlainStrLen, pDecodePos + 1, nLabelDataLen);
  22. memcpy(szDotStr + usPlainStrLen + nLabelDataLen, ".", 1);
  23. pDecodePos += (nLabelDataLen + 1);
  24. usPlainStrLen += (nLabelDataLen + 1);
  25. *pusEncodedStrLen += (nLabelDataLen + 1);
  26. }
  27. else
  28. {
  29. // Message compression format is 11000000 00000000, consisting of two bytes.
  30. // The first two bits are the jump flag, and the last 14 bits are the offset of the jump。
  31. if (NULL == szPacketStartPos)
  32. {
  33. return false;
  34. }
  35. uint16_t usJumpPos = ntohs(*(uint16_t*)(pDecodePos)) & 0x3fff;
  36. uint16_t nEncodeStrLen = 0;
  37. if (!ExtractName(szPacketStartPos + usJumpPos, &nEncodeStrLen, szDotStr + usPlainStrLen, nDotStrSize - usPlainStrLen, szPacketStartPos, szPacketEndPos, ppDecodePos))
  38. {
  39. return false;
  40. }
  41. else
  42. {
  43. *pusEncodedStrLen += 2;
  44. return true;
  45. }
  46. }
  47. }
  48. ++pDecodePos;
  49. szDotStr[usPlainStrLen - 1] = '\0';
  50. *pusEncodedStrLen += 1;
  51. return true;
  52. }
  53. static bool ExtractHost_DefaultPredicateB(dns_hdr* h) noexcept
  54. {
  55. uint16_t usFlags = htons(h->usFlags) & htons(DNS_TYPE_A);
  56. return usFlags != 0;
  57. }
  58. ppp::string ExtractHost(const Byte* szPacketStartPos, int nPacketLength) noexcept
  59. {
  60. ppp::function<bool(dns_hdr*)> predicate = ExtractHost_DefaultPredicateB;
  61. return ExtractHostX(szPacketStartPos, nPacketLength, predicate);
  62. }
  63. ppp::string ExtractHostX(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*)>& fPredicateB) noexcept
  64. {
  65. ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)> fPredicateE =
  66. [](dns_hdr* h, ppp::string& domain, uint16_t type, uint16_t clazz) noexcept -> bool
  67. {
  68. return true;
  69. };
  70. return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);
  71. }
  72. ppp::string ExtractHostY(const Byte* szPacketStartPos, int nPacketLength, const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept
  73. {
  74. ppp::function<bool(dns_hdr*)> fPredicateB = ExtractHost_DefaultPredicateB;
  75. return ExtractHostZ(szPacketStartPos, nPacketLength, fPredicateB, fPredicateE);
  76. }
  77. ppp::string ExtractHostZ(const Byte* szPacketStartPos,
  78. int nPacketLength,
  79. const ppp::function<bool(dns_hdr*)>& fPredicateB,
  80. const ppp::function<bool(dns_hdr*, ppp::string&, uint16_t, uint16_t)>& fPredicateE) noexcept
  81. {
  82. static constexpr int MAX_DOMAINNAME_LEN_STR = MAX_DOMAINNAME_LEN + 1;
  83. if (NULL == fPredicateB || NULL == fPredicateE)
  84. {
  85. return ppp::string();
  86. }
  87. struct dns_hdr* pDNSHeader = (struct dns_hdr*)szPacketStartPos;
  88. if (NULL == pDNSHeader || nPacketLength < sizeof(pDNSHeader))
  89. {
  90. return ppp::string();
  91. }
  92. if (!fPredicateB(pDNSHeader))
  93. {
  94. return ppp::string();
  95. }
  96. int nQuestionCount = htons(pDNSHeader->usQuestionCount);
  97. if (nQuestionCount < 1)
  98. {
  99. return ppp::string();
  100. }
  101. std::shared_ptr<Byte> pioBuffers = make_shared_alloc<Byte>(MAX_DOMAINNAME_LEN_STR);
  102. if (NULL == pioBuffers)
  103. {
  104. return ppp::string();
  105. }
  106. uint16_t pusEncodedStrLen = 0;
  107. char* pDecodePos = NULL;
  108. char* szDomainDotStr = (char*)pioBuffers.get();
  109. if (!ExtractName((char*)(pDNSHeader + 1), &pusEncodedStrLen, szDomainDotStr,
  110. (uint16_t)MAX_DOMAINNAME_LEN_STR, (char*)szPacketStartPos, (char*)szPacketStartPos + nPacketLength, &pDecodePos))
  111. {
  112. return ppp::string();
  113. }
  114. while (pusEncodedStrLen > 0 && szDomainDotStr[pusEncodedStrLen - 1] == '\x0')
  115. {
  116. pusEncodedStrLen--;
  117. }
  118. if (pusEncodedStrLen == 0)
  119. {
  120. return ppp::string();
  121. }
  122. uint16_t* pusDecodePos = (uint16_t*)pDecodePos;
  123. uint16_t usQueriesType = ntohs(pusDecodePos[0]);
  124. uint16_t usQueriesClass = ntohs(pusDecodePos[1]);
  125. ppp::string strDomianStr(szDomainDotStr, pusEncodedStrLen);
  126. if (!fPredicateE(pDNSHeader, strDomianStr, usQueriesType, usQueriesClass))
  127. {
  128. return ppp::string();
  129. }
  130. return strDomianStr.data();
  131. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/763058
推荐阅读
相关标签
  

闽ICP备14008679号