WIP dns server
This commit is contained in:
		
							parent
							
								
									083df5755b
								
							
						
					
					
						commit
						fcaafbf8b9
					
				
							
								
								
									
										117
									
								
								bin/digd.js
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								bin/digd.js
									
									
									
									
									
								
							@ -4,10 +4,10 @@ var cli = require('cli');
 | 
			
		||||
var dig = require('../dns-request');
 | 
			
		||||
var dgram = require('dgram');
 | 
			
		||||
var dnsjs = require('dns-suite');
 | 
			
		||||
var hexdump = require('hexdump.js').hexdump;
 | 
			
		||||
var crypto = require('crypto');
 | 
			
		||||
var common = require('../common');
 | 
			
		||||
var defaultNameservers = require('dns').getServers();
 | 
			
		||||
var hexdump;
 | 
			
		||||
 | 
			
		||||
cli.parse({
 | 
			
		||||
//  'b': [ false, 'set source IP address (defaults to 0.0.0.0)', 'string' ]
 | 
			
		||||
@ -81,18 +81,37 @@ cli.main(function (args, cli) {
 | 
			
		||||
 | 
			
		||||
  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 query;
 | 
			
		||||
    var count;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      query = dnsjs.DNSPacket.parse(queryAb);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      // TODO log bad queries (?)
 | 
			
		||||
      console.error("Could not parse DNS query, ignoring.");
 | 
			
		||||
      try {
 | 
			
		||||
        hexdump = require('hexdump.js').hexdump;
 | 
			
		||||
        console.error(hexdump(queryAb));
 | 
			
		||||
        console.error('');
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        // ignore
 | 
			
		||||
      }
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cli.debug) {
 | 
			
		||||
      console.log('');
 | 
			
		||||
      console.log('DNS Question:');
 | 
			
		||||
      console.log('');
 | 
			
		||||
      console.log(query);
 | 
			
		||||
      console.log('');
 | 
			
		||||
      console.log(hexdump(queryAb));
 | 
			
		||||
      console.log('');
 | 
			
		||||
      try {
 | 
			
		||||
        hexdump = require('hexdump.js').hexdump;
 | 
			
		||||
        console.log(hexdump(queryAb));
 | 
			
		||||
        console.log('');
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        // ignore
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dig.logQuestion(query);
 | 
			
		||||
@ -138,17 +157,18 @@ cli.main(function (args, cli) {
 | 
			
		||||
      //common.writeResponse(opts, query, nb, packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function sendEmptyResponse(query) {
 | 
			
		||||
      var newQuery = {
 | 
			
		||||
    function sendEmptyResponse(query, nx) {
 | 
			
		||||
      var newAb;
 | 
			
		||||
      var emptyResp = {
 | 
			
		||||
        header: {
 | 
			
		||||
          id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0)
 | 
			
		||||
        , qr: 1
 | 
			
		||||
        , opcode: 0
 | 
			
		||||
        , aa: 0     // TODO maybe
 | 
			
		||||
        , aa: 0     // TODO it may be authoritative
 | 
			
		||||
        , tc: 0
 | 
			
		||||
        , rd: query.header.rd
 | 
			
		||||
        , ra: cli.norecurse ? 0 : 1
 | 
			
		||||
        , rcode: 0  // no error
 | 
			
		||||
        , ra: cli.norecurse ? 0 : 1 // TODO is this bit dependent on the rd bit?
 | 
			
		||||
        , rcode: nx ? 3 : 0 // no error
 | 
			
		||||
        }
 | 
			
		||||
      , question: []
 | 
			
		||||
      , answer: []
 | 
			
		||||
@ -156,7 +176,7 @@ cli.main(function (args, cli) {
 | 
			
		||||
      , additional: []
 | 
			
		||||
      };
 | 
			
		||||
      query.question.forEach(function (q) {
 | 
			
		||||
        newQuery.question.push({
 | 
			
		||||
        emptyResp.question.push({
 | 
			
		||||
          name: q.name
 | 
			
		||||
        , type: q.type
 | 
			
		||||
        , typeName: q.typeName
 | 
			
		||||
@ -164,26 +184,52 @@ cli.main(function (args, cli) {
 | 
			
		||||
        , className: q.className
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log('[DEV] response sent');
 | 
			
		||||
 | 
			
		||||
      try {
 | 
			
		||||
        newAb = dnsjs.DNSPacket.write(emptyResp);
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        console.error("Could not write DNS response");
 | 
			
		||||
        console.error(emptyResp);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log('[DEV] response sent (empty)');
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function sendResponse(newPacket) {
 | 
			
		||||
      var newAb;
 | 
			
		||||
 | 
			
		||||
      try {
 | 
			
		||||
        newAb = dnsjs.DNSPacket.write(newPacket);
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        console.error("Could not write DNS response");
 | 
			
		||||
        console.error(newPacket);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log('[DEV] response sent (local query)');
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function recurse() {
 | 
			
		||||
      if (!query.header.rd) {
 | 
			
		||||
        console.log("[Could not answer. Sent empty response.]");
 | 
			
		||||
        sendEmptyResponse(query);
 | 
			
		||||
        sendEmptyResponse(query, true);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (cli.norecurse) {
 | 
			
		||||
        console.log("[Could not answer. Sent empty response.]");
 | 
			
		||||
        sendEmptyResponse(query);
 | 
			
		||||
        sendEmptyResponse(query, true);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT
 | 
			
		||||
      newQuery = {
 | 
			
		||||
      // TODO newQuery
 | 
			
		||||
 | 
			
		||||
      var newResponse = {
 | 
			
		||||
        header: {
 | 
			
		||||
          id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0)
 | 
			
		||||
        , qr: 0
 | 
			
		||||
@ -200,7 +246,7 @@ cli.main(function (args, cli) {
 | 
			
		||||
      , additional: []
 | 
			
		||||
      };
 | 
			
		||||
      query.question.forEach(function (q) {
 | 
			
		||||
        newQuery.question.push({
 | 
			
		||||
        newResponse.question.push({
 | 
			
		||||
          name: q.name
 | 
			
		||||
        , type: q.type
 | 
			
		||||
        , typeName: q.typeName
 | 
			
		||||
@ -209,9 +255,19 @@ cli.main(function (args, cli) {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        function updateCount() {
 | 
			
		||||
          var newAb;
 | 
			
		||||
          count -= 1;
 | 
			
		||||
 | 
			
		||||
          if (!count) {
 | 
			
		||||
            server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () {
 | 
			
		||||
            try {
 | 
			
		||||
              newAb = dnsjs.DNSPacket.write(newResponse);
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
              console.error("Could not write DNS response");
 | 
			
		||||
              console.error(newResponse);
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
              console.log('[DEV] response sent');
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
@ -225,29 +281,32 @@ cli.main(function (args, cli) {
 | 
			
		||||
 | 
			
		||||
            (packet.answer||[]).forEach(function (a) {
 | 
			
		||||
              // TODO copy each relevant property
 | 
			
		||||
              console.log('ans', a);
 | 
			
		||||
              newQuery.answer.push(a);
 | 
			
		||||
              console.log('ans', JSON.stringify(a, null, 2));
 | 
			
		||||
              newResponse.answer.push(a);
 | 
			
		||||
            });
 | 
			
		||||
            (packet.authority||[]).forEach(function (a) {
 | 
			
		||||
              // TODO copy each relevant property
 | 
			
		||||
              console.log('auth', a);
 | 
			
		||||
              newQuery.authority.push(a);
 | 
			
		||||
              console.log('auth', JSON.stringify(a, null, 2));
 | 
			
		||||
              newResponse.authority.push(a);
 | 
			
		||||
            });
 | 
			
		||||
            (packet.additional||[]).forEach(function (a) {
 | 
			
		||||
              // TODO copy each relevant property
 | 
			
		||||
              console.log('add', a);
 | 
			
		||||
              newQuery.additional.push(a);
 | 
			
		||||
              console.log('add', JSON.stringify(a, null, 2));
 | 
			
		||||
              newResponse.additional.push(a);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            updateCount();
 | 
			
		||||
 | 
			
		||||
          }
 | 
			
		||||
        , onListening: function () {}
 | 
			
		||||
        , onSent: function (res) {
 | 
			
		||||
        , onSent: function (/*res*/) {
 | 
			
		||||
            /*
 | 
			
		||||
            if (cli.debug) {
 | 
			
		||||
              console.log('');
 | 
			
		||||
              console.log('request sent to', res.nameserver);
 | 
			
		||||
            }
 | 
			
		||||
            */
 | 
			
		||||
            console.log('[DEV] response sent (recurse)');
 | 
			
		||||
          }
 | 
			
		||||
        , onTimeout: function (res) {
 | 
			
		||||
            console.log(";; [" + q.name + "] connection timed out; no servers could be reached");
 | 
			
		||||
@ -276,7 +335,11 @@ cli.main(function (args, cli) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO get local answer first, if available
 | 
			
		||||
    recurse();
 | 
			
		||||
    require('../dns-store').query(query, function (err, resp) {
 | 
			
		||||
      if (err) { recurse(); return; }
 | 
			
		||||
 | 
			
		||||
      sendResponse(resp);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,11 +27,10 @@ module.exports = {
 | 
			
		||||
  , '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);
 | 
			
		||||
      // 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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								dns-store.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								dns-store.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
(function () {
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
module.exports.query = function (query, cb) {
 | 
			
		||||
  process.nextTick(function () {
 | 
			
		||||
    cb(new Error('No local lookup method for DNS records defined.'));
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}());
 | 
			
		||||
@ -40,7 +40,9 @@
 | 
			
		||||
  "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",
 | 
			
		||||
    "hexdump.js": "^1.0.2"
 | 
			
		||||
    "dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1.1.0"
 | 
			
		||||
  },
 | 
			
		||||
  "optionalDependencies": {
 | 
			
		||||
    "hexdump.js": "git+https://git@git.daplie.com/Daplie/hexdump.js#master"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user