You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
6.9 KiB

3 months ago
  1. # dns-packet
  2. [![](https://img.shields.io/npm/v/dns-packet.svg?style=flat)](https://www.npmjs.org/package/dns-packet) [![](https://img.shields.io/npm/dm/dns-packet.svg)](https://www.npmjs.org/package/dns-packet) [![](https://github.com/github/mafintosh/dns-packet/workflows/ci.yml/badge.svg)](https://github.com/github/mafintosh/dns-packet/workflows/ci.yml) [![Coverage Status](https://coveralls.io/repos/github/mafintosh/dns-packet/badge.svg?branch=master)](https://coveralls.io/github/mafintosh/dns-packet?branch=master)
  3. An [abstract-encoding](https://github.com/mafintosh/abstract-encoding) compliant module for encoding / decoding DNS packets. Lifted out of [multicast-dns](https://github.com/mafintosh/multicast-dns) as a separate module.
  4. ```
  5. npm install dns-packet
  6. ```
  7. ## UDP Usage
  8. ``` js
  9. const dnsPacket = require('dns-packet')
  10. const dgram = require('dgram')
  11. const socket = dgram.createSocket('udp4')
  12. const buf = dnsPacket.encode({
  13. type: 'query',
  14. id: 1,
  15. flags: dnsPacket.RECURSION_DESIRED,
  16. questions: [{
  17. type: 'A',
  18. name: 'google.com'
  19. }]
  20. })
  21. socket.on('message', message => {
  22. console.log(dnsPacket.decode(message)) // prints out a response from google dns
  23. })
  24. socket.send(buf, 0, buf.length, 53, '8.8.8.8')
  25. ```
  26. Also see [the UDP example](examples/udp.js).
  27. ## TCP, TLS, HTTPS
  28. While DNS has traditionally been used over a datagram transport, it is increasingly being carried over TCP for larger responses commonly including DNSSEC responses and TLS or HTTPS for enhanced security. See below examples on how to use `dns-packet` to wrap DNS packets in these protocols:
  29. - [TCP](examples/tcp.js)
  30. - [DNS over TLS](examples/tls.js)
  31. - [DNS over HTTPS](examples/doh.js)
  32. ## API
  33. #### `var buf = packets.encode(packet, [buf], [offset])`
  34. Encodes a DNS packet into a buffer containing a UDP payload.
  35. #### `var packet = packets.decode(buf, [offset])`
  36. Decode a DNS packet from a buffer containing a UDP payload.
  37. #### `var buf = packets.streamEncode(packet, [buf], [offset])`
  38. Encodes a DNS packet into a buffer containing a TCP payload.
  39. #### `var packet = packets.streamDecode(buf, [offset])`
  40. Decode a DNS packet from a buffer containing a TCP payload.
  41. #### `var len = packets.encodingLength(packet)`
  42. Returns how many bytes are needed to encode the DNS packet
  43. ## Packets
  44. Packets look like this
  45. ``` js
  46. {
  47. type: 'query|response',
  48. id: optionalIdNumber,
  49. flags: optionalBitFlags,
  50. questions: [...],
  51. answers: [...],
  52. additionals: [...],
  53. authorities: [...]
  54. }
  55. ```
  56. The bit flags available are
  57. ``` js
  58. packet.RECURSION_DESIRED
  59. packet.RECURSION_AVAILABLE
  60. packet.TRUNCATED_RESPONSE
  61. packet.AUTHORITATIVE_ANSWER
  62. packet.AUTHENTIC_DATA
  63. packet.CHECKING_DISABLED
  64. ```
  65. To use more than one flag bitwise-or them together
  66. ``` js
  67. var flags = packet.RECURSION_DESIRED | packet.RECURSION_AVAILABLE
  68. ```
  69. And to check for a flag use bitwise-and
  70. ``` js
  71. var isRecursive = message.flags & packet.RECURSION_DESIRED
  72. ```
  73. A question looks like this
  74. ``` js
  75. {
  76. type: 'A', // or SRV, AAAA, etc
  77. class: 'IN', // one of IN, CS, CH, HS, ANY. Default: IN
  78. name: 'google.com' // which record are you looking for
  79. }
  80. ```
  81. And an answer, additional, or authority looks like this
  82. ``` js
  83. {
  84. type: 'A', // or SRV, AAAA, etc
  85. class: 'IN', // one of IN, CS, CH, HS
  86. name: 'google.com', // which name is this record for
  87. ttl: optionalTimeToLiveInSeconds,
  88. (record specific data, see below)
  89. }
  90. ```
  91. ## Supported record types
  92. #### `A`
  93. ``` js
  94. {
  95. data: 'IPv4 address' // fx 127.0.0.1
  96. }
  97. ```
  98. #### `AAAA`
  99. ``` js
  100. {
  101. data: 'IPv6 address' // fx fe80::1
  102. }
  103. ```
  104. #### `CAA`
  105. ``` js
  106. {
  107. flags: 128, // octet
  108. tag: 'issue|issuewild|iodef',
  109. value: 'ca.example.net',
  110. issuerCritical: false
  111. }
  112. ```
  113. #### `CNAME`
  114. ``` js
  115. {
  116. data: 'cname.to.another.record'
  117. }
  118. ```
  119. #### `DNAME`
  120. ``` js
  121. {
  122. data: 'dname.to.another.record'
  123. }
  124. ```
  125. #### `DNSKEY`
  126. ``` js
  127. {
  128. flags: 257, // 16 bits
  129. algorithm: 1, // octet
  130. key: Buffer
  131. }
  132. ```
  133. #### `DS`
  134. ``` js
  135. {
  136. keyTag: 12345,
  137. algorithm: 8,
  138. digestType: 1,
  139. digest: Buffer
  140. }
  141. ```
  142. #### `HINFO`
  143. ``` js
  144. {
  145. data: {
  146. cpu: 'cpu info',
  147. os: 'os info'
  148. }
  149. }
  150. ```
  151. #### `MX`
  152. ``` js
  153. {
  154. preference: 10,
  155. exchange: 'mail.example.net'
  156. }
  157. ```
  158. #### `NAPTR`
  159. ``` js
  160. {
  161. data:
  162. {
  163. order: 100,
  164. preference: 10,
  165. flags: 's',
  166. services: 'SIP+D2U',
  167. regexp: '!^.*$!sip:customer-service@example.com!',
  168. replacement: '_sip._udp.example.com'
  169. }
  170. }
  171. ```
  172. #### `NS`
  173. ``` js
  174. {
  175. data: nameServer
  176. }
  177. ```
  178. #### `NSEC`
  179. ``` js
  180. {
  181. nextDomain: 'a.domain',
  182. rrtypes: ['A', 'TXT', 'RRSIG']
  183. }
  184. ```
  185. #### `NSEC3`
  186. ``` js
  187. {
  188. algorithm: 1,
  189. flags: 0,
  190. iterations: 2,
  191. salt: Buffer,
  192. nextDomain: Buffer, // Hashed per RFC5155
  193. rrtypes: ['A', 'TXT', 'RRSIG']
  194. }
  195. ```
  196. #### `NULL`
  197. ``` js
  198. {
  199. data: Buffer('any binary data')
  200. }
  201. ```
  202. #### `OPT`
  203. [EDNS0](https://tools.ietf.org/html/rfc6891) options.
  204. ``` js
  205. {
  206. type: 'OPT',
  207. name: '.',
  208. udpPayloadSize: 4096,
  209. flags: packet.DNSSEC_OK,
  210. options: [{
  211. // pass in any code/data for generic EDNS0 options
  212. code: 12,
  213. data: Buffer.alloc(31)
  214. }, {
  215. // Several EDNS0 options have enhanced support
  216. code: 'PADDING',
  217. length: 31,
  218. }, {
  219. code: 'CLIENT_SUBNET',
  220. family: 2, // 1 for IPv4, 2 for IPv6
  221. sourcePrefixLength: 64, // used to truncate IP address
  222. scopePrefixLength: 0,
  223. ip: 'fe80::',
  224. }, {
  225. code: 'TCP_KEEPALIVE',
  226. timeout: 150 // increments of 100ms. This means 15s.
  227. }, {
  228. code: 'KEY_TAG',
  229. tags: [1, 2, 3],
  230. }]
  231. }
  232. ```
  233. The options `PADDING`, `CLIENT_SUBNET`, `TCP_KEEPALIVE` and `KEY_TAG` support enhanced de/encoding. See [optionscodes.js](https://github.com/mafintosh/dns-packet/blob/master/optioncodes.js) for all supported option codes. If the `data` property is present on a option, it takes precedence. On decoding, `data` will always be defined.
  234. #### `PTR`
  235. ``` js
  236. {
  237. data: 'points.to.another.record'
  238. }
  239. ```
  240. #### `RP`
  241. ``` js
  242. {
  243. mbox: 'admin.example.com',
  244. txt: 'txt.example.com'
  245. }
  246. ```
  247. #### `SSHFP`
  248. ``` js
  249. {
  250. algorithm: 1,
  251. hash: 1,
  252. fingerprint: 'A108C9F834354D5B37AF988141C9294822F5BC00'
  253. }
  254. ````
  255. #### `RRSIG`
  256. ``` js
  257. {
  258. typeCovered: 'A',
  259. algorithm: 8,
  260. labels: 1,
  261. originalTTL: 3600,
  262. expiration: timestamp,
  263. inception: timestamp,
  264. keyTag: 12345,
  265. signersName: 'a.name',
  266. signature: Buffer
  267. }
  268. ```
  269. #### `SOA`
  270. ``` js
  271. {
  272. data:
  273. {
  274. mname: domainName,
  275. rname: mailbox,
  276. serial: zoneSerial,
  277. refresh: refreshInterval,
  278. retry: retryInterval,
  279. expire: expireInterval,
  280. minimum: minimumTTL
  281. }
  282. }
  283. ```
  284. #### `SRV`
  285. ``` js
  286. {
  287. data: {
  288. port: servicePort,
  289. target: serviceHostName,
  290. priority: optionalServicePriority,
  291. weight: optionalServiceWeight
  292. }
  293. }
  294. ```
  295. #### `TLSA`
  296. ``` js
  297. {
  298. usage: 3,
  299. selector: 1,
  300. matchingType: 1,
  301. certificate: Buffer
  302. }
  303. ```
  304. #### `TXT`
  305. ``` js
  306. {
  307. data: 'text' || Buffer || [ Buffer || 'text' ]
  308. }
  309. ```
  310. When encoding, scalar values are converted to an array and strings are converted to UTF-8 encoded Buffers. When decoding, the return value will always be an array of Buffer.
  311. If you need another record type, open an issue and we'll try to add it.
  312. ## License
  313. MIT