dns-suite.js/README.md

256 lines
6.0 KiB
Markdown
Raw Normal View History

2017-02-23 23:25:39 +00:00
dns-suite
2017-01-21 22:07:10 +00:00
========
2017-02-23 23:25:39 +00:00
Fast, lightweight, and easy-to-extend **pure JavaScript** (ES5.1) implementation for DNS / mDNS.
2017-01-21 22:07:10 +00:00
Works great in **Web Browsers** and in node.js!
Detailed error checking makes it great for
2017-01-21 22:07:10 +00:00
* capture
2017-02-23 23:25:39 +00:00
* packing (JSON to DNS/mDNS)
* parsing (DNS/mDNS to JSON)
2017-01-21 22:07:10 +00:00
* linting (finding errors in packets)
* debugging
2017-02-23 23:25:39 +00:00
**No external dependencies** for node.js or modern browsers. Uses `DataView`, `Uint8Array`, `Uint16Array`, and `ArrayBuffer`
2017-01-21 22:07:10 +00:00
Similar API to `dns.js` and `native-dns-packet`.
2017-01-21 22:11:39 +00:00
```json
2017-02-11 15:51:47 +00:00
{ "header": {
2017-02-17 23:22:56 +00:00
"id": 5423
2017-02-11 15:51:47 +00:00
, "qr": 0
, "opcode": 0
, "aa": 0
, "tc": 0
, "rd": 1
, "ra": 0
, "res1": 0
, "res2": 0
, "res3": 0
, "rcode": 0
}
2017-02-03 04:26:05 +00:00
, "question": [
2017-01-21 22:11:39 +00:00
{ "name": "bowie._sftp-ssh._tcp.local"
, "type": 1
2017-02-11 15:51:47 +00:00
, "typeName": "A"
2017-01-21 22:11:39 +00:00
, "class": 1
2017-02-11 15:51:47 +00:00
, "className": "IN"
2017-01-21 22:11:39 +00:00
, "byteLength": 32
}
]
2017-02-03 04:26:05 +00:00
, "answer": []
2017-01-21 22:11:39 +00:00
, "authority": []
, "additional": []
2017-02-16 21:16:21 +00:00
, "edns_options": []
2017-01-21 22:11:39 +00:00
, "byteLength": 44
}
```
2017-02-23 23:40:20 +00:00
Install with git
2017-01-21 22:07:10 +00:00
-------
2017-02-23 23:40:20 +00:00
You can use git to install v1.x like so:
2017-01-21 22:11:39 +00:00
```bash
# latest of v1.x
npm install 'git+https://git@git.daplie.com:Daplie/dns-suite#v1'
```
2017-02-23 23:40:20 +00:00
If you want to be more specific to v1.0.x or exactly v1.0.2 you can do so like this:
```
# latest of v1.0.x
npm install 'git+https://git@git.daplie.com:Daplie/dns-suite#v1.0'
# exactly v1.0.2
npm install 'git+https://git@git.daplie.com:Daplie/dns-suite#v1.0.2'
```
Install without git
-------
Don't have git? Well you can also bow down to the gods of the centralized, monopolized, concentrated, dictatornet
(as we like to call it here at Daplie Labs), if that's how you roll:
```
npm install --save dns-suite
2017-01-21 22:07:10 +00:00
```
2017-02-03 04:26:05 +00:00
**Test**:
```bash
2017-02-23 23:25:39 +00:00
pushd node_modules/dns-suite
2017-02-03 04:26:05 +00:00
npm test
```
2017-01-21 22:07:10 +00:00
Usage
-----
2017-02-24 01:09:21 +00:00
* CLI
* API
2017-01-21 22:07:10 +00:00
**CLI**
2017-02-23 23:25:39 +00:00
You can work directly from `node_modules/dns-suite`:
2017-01-21 22:07:10 +00:00
2017-01-21 22:11:39 +00:00
```bash
2017-02-23 23:25:39 +00:00
pushd node_modules/dns-suite/
2017-01-21 22:07:10 +00:00
```
Parsing a saved packet
2017-01-21 22:11:39 +00:00
```bash
2017-01-21 22:07:10 +00:00
# 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.
2017-02-03 04:26:05 +00:00
these test packets have the binary for each record type and what it's parsed output
should be.
2017-01-21 22:07:10 +00:00
**Library**
2017-02-24 01:09:21 +00:00
* `DNSPacket.parse(nodeOrArrayBuffer)` returns json (as shown above)
* `DNSPacket.pack(packet)` returns ArrayBuffer (browser and node)
* `DNSPacket.write(packet)` returns NodeBuffer (node only)
2017-01-21 22:07:10 +00:00
node.js:
2017-01-21 22:11:39 +00:00
```js
2017-01-21 22:07:10 +00:00
var nodeBuffer = fs.readFileSync('./samples/a-0.mdns.bin');
var arrayBuffer = nodeBuffer.buffer;
2017-02-24 01:09:21 +00:00
var DNSPacket = require('dns-suite').DNSPacket;
var packet = DNSPacket.parse(arrayBuffer);
var ab = DNSPacket.pack(packet);
2017-01-21 22:07:10 +00:00
console.log(packet);
2017-02-24 01:09:21 +00:00
console.log(new Uint8Array(ab));
2017-01-21 22:07:10 +00:00
```
Browser:
2017-01-21 22:11:39 +00:00
```js
2017-01-21 22:07:10 +00:00
var arrayBuffer = new Uint8Array.from([ /* bytes */ ]).buffer;
2017-02-24 01:09:21 +00:00
var packet = DNSPacket.parse(arrayBuffer);
var ab = DNSPacket.pack(packet);
2017-01-21 22:07:10 +00:00
console.log(packet);
2017-02-24 01:09:21 +00:00
console.log(new Uint8Array(ab));
```
Capturing Packets
-----
We have a command line tool for that! See [dig.js](https://git.daplie.com/Daplie/dig.js).
```
# Install
npm install -g 'git+https://git@git.daplie.com/Daplie/dig.js.git'
# Use with DNS
dig.js A daplie.com --output .
# Use with mDNS
dig.js --mdns PTR _services._dns-sd._udp.local --output .
2017-01-21 22:07:10 +00:00
```
2017-02-11 15:51:47 +00:00
Contributing and Development
============================
How to add a new parser
-----------------------
Each RR (aka Resource Record or RData) parser is individual. Examples include:
2017-02-17 23:22:56 +00:00
* 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`)
2017-02-11 15:51:47 +00:00
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
2017-02-17 23:22:56 +00:00
the name of the type in the format `parser/type.<typename>.js`.
2017-02-11 15:51:47 +00:00
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
```
2) 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`
```bash
node bin/capture-query.js --name www.google.com --type CNAME
```
2017-02-17 23:22:56 +00:00
3) Create `parser/type.cname.js`
2017-02-11 15:51:47 +00:00
2017-02-17 23:22:56 +00:00
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.
2017-02-11 15:51:47 +00:00
```
var unpackLabels = exports.DNS_UNPACK_LABELS || require('./dns.unpack-labels.js').DNS_UNPACK_LABELS;
2017-02-17 23:22:56 +00:00
exports.DNS_PARSER_TYPE_CNAME = function (ab, packet, record) {
2017-02-11 15:51:47 +00:00
// 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));
```
4) 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.
5) 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)
2017-02-17 23:22:56 +00:00
├── packer
| └── type.cname.js
├── parser
| └── type.cname.js
2017-02-11 15:51:47 +00:00
└── test
└── fixtures
   ├── www.google.com.cname.bin
   └── www.google.com.cname.js
```