WIP dns server, mov hexdump.js to own repo, add aaonly flag

This commit is contained in:
AJ ONeal 2017-09-25 14:43:21 -06:00
parent cdd490ec42
commit 6d0f9b1588
4 changed files with 164 additions and 45 deletions

View File

@ -38,6 +38,16 @@ cli.main(function (args, cli) {
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");
@ -69,7 +79,7 @@ cli.main(function (args, cli) {
}
if (cli.query) {
console.error("'query' was specified more than once");
console.error("'query' was specified more than once or unrecognized flag: " + cli.query + ", " + arg);
process.exit(1);
return;
}
@ -124,11 +134,11 @@ cli.main(function (args, cli) {
id: require('crypto').randomBytes(2).readUInt16BE(0)
, qr: 0
, opcode: 0
, aa: 0 // NA
, tc: 0 // NA
, aa: cli.aaonly ? 1 : 0 // NA
, tc: 0 // NA
, rd: cli.norecurse ? 0 : 1
, ra: 0 // NA
, rcode: 0 // NA
, ra: 0 // NA
, rcode: 0 // NA
}
, question: [
{ name: cli.query
@ -140,7 +150,7 @@ cli.main(function (args, cli) {
var dnsjs = require('dns-suite');
var queryAb = dnsjs.DNSPacket.write(query);
var hexdump = require('../hexdump');
var hexdump = require('hexdump.js').hexdump;
if (cli.debug) {
console.log('');
@ -254,5 +264,6 @@ cli.main(function (args, cli) {
, port: cli.port
, timeout: cli.timeout
};
dig.resolve(queryAb, opts);
});

View File

@ -1,10 +1,10 @@
'use strict';
var cli = require('cli');
var dns = require('dns');
var dig = require('../dns-request');
var dgram = require('dgram');
var dnsjs = require('dns-suite');
var hexdump = require('../hexdump');
var hexdump = require('hexdump.js').hexdump;
var crypto = require('crypto');
var common = require('../common');
var defaultNameservers = require('dns').getServers();
@ -78,9 +78,12 @@ cli.main(function (args, cli) {
console.error("error:", err.stack);
server.close();
};
handlers.onMessage = function (nb) {
handlers.onMessage = function (nb, rinfo) {
var queryAb = nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength);
var query = dnsjs.DNSPacket.parse(queryAb);
var newQuery;
var count;
if (cli.debug) {
console.log('');
@ -92,6 +95,8 @@ cli.main(function (args, cli) {
console.log('');
}
dig.logQuestion(query);
/*
console.log(';; Got question:');
console.log(';; ->>HEADER<<-');
console.log(JSON.stringify(query.header));
@ -100,6 +105,7 @@ cli.main(function (args, cli) {
query.question.forEach(function (q) {
console.log(';' + q.name + '.', ' ', q.className, q.typeName);
});
*/
function print(q) {
var printer = common.printers[q.typeName] || common.printers.ANY;
@ -132,19 +138,147 @@ cli.main(function (args, cli) {
//common.writeResponse(opts, query, nb, packet);
}
if (!cli.norecurse) {
// ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT
var count = query.question.length;
function sendEmptyResponse(query) {
var newQuery = {
header: {
id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0)
, qr: 1
, opcode: 0
, aa: 0 // TODO maybe
, tc: 0
, rd: query.header.rd
, ra: cli.norecurse ? 0 : 1
, rcode: 0 // no error
}
, question: []
, answer: []
, authority: []
, additional: []
};
query.question.forEach(function (q) {
dns.resolve(q.name, q.typeName, function () {
count -= 1;
if (!count) {
}
newQuery.question.push({
name: q.name
, type: q.type
, typeName: q.typeName
, class: q.class
, className: q.className
});
console.log(';' + q.name + '.', ' ', q.className, q.typeName);
});
server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () {
console.log('[DEV] response sent');
});
}
count = query.question.length;
if (!count) {
sendEmptyResponse(query);
return;
}
// TODO get local answer first, if available
if (query.header.rd) {
if (cli.norecurse) {
console.log("[Could not answer. Sent empty response.]");
sendEmptyResponse(query);
return;
} else {
// ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT
newQuery = {
header: {
id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0)
, qr: 0
, opcode: 0
, aa: query.header.aa ? 1 : 0 // NA? not sure what this would do
, tc: 0 // NA
, rd: 1
, ra: 0 // NA
, rcode: 0 // NA
}
, question: [
/*
{ name: cli.query
, typeName: cli.type
, className: cli.class
}
*/
]
, answer: []
, authority: []
, additional: []
};
query.question.forEach(function (q) {
newQuery.question.push({
name: q.name
, type: q.type
, typeName: q.typeName
, class: q.class
, className: q.className
});
function updateCount() {
count -= 1;
if (!count) {
server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () {
console.log('[DEV] response sent');
});
}
}
var opts = {
onError: function () {
updateCount();
}
, onMessage: function (packet) {
(packet.answer||[]).forEach(function (a) {
// TODO copy each relevant property
console.log('ans', a);
newQuery.answer.push(a);
});
(packet.authority||[]).forEach(function (a) {
// TODO copy each relevant property
console.log('auth', a);
newQuery.authority.push(a);
});
(packet.additional||[]).forEach(function (a) {
// TODO copy each relevant property
console.log('add', a);
newQuery.additional.push(a);
});
updateCount();
}
, onListening: function () {}
, onSent: function (res) {
if (cli.debug) {
console.log('');
console.log('request sent to', res.nameserver);
}
}
, onTimeout: function (res) {
console.log(";; [" + q.name + "] 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);
dig.resolveJson(query, opts);
console.log(';' + q.name + '.', ' ', q.className, q.typeName);
});
}
}
};
handlers.onListening = function () {
/*jshint validthis:true*/
var server = this;

View File

@ -1,27 +0,0 @@
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;
};

View File

@ -40,6 +40,7 @@
"homepage": "https://git.daplie.com/Daplie/dig.js",
"dependencies": {
"cli": "^1.0.1",
"dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1.1.0"
"dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1.1.0",
"hexdump.js": "^1.0.2"
}
}