Fast, lightweight, easy-to-extend, easy-to-test, pure JavaScript (ES5.1) implementation for DNS / mDNS.
Go to file
AJ ONeal 442c5c8a20 update docs 2017-02-17 20:27:13 -07:00
bin create proper ArrayBuffer from NodeBuffer https://github.com/nodejs/node/issues/11132 2017-02-06 10:53:07 -07:00
examples cleanup 2017-01-21 14:44:37 -07:00
packer dir for packer 2017-02-17 16:07:26 -07:00
parser load parsers correctly 2017-02-17 19:38:47 -07:00
samples finished PTR parser 2017-02-01 20:37:28 -07:00
test fix hexdump function 2017-02-17 18:52:15 -07:00
.gitignore ignore generated json files 2017-02-02 21:11:47 -07:00
.gitmodules reorganzing 2017-01-28 13:53:54 -07:00
ORIGINAL_PROBLEM.md update docs 2017-02-17 20:27:13 -07:00
README.md update docs 2017-02-17 20:27:13 -07:00
browser.js started browser code 2017-02-01 21:57:40 -07:00
demo.css started fixing format to match native dns. Spotted bug in unpacking labels. Not fixed yet 2017-02-02 18:39:32 -07:00
demo.html more dir restructure updates 2017-02-17 16:22:56 -07:00
dns.classes.js in reverse also 2017-01-21 13:35:06 -07:00
dns.js started fixing format to match native dns. Spotted bug in unpacking labels. Not fixed yet 2017-02-02 18:39:32 -07:00
dns.packer.js don't modify original object, chimney 2017-02-17 18:57:25 -07:00
dns.parser.js WIP Packer 2017-02-16 14:16:21 -07:00
dns.rdata.pack.js dir for packer 2017-02-17 16:07:26 -07:00
dns.rdata.parse.js load parsers correctly 2017-02-17 19:38:47 -07:00
dns.type.any.js clean up 2017-02-02 14:46:25 -07:00
dns.types.js WIP Packer 2017-02-16 14:16:21 -07:00
dns.unpack-labels.js only add compression pointer length once 2017-02-11 09:54:27 -07:00
notes.md renamed some files and added objective statement and purpose of document 2017-01-14 13:49:40 -07:00
package.json add tests 2017-02-02 21:19:59 -07:00
parse-binary-test.js added the test code that AJ wrote 2017-01-20 17:10:00 -07:00

README.md

dns-lint

Fast, lightweight, pure JavaScript (ES5.1) implementation for DNS / mDNS.

Works great in Web Browsers and in node.js!

Detailed error checking makes it great for

  • capture
  • packing (JSON to DNS)
  • parsing (DNS to JSON)
  • linting (finding errors in packets)
  • debugging

No external dependencies for modern browsers. Uses DataView, Uint8Array, Uint16Array, and ArrayBuffer

Similar API to dns.js and native-dns-packet.

{ "header": {
    "id": 5423
  , "qr": 0
  , "opcode": 0
  , "aa": 0
  , "tc": 0
  , "rd": 1
  , "ra": 0
  , "res1": 0
  , "res2": 0
  , "res3": 0
  , "rcode": 0
  }
, "question": [
    { "name": "bowie._sftp-ssh._tcp.local"
    , "type": 1
    , "typeName": "A"
    , "class": 1
    , "className": "IN"
    , "byteLength": 32
    }
  ]
, "answer": []
, "authority": []
, "additional": []
, "edns_options": []
, "byteLength": 44
}

Install

npm install git+https://git@git.daplie.com:Daplie/dns-lint

Test:

pushd node_modules/dns-lint

npm test

Usage

CLI

You can work directly from node_modules/dns-lint:

pushd node_modules/dns-lint/

Capture mDNS broadcast packets

# example
# node bin/mdns-capture.js <file-prefix>
node bin/mdns-capture.js mdns-test
# in another terminal
dig @224.0.0.251 -p 5353 -t PTR _services._dns-sd._udp.local

Parsing a saved packet

# example
# node bin/dns-parse.js </path/to/packet.dns.bin>
node bin/dns-parse.js samples/a-0.mdns.bin

You can also parse a saved packet from the native-dns-packet directory. these test packets have the binary for each record type and what it's parsed output should be.

Library

  • packet = dnsjs.unpack(arrayBuffer)
  • packet = dnsjs.unpackRdatas(arrayBuffer, packet)
  • packet.answers[0].data = dnsjs.unpackRdatas(arrayBuffer, packet, packet.answers[0])

node.js:

var nodeBuffer = fs.readFileSync('./samples/a-0.mdns.bin');
var arrayBuffer = nodeBuffer.buffer;

var dnsjs = require('dns-lint');
var packet = dnsjs.unpack(arrayBuffer);

console.log(packet);

Browser:

var arrayBuffer = new Uint8Array.from([ /* bytes */ ]).buffer;

var packet = pdns.unpack(arrayBuffer);

console.log(packet);

Contributing and Development

How to add a new parser

Each RR (aka Resource Record or RData) parser is individual. Examples include:

  • A (parser/type.a.js)
  • AAAA (parser/type.aaaa.js)
  • CNAME (parser/type.cname.js)
  • TXT (parser/type.txt.js)
  • SRV (parser/type.srv.js)

Let's say that To create a parser for a type which we don't currently support, just add the appropriate information to dns.types.js and create a file for the name of the type in the format parser/type.<typename>.js.

For example, if CNAME wasn't already supported and I wanted to add support for it I would follow these steps:

  1. Update dns.types.js
  A: 			0x01	//   1
, NS: 		0x02  //   2
, CNAME: 	0x05  //   5    // I would simply add this line
, SOA: 		0x06  //   6
  1. Capture a packet to test/fixtures/<domain>.<tld>.<type>.bin

This will construct and send a DNS query and save the first result that comes back.

In some cases (such as CNAME), the typical (or required) way to illicit the desired response is to make a request of a different type.

If that's the case, manually rename the the file afterwards.

Ideally you should have some idea of what the result file should look like and should place that in test/fixtures/<domain>.<tld>.<type>.json

node bin/capture-query.js --name www.google.com --type CNAME
  1. Create parser/type.cname.js

Copy parser/type.TEMPLATE.js to the type for which you wish to create support (parser/type.cname.js in this example) and fill in the blanks.

var unpackLabels = exports.DNS_UNPACK_LABELS || require('./dns.unpack-labels.js').DNS_UNPACK_LABELS;
exports.DNS_PARSER_TYPE_CNAME = function (ab, packet, record) {
  // record = { rdstart, rdlength, type, class }
  // example of not parsing and just leaving as binary data
  record.data = new Uint8Array(ab.slice(record.rdstart, record.rdstart + record.rdlength));

  return record;
};

}('undefined' !== typeof window ? window : exports));
  1. Document what you've learned in doc/<type>.txt

You may be right or you might be wrong, but you might be right.

In any case, take a minute to document some of the gritty details of what you learned about this record type - tips, tricks, little-known facts, etc.

This may help (or wildly mislead) others if there's a bug in your parser that they need to track down. At the very least someone can follow a few links you followed and your thought process.

  1. Check that my changes include these files
├── README.md
├── demo.html         (add the appropriate script tag)
├── doc
|   └── cname.txt
├── dns.classes.js    (not necessarily, but potentially)
├── dns.types.js
├── package.json      (bump the minor version)
├── packer
|   └── type.cname.js
├── parser
|   └── type.cname.js
└── test
    └── fixtures
        ├── www.google.com.cname.bin
        └── www.google.com.cname.js