Compare commits
	
		
			No commits in common. "master" and "v1.1.0" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										16
									
								
								.jshintrc
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								.jshintrc
									
									
									
									
									
								
							| @ -1,16 +0,0 @@ | |||||||
| { "node": true |  | ||||||
| , "browser": true |  | ||||||
| , "jquery": true |  | ||||||
| , "strict": true |  | ||||||
| , "indent": 2 |  | ||||||
| , "onevar": true |  | ||||||
| , "laxcomma": true |  | ||||||
| , "laxbreak": true |  | ||||||
| , "eqeqeq": true |  | ||||||
| , "immed": true |  | ||||||
| , "undef": true |  | ||||||
| , "unused": true |  | ||||||
| , "latedef": true |  | ||||||
| , "curly": true |  | ||||||
| , "trailing": true |  | ||||||
| } |  | ||||||
							
								
								
									
										1
									
								
								BUGS.txt
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								BUGS.txt
									
									
									
									
									
								
							| @ -1 +0,0 @@ | |||||||
| Currently allows labels to be terminated by rdata length. This was a mistake. They should always be terminated by a null character. |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| v1.3.6 - A suitable replacement for most of my uses for big |  | ||||||
|     * Can capture dns packets in binary and JSON |  | ||||||
|     * Parses common record types including: |  | ||||||
|         * A,AAAA,CAA,CNAME,MX,NS,PTR,SOA,SRV,TXT |  | ||||||
|         * Arbitrary TYPExxx support |  | ||||||
|     * Known Bug: should error when label in rdata is not null terminated |  | ||||||
							
								
								
									
										41
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								LICENSE
									
									
									
									
									
								
							| @ -1,41 +0,0 @@ | |||||||
| Copyright 2017 AJ ONeal |  | ||||||
| 
 |  | ||||||
| This is open source software; you can redistribute it and/or modify it under the |  | ||||||
| terms of either: |  | ||||||
| 
 |  | ||||||
|    a) the "MIT License" |  | ||||||
|    b) the "Apache-2.0 License" |  | ||||||
| 
 |  | ||||||
| MIT License |  | ||||||
| 
 |  | ||||||
|    Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
|    of this software and associated documentation files (the "Software"), to deal |  | ||||||
|    in the Software without restriction, including without limitation the rights |  | ||||||
|    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |  | ||||||
|    copies of the Software, and to permit persons to whom the Software is |  | ||||||
|    furnished to do so, subject to the following conditions: |  | ||||||
| 
 |  | ||||||
|    The above copyright notice and this permission notice shall be included in all |  | ||||||
|    copies or substantial portions of the Software. |  | ||||||
| 
 |  | ||||||
|    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |  | ||||||
|    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
|    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |  | ||||||
|    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |  | ||||||
|    SOFTWARE. |  | ||||||
| 
 |  | ||||||
| Apache-2.0 License Summary |  | ||||||
| 
 |  | ||||||
|    Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|    you may not use this file except in compliance with the License. |  | ||||||
|    You may obtain a copy of the License at |  | ||||||
| 
 |  | ||||||
|      http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| 
 |  | ||||||
|    Unless required by applicable law or agreed to in writing, software |  | ||||||
|    distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|    See the License for the specific language governing permissions and |  | ||||||
|    limitations under the License. |  | ||||||
							
								
								
									
										59
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								README.md
									
									
									
									
									
								
							| @ -1,34 +1,27 @@ | |||||||
| dig.js | dig.js | ||||||
| ====== | ====== | ||||||
| 
 | 
 | ||||||
| | [dns-suite](https://git.coolaj86.com/coolaj86/dns-suite) |  | ||||||
| | **dig.js** |  | ||||||
| | [mdig.js](https://git.coolaj86.com/coolaj86/mdig.js) |  | ||||||
| | [digd.js](https://git.coolaj86.com/coolaj86/digd.js) |  | ||||||
| | Sponsored by [ppl](https://ppl.family)[.](https://dapliefounder.com) |  | ||||||
| 
 |  | ||||||
| Create and capture DNS and mDNS query and response packets to disk as binary and/or JSON. | Create and capture DNS and mDNS query and response packets to disk as binary and/or JSON. | ||||||
| Options are similar to the Unix `dig` command. Supports dns0x20 security checking. | Options are similar to the Unix `dig` command. | ||||||
| 
 | 
 | ||||||
| Install | Install with git | ||||||
| ------- | ------- | ||||||
| 
 | 
 | ||||||
| ### with git |  | ||||||
| 
 |  | ||||||
| ```bash | ```bash | ||||||
| # Install the latest of v1.x | # Install the latest of v1.x | ||||||
| npm install -g 'git+https://git.coolaj86.com/coolaj86/dig.js.git#v1' | npm install -g 'git+https://git@git.daplie.com/Daplie/dig.js.git#v1' | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| # Install exactly v1.0.0 | # Install exactly v1.0.0 | ||||||
| npm install -g 'git+https://git.coolaj86.com/coolaj86/dig.js.git#v1.0.0' | npm install -g 'git+https://git@git.daplie.com/Daplie/dig.js.git#v1.0.0' | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### without git | Install without git | ||||||
|  | ------- | ||||||
| 
 | 
 | ||||||
| Don't have git? Well, you can also bow down to the gods of the centralized, monopolized, concentrated, *dictator*net | Don't have git? Well, you can also bow down to the gods of the centralized, monopolized, concentrated, *dictator*net | ||||||
| (as we like to call it here at ppl Labs), if that's how you roll: | (as we like to call it here at Daplie Labs), if that's how you roll: | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| npm install -g dig.js | npm install -g dig.js | ||||||
| @ -37,14 +30,16 @@ npm install -g dig.js | |||||||
| Usage | Usage | ||||||
| ----- | ----- | ||||||
| 
 | 
 | ||||||
|  | ### Format | ||||||
|  | 
 | ||||||
| ```bash | ```bash | ||||||
| dig.js [TYPE] <domainname> | dig.js [TYPE] <domainname> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **Example**: | ### Example | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| dig.js coolaj86.com | dig.js daplie.com | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### mDNS Browser Example | ### mDNS Browser Example | ||||||
| @ -64,40 +59,24 @@ dig.js -p 5353 @224.0.0.251 PTR _services._dns-sd._udp.local +time=3 | |||||||
| ### Moar Examples | ### Moar Examples | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| dig.js A coolaj86.com | dig.js A daplie.com | ||||||
| 
 | 
 | ||||||
| dig.js @8.8.8.8 A coolaj86.com | dig.js -t A daplie.com | ||||||
|  | 
 | ||||||
|  | dig.js @8.8.8.8 A daplie.com | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Options | Options | ||||||
| ------- | ------- | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | --debug | ||||||
|  | --mdns | ||||||
| --output <path/to/file>     write query and response(s) to disk with this path prefix (ex: ./samples/dns) | --output <path/to/file>     write query and response(s) to disk with this path prefix (ex: ./samples/dns) | ||||||
| 
 | -t <type> (superfluous)     default ANY (mdns default: PTR) | ||||||
| --mdns                      Use mDNS port and nameserver address, and listen for multiple packets |  | ||||||
| 
 |  | ||||||
| -t <type> (superfluous)     A, CNAME, MX, etc. Also supports -t type<decimal> for "unsupported" types. default ANY (mdns default: PTR) |  | ||||||
| -c <class>                  default IN | -c <class>                  default IN | ||||||
| -p <port>                   default 53 (mdns default: 5353) (listener is random for DNS and 5353 for mDNS) | -p <port>                   default 53 (mdns default: 5353) (listener is random for DNS and 5353 for mDNS) | ||||||
| -q <query> (superfluous)    required (ex: coolaj86.com) | -q <query> (superfluous)    required (ex: daplie.com) | ||||||
| --nameserver <ns>           alias of @<nameserver> |  | ||||||
| --timeout <ms>              alias of +time=<seconds>, but in milliseconds |  | ||||||
| 
 | 
 | ||||||
| @<nameserver>               specify the nameserver to use for DNS resolution (defaults to system defaults) |  | ||||||
| +time=<seconds>             Sets the timeout for a query in seconds. | +time=<seconds>             Sets the timeout for a query in seconds. | ||||||
| +norecurse                  Set `rd` flag to 0. Do not request recursion |  | ||||||
| +aaonly                     Set `aa` flag to 1. |  | ||||||
| 
 |  | ||||||
| --norecase         					Disable dns0x20 security checking (mixed casing). See https://dyn.com/blog/use-of-bit-0x20-in-dns-labels/ |  | ||||||
| --recase           					Print the dns0x20 casing as-is rather than converting it back to lowercase. This is the default when explicitly using mixed case. |  | ||||||
| 
 |  | ||||||
| --debug                     verbose output |  | ||||||
| ``` | ``` | ||||||
| 
 |  | ||||||
| Security Concerns |  | ||||||
| ----------------- |  | ||||||
| 
 |  | ||||||
| The 16-bit `id` of the query must match that of the response. |  | ||||||
| 
 |  | ||||||
| Extra entropy is added by using `dns0x20`, the de facto standard for RanDOmCASiNg on the query which must be matched in the response. |  | ||||||
|  | |||||||
							
								
								
									
										502
									
								
								bin/dig.js
									
									
									
									
									
								
							
							
						
						
									
										502
									
								
								bin/dig.js
									
									
									
									
									
								
							| @ -1,11 +1,10 @@ | |||||||
| #!/usr/bin/env node
 | #!/usr/bin/env node
 | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| var dig = require('../dns-request'); | var dnsjs = require('dns-suite'); | ||||||
| var cli = require('cli'); | var cli = require('cli'); | ||||||
| var defaultNameservers = require('dns').getServers(); | var hexdump = require('../hexdump'); | ||||||
| var typeRe = /^type\d+$/i; | var crypto = require('crypto'); | ||||||
| 
 |  | ||||||
| cli.parse({ | cli.parse({ | ||||||
| //  'b': [ false, 'set source IP address (defaults to 0.0.0.0)', 'string' ]
 | //  'b': [ false, 'set source IP address (defaults to 0.0.0.0)', 'string' ]
 | ||||||
|   'class': [ 'c', 'class (defaults to IN)', 'string', 'IN' ] |   'class': [ 'c', 'class (defaults to IN)', 'string', 'IN' ] | ||||||
| @ -16,50 +15,243 @@ cli.parse({ | |||||||
| //, 'json': [ false, 'output results as json', 'string' ]
 | //, 'json': [ false, 'output results as json', 'string' ]
 | ||||||
| //, 'lint': [ false, 'attack (in the metaphorical sense) a nameserver with all sorts of queries to test for correct responses', 'string', false ]
 | //, 'lint': [ false, 'attack (in the metaphorical sense) a nameserver with all sorts of queries to test for correct responses', 'string', false ]
 | ||||||
| , 'mdns': [ false, "Alias for setting defaults to -p 5353 @224.0.0.251 -t PTR -q _services._dns-sd._udp.local and waiting for multiple responses", 'boolean', false ] | , 'mdns': [ false, "Alias for setting defaults to -p 5353 @224.0.0.251 -t PTR -q _services._dns-sd._udp.local and waiting for multiple responses", 'boolean', false ] | ||||||
| , 'timeout': [ false, "How long, in milliseconds, to wait for a response. Alias of +time=", 'int', false ] | , 'timeout': [ false, "Alias for setting defaults to -p 5353 @224.0.0.251 -t PTR -q _services._dns-sd._udp.local and waiting for multiple responses", 'boolean', false ] | ||||||
| , 'output': [ 'o', 'output prefix to use for writing query and response(s) to disk', 'file' ] | , 'output': [ 'o', 'output prefix to use for writing query and response(s) to disk', 'file' ] | ||||||
| , 'port': [ 'p', 'port (defaults to 53 for dns and 5353 for mdns)', 'int' ] | , 'port': [ 'p', 'port (defaults to 53 for dns and 5353 for mdns)', 'int' ] | ||||||
| , 'nameserver': [ false, 'the nameserver to use for DNS resolution (defaults to ' + defaultNameservers.join(',') + ')', 'string' ] |  | ||||||
| //, 'serve': [ 's', 'path to json file with array of responses to issue for given queries', 'string' ]
 | //, 'serve': [ 's', 'path to json file with array of responses to issue for given queries', 'string' ]
 | ||||||
| , 'type': [ 't', 'type (defaults to ANY for dns and PTR for mdns)', 'string' ] | , 'type': [ 't', 'type (defaults to ANY for dns and PTR for mdns)', 'string' ] | ||||||
| , 'query': [ 'q', 'a superfluous explicit option to set the query as a command line flag', 'string' ] | , 'query': [ 'q', 'a superfluous explicit option to set the query as a command line flag' ] | ||||||
| , 'norecase': [ false, 'Disable dns0x20 security checking (mixed casing). See https://dyn.com/blog/use-of-bit-0x20-in-dns-labels/' ] |  | ||||||
| , 'recase': [ false, "Print the dns0x20 casing as-is rather than converting it back to lowercase. This is the default when explicitly using mixed case." ] |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| var common = require('../common.js'); | var fs = require('fs'); | ||||||
|  | var dgram = require('dgram'); | ||||||
|  | var commonTypes = [ 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' ]; | ||||||
|  | var commonPrinters = { | ||||||
|  |   'ANY': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data || q.rdata || 'unknown record type'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | , 'A': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); | ||||||
|  |   } | ||||||
|  | , 'AAAA': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); | ||||||
|  |   } | ||||||
|  | , 'CNAME': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data + '.'); | ||||||
|  |   } | ||||||
|  | , 'MX': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.exchange + '.'); | ||||||
|  |   } | ||||||
|  | , 'NS': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | , 'PTR': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | /* | ||||||
|  | , 'SOA': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | */ | ||||||
|  | , 'SRV': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.weight + ' ' + q.port + ' ' + q.target); | ||||||
|  |   } | ||||||
|  | , 'TXT': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, '"' + q.data.join('" "') + '"'); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function writeQuery(opts, query, queryAb) { | ||||||
|  |   var path = require('path'); | ||||||
|  |   var binname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.query.bin'; | ||||||
|  |   var jsonname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.query.json'; | ||||||
|  |   var binpath = opts.output + '.' + binname; | ||||||
|  |   var jsonpath = opts.output + '.' + jsonname; | ||||||
|  |   var json = JSON.stringify(query, null, 2); | ||||||
|  |   if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { | ||||||
|  |     binpath = path.join(opts.output, binname); | ||||||
|  |     jsonpath = path.join(opts.output, jsonname); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fs.writeFile(binpath, Buffer.from(queryAb), null, function () { | ||||||
|  |     console.log('wrote ' + queryAb.byteLength + ' bytes to ' + binpath); | ||||||
|  |   }); | ||||||
|  |   fs.writeFile(jsonpath, json, null, function () { | ||||||
|  |     console.log('wrote ' + json.length + ' bytes to ' + jsonpath); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var count = 0; | ||||||
|  | function writeResponse(opts, query, nb, packet) { | ||||||
|  |   var path = require('path'); | ||||||
|  |   var binname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.' + count + '.bin'; | ||||||
|  |   var jsonname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.' + count + '.json'; | ||||||
|  |   var binpath = opts.output + '.' + binname; | ||||||
|  |   var jsonpath = opts.output + '.' + jsonname; | ||||||
|  |   var json = JSON.stringify(packet, null, 2); | ||||||
|  |   if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { | ||||||
|  |     binpath = path.join(opts.output, binname); | ||||||
|  |     jsonpath = path.join(opts.output, jsonname); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   count += 1; | ||||||
|  | 
 | ||||||
|  |   fs.writeFile(binpath, nb, null, function () { | ||||||
|  |     console.log('wrote ' + nb.byteLength + ' bytes to ' + binpath); | ||||||
|  |   }); | ||||||
|  |   fs.writeFile(jsonpath, json, null, function () { | ||||||
|  |     console.log('wrote ' + json.length + ' bytes to ' + jsonpath); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function request(query, opts) { | ||||||
|  |   var queryAb = dnsjs.DNSPacket.write(query); | ||||||
|  | 
 | ||||||
|  |   if (opts.debug) { | ||||||
|  |     console.log(''); | ||||||
|  |     console.log('DNS Question:'); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(query); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(hexdump(queryAb)); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(dnsjs.DNSPacket.parse(queryAb)); | ||||||
|  |     console.log(''); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var handlers = {}; | ||||||
|  |   var server = dgram.createSocket({ | ||||||
|  |     type: 'udp4' | ||||||
|  |   , reuseAddr: true | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   handlers.onError = function (err) { | ||||||
|  |     console.error("error:", err.stack); | ||||||
|  |     server.close(); | ||||||
|  |   }; | ||||||
|  |   handlers.onMessage = function (nb) { | ||||||
|  |     var packet = dnsjs.DNSPacket.parse(nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength)); | ||||||
|  | 
 | ||||||
|  |     if (packet.id !== query.id) { | ||||||
|  |       console.log('ignoring packet for ', packet.question[0].name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!opts.mdns) { | ||||||
|  |       server.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log('DNS Response:'); | ||||||
|  |       console.log(packet); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.log(''); | ||||||
|  |     console.log('; <<>> dig.js ' + 'v0.0.0' + ' <<>> ' + query.question[0].name); | ||||||
|  |     console.log(';; Got answer:'); | ||||||
|  |     console.log(';; ->>HEADER<<-'); | ||||||
|  |     console.log(JSON.stringify(packet.header)); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(';; QUESTION SECTION:'); | ||||||
|  |     packet.question.forEach(function (q) { | ||||||
|  |       console.log(';' + q.name + '.', ' ', q.className, q.typeName); | ||||||
|  |     }); | ||||||
|  |     function print(q) { | ||||||
|  |       var printer = commonPrinters[q.typeName] || commonPrinters.ANY; | ||||||
|  |       printer(q); | ||||||
|  |     } | ||||||
|  |     if (packet.answer.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; ANSWER SECTION:'); | ||||||
|  |       packet.answer.forEach(print); | ||||||
|  |     } | ||||||
|  |     if (packet.authority.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; AUTHORITY SECTION:'); | ||||||
|  |       packet.authority.forEach(print); | ||||||
|  |     } | ||||||
|  |     if (packet.additional.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; ADDITIONAL SECTION:'); | ||||||
|  |       packet.additional.forEach(print); | ||||||
|  |     } | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(';; MSG SIZE  rcvd: ' + nb.byteLength); | ||||||
|  |     console.log(''); | ||||||
|  | 
 | ||||||
|  |     if (opts.output) { | ||||||
|  |       console.log(''); | ||||||
|  |       writeQuery(opts, query, queryAb); | ||||||
|  |       writeResponse(opts, query, nb, packet); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   handlers.onListening = function () { | ||||||
|  |     /*jshint validthis:true*/ | ||||||
|  |     var server = this; | ||||||
|  |     var nameserver = opts.nameserver; | ||||||
|  |     var nameservers; | ||||||
|  |     var index; | ||||||
|  | 
 | ||||||
|  |     if (!nameserver) { | ||||||
|  |       nameservers = require('dns').getServers(); | ||||||
|  |       index = crypto.randomBytes(2).readUInt16BE(0) % nameservers.length; | ||||||
|  |       nameserver = nameservers[index]; | ||||||
|  |       if (opts.debug) { | ||||||
|  |         console.log(index, nameservers); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.mdns || '224.0.0.251' === opts.nameserver) { | ||||||
|  |       server.setBroadcast(true); | ||||||
|  |       server.addMembership(opts.nameserver); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log('Bound and Listening:'); | ||||||
|  |       console.log(server.address()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log("querying '" + nameserver + "':'" + opts.port + "'"); | ||||||
|  |     } | ||||||
|  |     server.send(Buffer.from(queryAb), opts.port, nameserver, function () { | ||||||
|  |       if (opts.debug) { | ||||||
|  |         console.log(''); | ||||||
|  |         console.log('request sent'); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   server.on('error', handlers.onError); | ||||||
|  |   server.on('message', handlers.onMessage); | ||||||
|  |   server.on('listening', handlers.onListening); | ||||||
|  | 
 | ||||||
|  |   // 0 dns request
 | ||||||
|  |   // 53 dns server
 | ||||||
|  |   // 5353 mdns
 | ||||||
|  |   if (opts.mdns) { | ||||||
|  |     server.bind(opts.port /*5353*/); | ||||||
|  |     setTimeout(function () { | ||||||
|  |       server.close(); | ||||||
|  |     }, opts.timeout || (5 * 1000)); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     server.bind(0); | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| cli.main(function (args, cli) { | cli.main(function (args, cli) { | ||||||
|   cli.implicitType = cli.type; |  | ||||||
|   cli.implicitQuery = cli.query; |  | ||||||
|   args.forEach(function (arg) { |   args.forEach(function (arg) { | ||||||
|     if (typeRe.test(arg) || -1 !== common.types.concat([ 'ANY' ]).indexOf(arg.toUpperCase())) { |     if (-1 !== commonTypes.concat([ 'ANY' ]).indexOf(arg.toUpperCase())) { | ||||||
|       if (cli.implicitType) { |       if (cli.type) { | ||||||
|         console.error("'type' was specified more than once"); |         console.error("'type' was specified more than once"); | ||||||
|         process.exit(1); |         process.exit(1); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|       cli.implicitType = cli.t = arg.toUpperCase(); |       cli.type = cli.t = arg.toUpperCase(); | ||||||
|       return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (arg === '+aaonly' || arg === '+aaflag') { |  | ||||||
|       if (cli.aaonly) { |  | ||||||
|         console.error("'+aaonly' was specified more than once"); |  | ||||||
|         process.exit(1); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|       cli.aaonly = true; |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (arg === '+norecurse') { |  | ||||||
|       if (cli.norecurse) { |  | ||||||
|         console.error("'+norecurse' was specified more than once"); |  | ||||||
|         process.exit(1); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|       cli.norecurse = true; |  | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -83,41 +275,15 @@ cli.main(function (args, cli) { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if ('string' === typeof cli.implicitQuery) { |     if (cli.query) { | ||||||
|       console.error("'query' was specified more than once or unrecognized flag: " + cli.implicitQuery + ", " + arg); |       console.error("'query' was specified more than once"); | ||||||
|       process.exit(1); |       process.exit(1); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     cli.implicitQuery = cli.q = arg; |     cli.query = cli.q = arg; | ||||||
| 
 | 
 | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|   // it can happen that a TLD is created with the name of a common type
 |  | ||||||
|   if (!cli.type && cli.implicitType && !cli.implicitQuery) { |  | ||||||
|     cli.implicitQuery = cli.implicitType; |  | ||||||
|     cli.implicitType = null; |  | ||||||
|   } |  | ||||||
|   if ('string' === typeof cli.implicitQuery) { |  | ||||||
|     cli.query = cli.implicitQuery; |  | ||||||
|   } |  | ||||||
|   if (cli.implicitType) { |  | ||||||
|     cli.type = cli.implicitType; |  | ||||||
|   } |  | ||||||
|   if ('string' !== typeof cli.query) { |  | ||||||
|     console.error(''); |  | ||||||
|     console.error('Usage:'); |  | ||||||
|     console.error('dig.js [@server] [TYPE] [domain]'); |  | ||||||
|     console.error(''); |  | ||||||
|     console.error('Example:'); |  | ||||||
|     console.error('dig.js daplie.com'); |  | ||||||
|     console.error(''); |  | ||||||
|     process.exit(1); |  | ||||||
|   } |  | ||||||
|   if (cli.query !== cli.query.toLowerCase()) { |  | ||||||
|     cli.norecase = true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (cli.mdns) { |   if (cli.mdns) { | ||||||
|     if (!cli.type) { |     if (!cli.type) { | ||||||
|       cli.type = cli.t = 'PTR'; |       cli.type = cli.t = 'PTR'; | ||||||
| @ -128,222 +294,52 @@ cli.main(function (args, cli) { | |||||||
|     if (!cli.nameserver) { |     if (!cli.nameserver) { | ||||||
|       cli.nameserver = '224.0.0.251'; |       cli.nameserver = '224.0.0.251'; | ||||||
|     } |     } | ||||||
|     if ('string' !== typeof cli.query) { |     if (!cli.query) { | ||||||
|       cli.query = '_services._dns-sd._udp.local'; |       cli.query = '_services._dns-sd._udp.local'; | ||||||
|     } |     } | ||||||
|     if (!cli.timeout) { |     if (!cli.timeout) { | ||||||
|       cli.timeout = 3000; |       cli.timeout = 3000; | ||||||
|     } |     } | ||||||
|   } else { |  | ||||||
|     if (!cli.timeout) { |  | ||||||
|       cli.timeout = 5000; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (!cli.norecase) { |  | ||||||
|     cli.casedQuery = cli.query.split('').map(function (ch) { |  | ||||||
|       // dns0x20 takes advantage of the fact that the binary operation for toUpperCase is
 |  | ||||||
|       // ch = ch | 0x20;
 |  | ||||||
|       return Math.round(Math.random()) % 2 ? ch : ch.toUpperCase(); |  | ||||||
|     }).join(''); |  | ||||||
|   } else { |  | ||||||
|     cli.casedQuery = cli.query; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (!cli.type) { |   if (!cli.type) { | ||||||
|     cli.type = cli.t = 'ANY'; |     cli.type = cli.t = 'ANY'; | ||||||
|   } |   } | ||||||
|   if (typeRe.test(cli.type)) { |  | ||||||
|     cli.rawType = parseInt(cli.type.replace('type', ''), 10); |  | ||||||
|   } |  | ||||||
|   if (!cli.port) { |   if (!cli.port) { | ||||||
|     cli.port = cli.p = 53; |     cli.port = cli.p = 53; | ||||||
|   } |   } | ||||||
|   if (!cli.class) { |   if (!cli.class) { | ||||||
|     cli.class = cli.c = 'IN'; |     cli.class = cli.c = 'IN'; | ||||||
|   } |   } | ||||||
|  |   if (!cli.query) { | ||||||
|  |     console.error(''); | ||||||
|  |     console.error('Usage:'); | ||||||
|  |     console.error('dig.js [@server] [TYPE] [domain]'); | ||||||
|  |     console.error(''); | ||||||
|  |     console.error('Example:'); | ||||||
|  |     console.error('dig.js daplie.com'); | ||||||
|  |     console.error(''); | ||||||
|  |     process.exit(1); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   var query = { |   var query = { | ||||||
|     header: { |     header: { | ||||||
|       id: require('crypto').randomBytes(2).readUInt16BE(0) |       id: require('crypto').randomBytes(2).readUInt16BE(0) | ||||||
|     , qr: 0 |     , qr: 0 | ||||||
|     , opcode: 0 |     , opcode: 0 | ||||||
|     , aa: cli.aaonly ? 1 : 0  // NA
 |     , aa: 0     // NA
 | ||||||
|     , tc: 0                   // NA
 |     , tc: 0     // NA
 | ||||||
|     , rd: cli.norecurse ? 0 : 1 |     , rd: 1 | ||||||
|     , ra: 0                   // NA
 |     , ra: 0     // NA
 | ||||||
|     , rcode: 0                // NA
 |     , rcode: 0  // NA
 | ||||||
|     } |     } | ||||||
|   , question: [ |   , question: [ | ||||||
|       { name: cli.casedQuery |       { name: cli.query | ||||||
|       , type: cli.rawType |       , typeName: cli.type | ||||||
|       , typeName: cli.rawType ? undefined : cli.type |  | ||||||
|       , className: cli.class |       , className: cli.class | ||||||
|       } |       } | ||||||
|     ] |     ] | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   var dnsjs = require('dns-suite'); |   request(query, cli); | ||||||
|   var queryAb = dnsjs.DNSPacket.write(query); |  | ||||||
|   var hexdump = require('hexdump.js').hexdump; |  | ||||||
| 
 |  | ||||||
|   if (cli.debug) { |  | ||||||
|     console.log(''); |  | ||||||
|     console.log('DNS Question:'); |  | ||||||
|     console.log(''); |  | ||||||
|     console.log(query); |  | ||||||
|     console.log(''); |  | ||||||
|     console.log(hexdump(queryAb)); |  | ||||||
|     console.log(''); |  | ||||||
|     console.log(dnsjs.DNSPacket.parse(queryAb)); |  | ||||||
|     console.log(''); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   cli.onError = function (err) { |  | ||||||
|     console.error("error:", err.stack); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   cli.onMessage = function (nb) { |  | ||||||
|     var packet = dnsjs.DNSPacket.parse(nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength)); |  | ||||||
|     var fail0x20; |  | ||||||
| 
 |  | ||||||
|     if (packet.id !== query.id) { |  | ||||||
|       console.error('[SECURITY] ignoring packet for \'' + packet.question[0].name + '\' due to mismatched id'); |  | ||||||
|       console.error(packet); |  | ||||||
|       return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (cli.debug) { |  | ||||||
|       console.log(''); |  | ||||||
|       console.log('DNS Response:'); |  | ||||||
|       console.log(packet); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     packet.question.forEach(function (q) { |  | ||||||
|       // if (-1 === q.name.lastIndexOf(cli.casedQuery))
 |  | ||||||
|       if (q.name !== cli.casedQuery) { |  | ||||||
|         fail0x20 = q.name; |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     if (!cli.norecase && !cli.recase) { |  | ||||||
|       [ 'question', 'answer', 'authority', 'additional' ].forEach(function (group) { |  | ||||||
|         (packet[group]||[]).forEach(function (a) { |  | ||||||
|           var an = a.name; |  | ||||||
|           var i = cli.query.toLowerCase().lastIndexOf(a.name.toLowerCase());  // answer is something like ExAMPle.cOM and query was wWw.ExAMPle.cOM
 |  | ||||||
|           var j = a.name.toLowerCase().lastIndexOf(cli.query.toLowerCase());  // answer is something like www.ExAMPle.cOM and query was ExAMPle.cOM
 |  | ||||||
| 
 |  | ||||||
|           // it's important to note that these should only relpace changes in casing that we expected
 |  | ||||||
|           // any abnormalities should be left intact to go "huh?" about
 |  | ||||||
|           // TODO detect abnormalities?
 |  | ||||||
|           if (-1 !== i) { |  | ||||||
|             // "EXamPLE.cOm".replace("wWw.EXamPLE.cOm".substr(4), "www.example.com".substr(4))
 |  | ||||||
|             a.name = a.name.replace(cli.casedQuery.substr(i), cli.query.substr(i)); |  | ||||||
|           } else if (-1 !== j) { |  | ||||||
|             // "www.example.com".replace("EXamPLE.cOm", "example.com")
 |  | ||||||
|             a.name = a.name.substr(0, j) + a.name.substr(j).replace(cli.casedQuery, cli.query); |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           // NOTE: right now this assumes that anything matching the query matches all the way to the end
 |  | ||||||
|           // it does not handle the case of a record for example.com.uk being returned in response to a query for www.example.com correctly
 |  | ||||||
|           // (but I don't think it should need to)
 |  | ||||||
|           if (a.name.length !== an.length) { |  | ||||||
|             console.error("[ERROR] question / answer mismatch: '" + an + "' != '" + a.length + "'"); |  | ||||||
|             console.error(a); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (fail0x20) { |  | ||||||
|       console.warn(""); |  | ||||||
|       console.warn(";; Warning: DNS 0x20 security not implemented (or packet spoofed). Queried '" + cli.casedQuery + "' but got response for '" + fail0x20 + "'."); |  | ||||||
|       console.warn(""); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     console.log(';; Got answer:'); |  | ||||||
|     dig.logQuestion(packet); |  | ||||||
| 
 |  | ||||||
|     function print(q) { |  | ||||||
|       var printer = common.printers[q.typeName] || common.printers.ANY; |  | ||||||
|       printer(q); |  | ||||||
|     } |  | ||||||
|     if (packet.answer.length) { |  | ||||||
|       console.log(''); |  | ||||||
|       console.log(';; ANSWER SECTION:'); |  | ||||||
|       packet.answer.forEach(print); |  | ||||||
|     } |  | ||||||
|     if (packet.authority.length) { |  | ||||||
|       console.log(''); |  | ||||||
|       console.log(';; AUTHORITY SECTION:'); |  | ||||||
|       packet.authority.forEach(print); |  | ||||||
|     } |  | ||||||
|     if (packet.additional.length) { |  | ||||||
|       console.log(''); |  | ||||||
|       console.log(';; ADDITIONAL SECTION:'); |  | ||||||
|       packet.additional.forEach(print); |  | ||||||
|     } |  | ||||||
|     console.log(''); |  | ||||||
|     console.log(';; Query time: ' + (Date.now() - cli._ts) + ' msec'); |  | ||||||
|     // ;; SERVER: 8.8.8.8#53(8.8.8.8)
 |  | ||||||
|     console.log(';; SERVER: ' + cli._nameserver + '#' + cli.port + '(' + cli._nameserver + ')'); |  | ||||||
|     // TODO ;; WHEN: Fri Sep 15 18:25:53 2017
 |  | ||||||
|     console.log(';; WHEN: ' + new Date().toString()); |  | ||||||
|     console.log(';; MSG SIZE  rcvd: ' + nb.byteLength); |  | ||||||
|     console.log(''); |  | ||||||
| 
 |  | ||||||
|     if (cli.output) { |  | ||||||
|       console.log(''); |  | ||||||
|       common.writeQuery(cli, query, queryAb); |  | ||||||
|       common.writeResponse(cli, query, nb, packet); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|   cli.onListening = function () { |  | ||||||
|     /*jshint validthis:true*/ |  | ||||||
|     var server = this; |  | ||||||
| 
 |  | ||||||
|     if (cli.debug) { |  | ||||||
|       console.log(''); |  | ||||||
|       console.log('Bound and Listening:', server.type); |  | ||||||
|       console.log(server.address()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // technicially this should be a seperate event
 |  | ||||||
|     if (cli.debug) { |  | ||||||
|       console.log("querying '" + server.nameserver + "':'" + cli.port + "'"); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   console.log(''); |  | ||||||
|   if (!cli.nocmd) { |  | ||||||
|     console.log('; <<>> dig.js ' + 'v0.0.0' + ' <<>> ' + process.argv.slice(2).join(' ').replace(cli.query, cli.casedQuery)); |  | ||||||
|     console.log(';; global options: +cmd'); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   var opts = { |  | ||||||
|     onError: cli.onError |  | ||||||
|   , onMessage: cli.onMessage |  | ||||||
|   , onListening: cli.onListening |  | ||||||
|   , onSent: function (res) { |  | ||||||
|       cli._nameserver = res.nameserver; |  | ||||||
|       cli._ts = Date.now(); |  | ||||||
|       if (cli.debug) { |  | ||||||
|         console.log(''); |  | ||||||
|         console.log('request sent to', res.nameserver); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   , onTimeout: function (res) { |  | ||||||
|       console.log(";; connection timed out; no servers could be reached"); |  | ||||||
|       console.log(";; [timed out after " + res.timeout + "ms and 1 tries]"); |  | ||||||
|     } |  | ||||||
|   , onClose: function () { |  | ||||||
|       console.log(''); |  | ||||||
|     } |  | ||||||
|   , mdns: cli.mdns |  | ||||||
|   , nameserver: cli.nameserver |  | ||||||
|   , port: cli.port |  | ||||||
|   , timeout: cli.timeout |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   dig.resolve(queryAb, opts); |  | ||||||
| }); | }); | ||||||
|  | |||||||
							
								
								
									
										331
									
								
								bin/digd.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								bin/digd.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,331 @@ | |||||||
|  | #!/usr/bin/env node
 | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | var dnsjs = require('dns-suite'); | ||||||
|  | var cli = require('cli'); | ||||||
|  | var hexdump = require('../hexdump'); | ||||||
|  | var crypto = require('crypto'); | ||||||
|  | cli.parse({ | ||||||
|  | //  'b': [ false, 'set source IP address (defaults to 0.0.0.0)', 'string' ]
 | ||||||
|  |   'debug': [ false, 'more verbose output', 'boolean', false ] | ||||||
|  | //, 'insecure': [ false, 'turn off RaNDOm cAPS required for securing queries']
 | ||||||
|  | //, 'ipv4': [ '4', 'use ipv4 exclusively (defaults to false)', 'boolean', false ]
 | ||||||
|  | //, 'ipv6': [ '6', 'use ipv6 exclusively (defaults to false)', 'boolean', false ]
 | ||||||
|  | //, 'json': [ false, 'output results as json', 'string' ]
 | ||||||
|  | //, 'lint': [ false, 'attack (in the metaphorical sense) a nameserver with all sorts of queries to test for correct responses', 'string', false ]
 | ||||||
|  | , 'mdns': [ false, "Alias for setting defaults to -p 5353 @224.0.0.251 -t PTR -q _services._dns-sd._udp.local and waiting for multiple responses", 'boolean', false ] | ||||||
|  | , 'output': [ 'o', 'output prefix to use for writing query and response(s) to disk', 'file' ] | ||||||
|  | , 'port': [ 'p', 'port (defaults to 53 for dns and 5353 for mdns)', 'int' ] | ||||||
|  | //, 'serve': [ 's', 'path to json file with array of responses to issue for given queries', 'string' ]
 | ||||||
|  | , 'type': [ 't', 'type (defaults to ANY for dns and PTR for mdns)', 'string' ] | ||||||
|  | , 'query': [ 'q', 'a superfluous explicit option to set the query as a command line flag' ] | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | var fs = require('fs'); | ||||||
|  | var dgram = require('dgram'); | ||||||
|  | var commonTypes = [ 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' ]; | ||||||
|  | var commonPrinters = { | ||||||
|  |   'ANY': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data || q.rdata || 'unknown record type'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | , 'A': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); | ||||||
|  |   } | ||||||
|  | , 'AAAA': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); | ||||||
|  |   } | ||||||
|  | , 'CNAME': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data + '.'); | ||||||
|  |   } | ||||||
|  | , 'MX': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.exchange + '.'); | ||||||
|  |   } | ||||||
|  | , 'NS': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | , 'PTR': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | /* | ||||||
|  | , 'SOA': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); | ||||||
|  |   } | ||||||
|  | */ | ||||||
|  | , 'SRV': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.weight + ' ' + q.port + ' ' + q.target); | ||||||
|  |   } | ||||||
|  | , 'TXT': function (q) { | ||||||
|  |     console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, '"' + q.data.join('" "') + '"'); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function writeQuery(opts, query, queryAb) { | ||||||
|  |   var path = require('path'); | ||||||
|  |   var binname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.query.bin'; | ||||||
|  |   var jsonname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.query.json'; | ||||||
|  |   var binpath = opts.output + '.' + binname; | ||||||
|  |   var jsonpath = opts.output + '.' + jsonname; | ||||||
|  |   var json = JSON.stringify(query, null, 2); | ||||||
|  |   if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { | ||||||
|  |     binpath = path.join(opts.output, binname); | ||||||
|  |     jsonpath = path.join(opts.output, jsonname); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fs.writeFile(binpath, Buffer.from(queryAb), null, function () { | ||||||
|  |     console.log('wrote ' + queryAb.byteLength + ' bytes to ' + binpath); | ||||||
|  |   }); | ||||||
|  |   fs.writeFile(jsonpath, json, null, function () { | ||||||
|  |     console.log('wrote ' + json.length + ' bytes to ' + jsonpath); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var count = 0; | ||||||
|  | function writeResponse(opts, query, nb, packet) { | ||||||
|  |   var path = require('path'); | ||||||
|  |   var binname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.' + count + '.bin'; | ||||||
|  |   var jsonname = query.question[0].name + '.' + query.question[0].typeName.toLowerCase() + '.' + count + '.json'; | ||||||
|  |   var binpath = opts.output + '.' + binname; | ||||||
|  |   var jsonpath = opts.output + '.' + jsonname; | ||||||
|  |   var json = JSON.stringify(packet, null, 2); | ||||||
|  |   if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { | ||||||
|  |     binpath = path.join(opts.output, binname); | ||||||
|  |     jsonpath = path.join(opts.output, jsonname); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   count += 1; | ||||||
|  | 
 | ||||||
|  |   fs.writeFile(binpath, nb, null, function () { | ||||||
|  |     console.log('wrote ' + nb.byteLength + ' bytes to ' + binpath); | ||||||
|  |   }); | ||||||
|  |   fs.writeFile(jsonpath, json, null, function () { | ||||||
|  |     console.log('wrote ' + json.length + ' bytes to ' + jsonpath); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function request(query, opts) { | ||||||
|  |   var queryAb = dnsjs.DNSPacket.write(query); | ||||||
|  | 
 | ||||||
|  |   if (opts.debug) { | ||||||
|  |     console.log(''); | ||||||
|  |     console.log('DNS Question:'); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(query); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(hexdump(queryAb)); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(dnsjs.DNSPacket.parse(queryAb)); | ||||||
|  |     console.log(''); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var handlers = {}; | ||||||
|  |   var server = dgram.createSocket({ | ||||||
|  |     type: 'udp4' | ||||||
|  |   , reuseAddr: true | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   handlers.onError = function (err) { | ||||||
|  |     console.error("error:", err.stack); | ||||||
|  |     server.close(); | ||||||
|  |   }; | ||||||
|  |   handlers.onMessage = function (nb) { | ||||||
|  |     console.log("YOYOYO GOT MESSAGE"); | ||||||
|  |     var packet = dnsjs.DNSPacket.parse(nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength)); | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log('DNS Request:'); | ||||||
|  |       console.log(packet); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.log(''); | ||||||
|  |     console.log('; <<>> dig.js ' + 'v0.0.0' + ' <<>> ' + query.question[0].name); | ||||||
|  |     console.log(';; Got answer:'); | ||||||
|  |     console.log(';; ->>HEADER<<-'); | ||||||
|  |     console.log(JSON.stringify(packet.header)); | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(';; QUESTION SECTION:'); | ||||||
|  |     packet.question.forEach(function (q) { | ||||||
|  |       console.log(';' + q.name + '.', ' ', q.className, q.typeName); | ||||||
|  |     }); | ||||||
|  |     /* | ||||||
|  |     function print(q) { | ||||||
|  |       var printer = commonPrinters[q.typeName] || commonPrinters.ANY; | ||||||
|  |       printer(q); | ||||||
|  |     } | ||||||
|  |     if (packet.answer.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; ANSWER SECTION:'); | ||||||
|  |       packet.answer.forEach(print); | ||||||
|  |     } | ||||||
|  |     if (packet.authority.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; AUTHORITY SECTION:'); | ||||||
|  |       packet.authority.forEach(print); | ||||||
|  |     } | ||||||
|  |     if (packet.additional.length) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log(';; ADDITIONAL SECTION:'); | ||||||
|  |       packet.additional.forEach(print); | ||||||
|  |     } | ||||||
|  |     console.log(''); | ||||||
|  |     console.log(';; MSG SIZE  rcvd: ' + nb.byteLength); | ||||||
|  |     console.log(''); | ||||||
|  |     */ | ||||||
|  | 
 | ||||||
|  |     if (opts.output) { | ||||||
|  |       console.log(''); | ||||||
|  |       writeQuery(opts, query, queryAb); | ||||||
|  |       //writeResponse(opts, query, nb, packet);
 | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   handlers.onListening = function () { | ||||||
|  |     console.log("YOYOYO ON LISTENING"); | ||||||
|  |     /*jshint validthis:true*/ | ||||||
|  |     var server = this; | ||||||
|  |     var nameserver = opts.nameserver; | ||||||
|  |     var nameservers; | ||||||
|  |     var index; | ||||||
|  | 
 | ||||||
|  |     if (!nameserver) { | ||||||
|  |       nameservers = require('dns').getServers(); | ||||||
|  |       index = crypto.randomBytes(2).readUInt16BE(0) % nameservers.length; | ||||||
|  |       nameserver = nameservers[index]; | ||||||
|  |       if (opts.debug) { | ||||||
|  |         console.log(index, nameservers); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.mdns || '224.0.0.251' === opts.nameserver) { | ||||||
|  |       server.setBroadcast(true); | ||||||
|  |       server.addMembership(opts.nameserver); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log(''); | ||||||
|  |       console.log('Bound and Listening:'); | ||||||
|  |       console.log(server.address()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.debug) { | ||||||
|  |       console.log('querying ' + nameserver + ':' + opts.port); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   server.on('error', handlers.onError); | ||||||
|  |   server.on('message', handlers.onMessage); | ||||||
|  |   server.on('listening', handlers.onListening); | ||||||
|  | 
 | ||||||
|  |   // 53 dns server
 | ||||||
|  |   // 5353 mdns
 | ||||||
|  |   console.log("YOYOYO BINDING ON", opts.port); | ||||||
|  |   server.bind(opts.port); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cli.main(function (args, cli) { | ||||||
|  |   args.forEach(function (arg) { | ||||||
|  |     if (-1 !== commonTypes.indexOf(arg.toUpperCase())) { | ||||||
|  |       if (cli.type) { | ||||||
|  |         console.error("'type' was specified more than once"); | ||||||
|  |         process.exit(1); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       cli.type = cli.t = arg.toUpperCase(); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (/^\+time=/.test(arg)) { | ||||||
|  |       if (cli.timeout) { | ||||||
|  |         console.error("'+time=' was specified more than once"); | ||||||
|  |         process.exit(1); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       cli.timeout = Math.round(parseInt(arg.replace(/\+time=/, ''), 10) * 1000); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (/^@/.test(arg)) { | ||||||
|  |       if (cli.nameserver) { | ||||||
|  |         console.error("'@server' was specified more than once"); | ||||||
|  |         process.exit(1); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       cli.nameserver = cli.n = arg.substr(1); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (cli.query) { | ||||||
|  |       console.error("'query' was specified more than once"); | ||||||
|  |       process.exit(1); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     cli.query = cli.q = arg; | ||||||
|  | 
 | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   if (cli.mdns) { | ||||||
|  |     if (!cli.type) { | ||||||
|  |       cli.type = cli.t = 'PTR'; | ||||||
|  |     } | ||||||
|  |     if (!cli.port) { | ||||||
|  |       cli.port = cli.p = 5353; | ||||||
|  |     } | ||||||
|  |     if (!cli.nameserver) { | ||||||
|  |       cli.nameserver = '224.0.0.251'; | ||||||
|  |     } | ||||||
|  |     if (!cli.query) { | ||||||
|  |       cli.query = '_services._dns-sd._udp.local'; | ||||||
|  |     } | ||||||
|  |     if (!cli.timeout) { | ||||||
|  |       cli.timeout = 3000; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!cli.type) { | ||||||
|  |     cli.type = cli.t = 'A'; | ||||||
|  |   } | ||||||
|  |   if (!cli.port) { | ||||||
|  |     cli.port = cli.p = 53; | ||||||
|  |   } | ||||||
|  |   if (!cli.class) { | ||||||
|  |     cli.class = cli.c = 'IN'; | ||||||
|  |   } | ||||||
|  |   if (!cli.query) { | ||||||
|  |     cli.query = 'example.com'; | ||||||
|  |     /* | ||||||
|  |     console.error(''); | ||||||
|  |     console.error('Usage:'); | ||||||
|  |     console.error('digd.js [@server] [TYPE] [domain]'); | ||||||
|  |     console.error(''); | ||||||
|  |     console.error('Example:'); | ||||||
|  |     console.error('digd.js daplie.com'); | ||||||
|  |     console.error(''); | ||||||
|  |     process.exit(1); | ||||||
|  |     */ | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var query = { | ||||||
|  |     header: { | ||||||
|  |       id: crypto.randomBytes(2).readUInt16BE(0) | ||||||
|  |     , qr: 0 | ||||||
|  |     , opcode: 0 | ||||||
|  |     , aa: 0     // NA
 | ||||||
|  |     , tc: 0     // NA
 | ||||||
|  |     , rd: 1 | ||||||
|  |     , ra: 0     // NA
 | ||||||
|  |     , rcode: 0  // NA
 | ||||||
|  |     } | ||||||
|  |   , question: [ | ||||||
|  |       { name: cli.query | ||||||
|  |       , typeName: cli.type | ||||||
|  |       , className: cli.class | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   if (!cli.daemon) { | ||||||
|  |     request(query, cli); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | }); | ||||||
							
								
								
									
										90
									
								
								common.js
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								common.js
									
									
									
									
									
								
							| @ -1,90 +0,0 @@ | |||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| var fs = require('fs'); |  | ||||||
| 
 |  | ||||||
| module.exports = { |  | ||||||
|   types: [ 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' ] |  | ||||||
| , printers: { |  | ||||||
|     'ANY': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, (q.className || q.class), (q.typeName || ('type' + q.type)), q.data || q.rdata || 'unknown record type'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   , 'A': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); |  | ||||||
|     } |  | ||||||
|   , 'AAAA': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.address); |  | ||||||
|     } |  | ||||||
|   , 'CNAME': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data + '.'); |  | ||||||
|     } |  | ||||||
|   , 'MX': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.exchange + '.'); |  | ||||||
|     } |  | ||||||
|   , 'NS': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); |  | ||||||
|     } |  | ||||||
|   , 'PTR': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.data); |  | ||||||
|     } |  | ||||||
|   , 'SOA': function (q) { |  | ||||||
|       // no ';' in authority section?
 |  | ||||||
|       console.log('' + q.name + '.', q.ttl, q.className, q.typeName, q.name_server, q.email_addr, q.sn, q.ref, q.ret, q.ex, q.nx); |  | ||||||
|     } |  | ||||||
|   , 'SRV': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.priority + ' ' + q.weight + ' ' + q.port + ' ' + q.target); |  | ||||||
|     } |  | ||||||
|   , 'TXT': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, '"' + q.data.join('" "') + '"'); |  | ||||||
|     } |  | ||||||
|   , 'CAA': function (q) { |  | ||||||
|       console.log(';' + q.name + '.', q.ttl, q.className, q.typeName, q.flag + ' ' + q.tag + ' "' + q.value + '"'); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| , writeQuery: function (opts, query, queryAb) { |  | ||||||
|     var path = require('path'); |  | ||||||
|     var basename = query.question[0].name + '.' |  | ||||||
|       + (query.question[0].typeName||query.question[0].type.toString()).toLowerCase(); |  | ||||||
|     var binname =  basename + '.query.bin'; |  | ||||||
|     var jsonname = basename + '.query.json'; |  | ||||||
|     var binpath = opts.output + '.' + binname; |  | ||||||
|     var jsonpath = opts.output + '.' + jsonname; |  | ||||||
|     var json = JSON.stringify(query, null, 2); |  | ||||||
|     if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { |  | ||||||
|       binpath = path.join(opts.output, binname); |  | ||||||
|       jsonpath = path.join(opts.output, jsonname); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fs.writeFile(binpath, Buffer.from(queryAb), null, function () { |  | ||||||
|       console.log('wrote ' + queryAb.byteLength + ' bytes to ' + binpath); |  | ||||||
|     }); |  | ||||||
|     fs.writeFile(jsonpath, json, null, function () { |  | ||||||
|       console.log('wrote ' + json.length + ' bytes to ' + jsonpath); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| , writeResponse: function (opts, query, nb, packet) { |  | ||||||
|     var me = this; |  | ||||||
|     me._count = me._count || 0; |  | ||||||
|     var path = require('path'); |  | ||||||
|     var basename = query.question[0].name + '.' |  | ||||||
|       + (query.question[0].typeName||query.question[0].type.toString()).toLowerCase(); |  | ||||||
|     var binname = basename + '.' + me._count + '.bin'; |  | ||||||
|     var jsonname = basename + '.' + me._count + '.json'; |  | ||||||
|     var binpath = opts.output + '.' + binname; |  | ||||||
|     var jsonpath = opts.output + '.' + jsonname; |  | ||||||
|     var json = JSON.stringify(packet, null, 2); |  | ||||||
|     if (-1 !== ['.', '/', '\\' ].indexOf(opts.output[opts.output.length -1])) { |  | ||||||
|       binpath = path.join(opts.output, binname); |  | ||||||
|       jsonpath = path.join(opts.output, jsonname); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     me._count += 1; |  | ||||||
| 
 |  | ||||||
|     fs.writeFile(binpath, nb, null, function () { |  | ||||||
|       console.log('wrote ' + nb.byteLength + ' bytes to ' + binpath); |  | ||||||
|     }); |  | ||||||
|     fs.writeFile(jsonpath, json, null, function () { |  | ||||||
|       console.log('wrote ' + json.length + ' bytes to ' + jsonpath); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
							
								
								
									
										154
									
								
								dns-request.js
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								dns-request.js
									
									
									
									
									
								
							| @ -1,154 +0,0 @@ | |||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| var dnsjs = require('dns-suite'); |  | ||||||
| var crypto = require('crypto'); |  | ||||||
| var dgram = require('dgram'); |  | ||||||
| 
 |  | ||||||
| var RCODES = { |  | ||||||
|   0: 'NOERROR' |  | ||||||
| , 3: 'NXDOMAIN' |  | ||||||
| , 5: 'REFUSED' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| function logQuestion(packet) { |  | ||||||
|   var flags = ""; |  | ||||||
| 
 |  | ||||||
|   // TODO opcode 0 QUERY rcode 0 NOERROR
 |  | ||||||
|   console.info(';; ->>HEADER<<- [opcode: ' + packet.header.opcode + ', status: ' + (RCODES[packet.header.rcode] || packet.header.rcode) + '], id: ' + packet.header.id); |  | ||||||
|   if (packet.header.tc) { console.info("Truncated [tc] (we don't know the normal way to print a tc packet... you should record this with -o tc-packet.dig and send it to us)"); } |  | ||||||
|   flags += ";; flags:"; |  | ||||||
|   if (packet.header.qr) { flags += " qr"; } |  | ||||||
|   if (packet.header.aa) { flags += " aa"; } |  | ||||||
|   if (packet.header.rd) { flags += " rd"; } |  | ||||||
|   if (packet.header.ra) { flags += " ra"; } |  | ||||||
|   flags += "; QUERY: " + packet.question.length + ", ANSWER: " + packet.answer.length + ", AUTHORITY: " + packet.authority.length + ", ADDITIONAL: " + packet.additional.length; |  | ||||||
|   console.info(flags); |  | ||||||
|   if (packet.header.res1) { console.info("[res1] (we don't know how to print a packet with res1 yet)"); } |  | ||||||
|   if (packet.header.res2) { console.info("[res2] (we don't know how to print a packet with res2 yet)"); } |  | ||||||
|   if (packet.header.res3) { console.info("[res3] (we don't know how to print a packet with res2 yet)"); } |  | ||||||
|   // {"id":32736,"qr":1,"opcode":0,"aa":0,"tc":0,"rd":1,"ra":0,"res1":0,"res2":0,"res3":0,"rcode":5}
 |  | ||||||
|   //console.log(JSON.stringify(packet.header));
 |  | ||||||
|   console.info(''); |  | ||||||
|   console.info(';; QUESTION SECTION:'); |  | ||||||
|   packet.question.forEach(function (q) { |  | ||||||
|     console.info(';' + q.name + '.', ' ', q.className, q.typeName || ('type' + q.type)); |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function resolve(queryAb, opts) { |  | ||||||
|   var handlers = {}; |  | ||||||
|   var nameservers; |  | ||||||
|   var nameserver = opts.nameserver; |  | ||||||
|   var index; |  | ||||||
|   var udpType; |  | ||||||
|   var receivedMessage; |  | ||||||
|   if (!nameserver) { |  | ||||||
|     nameservers = require('dns').getServers(); |  | ||||||
|     index = crypto.randomBytes(2).readUInt16BE(0) % nameservers.length; |  | ||||||
|     nameserver = nameservers[index]; |  | ||||||
|   } |  | ||||||
|   udpType = /:/.test(nameserver) ? 'udp6' : 'udp4'; |  | ||||||
|   var server = dgram.createSocket({ |  | ||||||
|     type: udpType |  | ||||||
|   , reuseAddr: true |  | ||||||
|   }); |  | ||||||
|   server.nameserver = nameserver; |  | ||||||
| 
 |  | ||||||
|   handlers.onError = function (err) { |  | ||||||
|     if (opts.onError) { opts.onError(err); } else { throw err; } |  | ||||||
|     server.close(); |  | ||||||
|   }; |  | ||||||
|   handlers.onMessage = function (bin) { |  | ||||||
|     receivedMessage = true; |  | ||||||
|     if (!opts.mdns) { |  | ||||||
|       clearTimeout(server._timeoutToken); |  | ||||||
|       server.close(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (opts.onMessage) { opts.onMessage(bin); } |  | ||||||
|   }; |  | ||||||
|   handlers.onListening = function () { |  | ||||||
|     /*jshint validthis:true*/ |  | ||||||
|     var server = this; |  | ||||||
| 
 |  | ||||||
|     if (opts.mdns || '224.0.0.251' === server.nameserver) { |  | ||||||
|       server.setBroadcast(true); |  | ||||||
|       server.addMembership(server.nameserver || '224.0.0.251'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (opts.onListening) { opts.onListening.apply(server); } |  | ||||||
| 
 |  | ||||||
|     server.send(Buffer.from(queryAb), opts.port, server.nameserver, function () { |  | ||||||
|       if (opts.onSent) { opts.onSent({ port: opts.port, nameserver: server.nameserver }); } |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
|   handlers.onClose = function () { |  | ||||||
|     if (opts.onClose) { opts.onClose(); } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   server.on('error', handlers.onError); |  | ||||||
|   server.on('message', handlers.onMessage); |  | ||||||
|   server.on('listening', handlers.onListening); |  | ||||||
|   server.on('close', handlers.onClose); |  | ||||||
| 
 |  | ||||||
|   // 0 dns request
 |  | ||||||
|   // 53 dns server
 |  | ||||||
|   // 5353 mdns
 |  | ||||||
|   if (opts.mdns) { |  | ||||||
|     server.bind(opts.port /*5353*/); |  | ||||||
|   } |  | ||||||
|   else { |  | ||||||
|     server.bind(0); |  | ||||||
|   } |  | ||||||
|   var ms = opts.timeout || (5 * 1000); |  | ||||||
|   server._timeoutToken = setTimeout(function () { |  | ||||||
|     if (!receivedMessage && opts.onTimeout) { opts.onTimeout({ timeout: ms }); } |  | ||||||
|     server.close(); |  | ||||||
|   }, ms); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function resolveJson(query, opts) { |  | ||||||
|   var queryAb; |  | ||||||
|   try { |  | ||||||
|     queryAb = dnsjs.DNSPacket.write(query); |  | ||||||
|   } catch(e) { |  | ||||||
|     if ('function' === typeof opts.onError) { opts.onError(e); return; } |  | ||||||
|     throw e; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   //console.log('[DEV] nameserver', opts.nameserver);
 |  | ||||||
|   var options = { |  | ||||||
|     onError: opts.onError |  | ||||||
|   , onMessage: function (nb) { |  | ||||||
|       var packet; |  | ||||||
|       try { |  | ||||||
|         packet = dnsjs.DNSPacket.parse(nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength)); |  | ||||||
|       } catch(e) { |  | ||||||
|         if (opts.onError) { opts.onError(e); return; } |  | ||||||
| 
 |  | ||||||
|         console.error("[Error] couldn't parse incoming message"); |  | ||||||
|         console.error(e); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       opts.onMessage(packet); |  | ||||||
|     } |  | ||||||
|   , onListening: opts.onListening |  | ||||||
|   , onSent: opts.onSent |  | ||||||
|   , onClose: opts.onClose |  | ||||||
|   , onTimeout: opts.onTimeout |  | ||||||
|   , mdns: opts.mdns |  | ||||||
|   , nameserver: opts.nameserver |  | ||||||
|   , port: opts.port |  | ||||||
|   , timeout: opts.timeout |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   return resolve(queryAb, options); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| module.exports.resolve = resolve; |  | ||||||
| module.exports.resolveJson = resolveJson; |  | ||||||
| module.exports.request = resolve; |  | ||||||
| module.exports.requestJson = resolveJson; |  | ||||||
| 
 |  | ||||||
| module.exports.logQuestion = logQuestion; |  | ||||||
							
								
								
									
										27
									
								
								hexdump.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								hexdump.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | module.exports = function hexdump(ab) { | ||||||
|  |   var ui8 = new Uint8Array(ab); | ||||||
|  |   var bytecount = 0; | ||||||
|  |   var head = '        0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F'; | ||||||
|  |   var trail; | ||||||
|  |   var str = [].slice.call(ui8).map(function (i) { | ||||||
|  |     var h = i.toString(16); | ||||||
|  |     if (h.length < 2) { | ||||||
|  |       h = '0' + h; | ||||||
|  |     } | ||||||
|  |     return h; | ||||||
|  |   }).join('').match(/.{1,2}/g).join(' ').match(/.{1,48}/g).map(function (str) { | ||||||
|  |     var lead = bytecount.toString(16); | ||||||
|  |     bytecount += 16; | ||||||
|  | 
 | ||||||
|  |     while (lead.length < 7) { | ||||||
|  |       lead = '0' + lead; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return lead + ' ' + str; | ||||||
|  |   }).join('\n'); | ||||||
|  |   trail = ab.byteLength.toString(16); | ||||||
|  |   while (trail.length < 7) { | ||||||
|  |     trail = '0' + trail; | ||||||
|  |   } | ||||||
|  |   return head + '\n' + str + '\n' + trail; | ||||||
|  | }; | ||||||
							
								
								
									
										20
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								package.json
									
									
									
									
									
								
							| @ -1,18 +1,18 @@ | |||||||
| { | { | ||||||
|   "name": "dig.js", |   "name": "dig.js", | ||||||
|   "version": "1.3.9", |   "version": "1.1.0", | ||||||
|   "description": "Create and capture DNS and mDNS query and response packets to disk as binary and/or JSON. Options are similar to the Unix `dig` command.", |   "description": "Create and capture DNS and mDNS query and response packets to disk as binary and/or JSON. Options are similar to the Unix `dig` command.", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "homepage": "https://git.coolaj86.com/coolaj86/dig.js", |  | ||||||
|   "bin": { |   "bin": { | ||||||
|     "dig.js": "./bin/dig.js" |     "dig.js": "./bin/dig.js", | ||||||
|  |     "digd.js": "./bin/digd.js" | ||||||
|   }, |   }, | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "test": "echo \"Error: no test specified\" && exit 1" |     "test": "echo \"Error: no test specified\" && exit 1" | ||||||
|   }, |   }, | ||||||
|   "repository": { |   "repository": { | ||||||
|     "type": "git", |     "type": "git", | ||||||
|     "url": "git://git.coolaj86.com:coolaj86/dig.js.git" |     "url": "git@git.daplie.com:Daplie/dig.js.git" | ||||||
|   }, |   }, | ||||||
|   "keywords": [ |   "keywords": [ | ||||||
|     "mdig", |     "mdig", | ||||||
| @ -25,8 +25,6 @@ | |||||||
|     "dig", |     "dig", | ||||||
|     "dns", |     "dns", | ||||||
|     "mdns", |     "mdns", | ||||||
|     "dns0x20", |  | ||||||
|     "0x20", |  | ||||||
|     "lint", |     "lint", | ||||||
|     "capture", |     "capture", | ||||||
|     "create", |     "create", | ||||||
| @ -34,16 +32,14 @@ | |||||||
|     "binary", |     "binary", | ||||||
|     "json" |     "json" | ||||||
|   ], |   ], | ||||||
|   "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", |   "author": "AJ ONeal <aj@daplie.com> (https://daplie.com/)", | ||||||
|   "license": "(MIT OR Apache-2.0)", |   "license": "(MIT OR Apache-2.0)", | ||||||
|   "bugs": { |   "bugs": { | ||||||
|     "url": "https://git.coolaj86.com/coolaj86/dig.js/issues" |     "url": "https://git.daplie.com/Daplie/dig.js/issues" | ||||||
|   }, |   }, | ||||||
|  |   "homepage": "https://git.daplie.com/Daplie/dig.js", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "cli": "^1.0.1", |     "cli": "^1.0.1", | ||||||
|     "dns-suite": "git+https://git.coolaj86.com/coolaj86/dns-suite.js#v1.2" |     "dns-suite": "git+https://git@git.daplie.com:Daplie/dns-suite#v1" | ||||||
|   }, |  | ||||||
|   "optionalDependencies": { |  | ||||||
|     "hexdump.js": "git+https://git.coolaj86.com/coolaj86/hexdump.js#v1.0.4" |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user