Compare commits
	
		
			No commits in common. "bc93b942eeed278077d1a433c6a182dc48394e7d" and "bd8b57efd11e75472e9372a252e91189f8b830d9" have entirely different histories.
		
	
	
		
			bc93b942ee
			...
			bd8b57efd1
		
	
		
@ -89,8 +89,6 @@ Options
 | 
			
		||||
+time=<seconds>             Sets the timeout for a query in seconds.
 | 
			
		||||
+norecurse                  Set `ra` flag to 0. Do not perform recursion.
 | 
			
		||||
+aaonly                     Set `aa` flag to 1. Do not respond with non-authoritative responses.
 | 
			
		||||
+notcp                      Disable TCP server (default in v1.2)
 | 
			
		||||
+tcp                        Enable TCP server (default in v1.3)
 | 
			
		||||
 | 
			
		||||
--debug                     verbose output
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								bin/digd.js
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								bin/digd.js
									
									
									
									
									
								
							@ -5,7 +5,9 @@
 | 
			
		||||
var cli = require('cli');
 | 
			
		||||
var pkg = require('../package.json');
 | 
			
		||||
var dig = require('dig.js/dns-request');
 | 
			
		||||
var dgram = require('dgram');
 | 
			
		||||
var dnsjs = require('dns-suite');
 | 
			
		||||
var crypto = require('crypto');
 | 
			
		||||
var common = require('dig.js/common');
 | 
			
		||||
var defaultNameservers = require('dns').getServers();
 | 
			
		||||
var hexdump;
 | 
			
		||||
@ -47,32 +49,8 @@ cli.main(function (args, cli) {
 | 
			
		||||
      cli.norecurse = true;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (arg === '+notcp') {
 | 
			
		||||
      if (cli.notcp) {
 | 
			
		||||
        console.error("'+notcp' was specified more than once");
 | 
			
		||||
        process.exit(1);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      cli.notcp = true;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (arg === '+tcp') {
 | 
			
		||||
      if (cli.tcp) {
 | 
			
		||||
        console.error("'+tcp' was specified more than once");
 | 
			
		||||
        process.exit(1);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      cli.tcp = true;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (!cli.tcp) {
 | 
			
		||||
    if (!cli.notcp) {
 | 
			
		||||
      console.info("[WARNING] Set '+notcp' to disable tcp connections. The default behavior changes to +tcp in v1.3");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (cli.mdns) {
 | 
			
		||||
    if (!cli.type) {
 | 
			
		||||
      cli.type = cli.t = 'PTR';
 | 
			
		||||
@ -95,10 +73,32 @@ cli.main(function (args, cli) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var dnsd = {};
 | 
			
		||||
  dnsd.onMessage = function (nb, cb) {
 | 
			
		||||
    var byteOffset = nb._dnsByteOffset || nb.byteOffset;
 | 
			
		||||
    var queryAb = nb.buffer.slice(byteOffset, byteOffset + nb.byteLength);
 | 
			
		||||
  var handlers = {};
 | 
			
		||||
  var server = dgram.createSocket({
 | 
			
		||||
    type: cli.udp6 ? 'udp6' : 'udp4'
 | 
			
		||||
  , reuseAddr: true
 | 
			
		||||
  });
 | 
			
		||||
  server.bind({
 | 
			
		||||
    port: cli.port
 | 
			
		||||
  , address: cli.address
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  handlers.onError = function (err) {
 | 
			
		||||
    if ('EACCES' === err.code) {
 | 
			
		||||
      console.error("");
 | 
			
		||||
      console.error("EACCES: Couldn't bind to port. You probably need to use sudo, authbind, or setcap.");
 | 
			
		||||
      console.error("");
 | 
			
		||||
      process.exit(123);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    console.error("error:", err.stack);
 | 
			
		||||
    server.close();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handlers.onMessage = function (nb, rinfo) {
 | 
			
		||||
    console.log('[DEBUG] got a message');
 | 
			
		||||
 | 
			
		||||
    var queryAb = nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength);
 | 
			
		||||
    var query;
 | 
			
		||||
    var count;
 | 
			
		||||
 | 
			
		||||
@ -215,11 +215,12 @@ cli.main(function (args, cli) {
 | 
			
		||||
        console.error("Could not write empty DNS response");
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        console.error(emptyResp);
 | 
			
		||||
        cb(e, null, '[DEV] response sent (empty)');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      cb(null, newAb, '[DEV] response sent (empty)');
 | 
			
		||||
      server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log('[DEV] response sent (empty)', rinfo.port, rinfo.address);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function sendResponse(newPacket) {
 | 
			
		||||
@ -231,11 +232,12 @@ cli.main(function (args, cli) {
 | 
			
		||||
        console.error("Could not write DNS response from local");
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        console.error(newPacket);
 | 
			
		||||
        cb(e, null, '[DEV] response sent (local query)');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      cb(null, newAb, '[DEV] response sent (local query)');
 | 
			
		||||
      server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log('[DEV] response sent (local query)', rinfo.port, rinfo.address);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function recurse() {
 | 
			
		||||
@ -288,11 +290,12 @@ cli.main(function (args, cli) {
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
              console.error("Could not write DNS response");
 | 
			
		||||
              console.error(newResponse);
 | 
			
		||||
              cb(e, null, '[DEV] response sent');
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            cb(null, newAb, '[DEV] response sent');
 | 
			
		||||
            server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
              console.log('[DEV] response sent', rinfo.port, rinfo.address);
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -332,8 +335,7 @@ cli.main(function (args, cli) {
 | 
			
		||||
              console.log('request sent to', res.nameserver);
 | 
			
		||||
            }
 | 
			
		||||
            */
 | 
			
		||||
            //console.log('[DEV] query sent (recurse)', rinfo.port, rinfo.address);
 | 
			
		||||
            //dnsd.onSent('[DEV] query sent (recurse)');
 | 
			
		||||
            console.log('[DEV] query sent (recurse)', rinfo.port, rinfo.address);
 | 
			
		||||
          }
 | 
			
		||||
        , onTimeout: function (res) {
 | 
			
		||||
            console.log(";; [" + q.name + "] connection timed out; no servers could be reached");
 | 
			
		||||
@ -391,24 +393,32 @@ cli.main(function (args, cli) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    require('../lib/digd.js').query(engine, query, respondWithResults);
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  cli.defaultNameservers = defaultNameservers;
 | 
			
		||||
  require('../lib/udpd.js').create(cli, dnsd).on('listening', function () {
 | 
			
		||||
  handlers.onListening = function () {
 | 
			
		||||
    /*jshint validthis:true*/
 | 
			
		||||
    var server = this;
 | 
			
		||||
    cli.chosenNameserver = cli.nameserver;
 | 
			
		||||
    var index;
 | 
			
		||||
 | 
			
		||||
    if (!cli.chosenNameserver) {
 | 
			
		||||
      index = require('crypto').randomBytes(2).readUInt16BE(0) % cli.defaultNameservers.length;
 | 
			
		||||
      cli.chosenNameserver = cli.defaultNameservers[index];
 | 
			
		||||
      index = crypto.randomBytes(2).readUInt16BE(0) % defaultNameservers.length;
 | 
			
		||||
      cli.chosenNameserver = defaultNameservers[index];
 | 
			
		||||
      if (cli.debug) {
 | 
			
		||||
        console.log('index, defaultNameservers', index, cli.defaultNameservers);
 | 
			
		||||
        console.log('index, defaultNameservers', index, defaultNameservers);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  if (cli.tcp /* TODO v1.3 !cli.notcp */) {
 | 
			
		||||
    require('../lib/tcpd.js').create(cli, dnsd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (cli.mdns || '224.0.0.251' === cli.nameserver) {
 | 
			
		||||
      server.setBroadcast(true);
 | 
			
		||||
      server.addMembership(cli.nameserver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.log('');
 | 
			
		||||
    console.log('Bound and Listening:');
 | 
			
		||||
    console.log(server.address().address + '#' + server.address().port + ' (' + server.type + ')');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  console.log('');
 | 
			
		||||
  if (!cli.nocmd) {
 | 
			
		||||
@ -416,4 +426,7 @@ cli.main(function (args, cli) {
 | 
			
		||||
    console.log(';; global options: +cmd');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  server.on('error', handlers.onError);
 | 
			
		||||
  server.on('message', handlers.onMessage);
 | 
			
		||||
  server.on('listening', handlers.onListening);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										70
									
								
								lib/tcpd.js
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								lib/tcpd.js
									
									
									
									
									
								
							@ -1,70 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (cli, dnsd) {
 | 
			
		||||
  function runTcp() {
 | 
			
		||||
    var tcpServer = require('net').createServer({ }, function (c) {
 | 
			
		||||
      c.on('error', function (err) {
 | 
			
		||||
        console.warn("TCP Connection Error:");
 | 
			
		||||
        console.warn(err);
 | 
			
		||||
      });
 | 
			
		||||
      c.on('data', function (nb) {
 | 
			
		||||
        //console.log('TCP data.length:', nb.length);
 | 
			
		||||
        //console.log(nb.toString('hex'));
 | 
			
		||||
 | 
			
		||||
        // DNS packets include a 2-byte length header
 | 
			
		||||
        var count = nb.length;
 | 
			
		||||
        var length = nb[0] << 8;
 | 
			
		||||
        length = length | nb[1];
 | 
			
		||||
        count -= 2;
 | 
			
		||||
        // TODO slice?
 | 
			
		||||
        nb._dnsByteOffset = nb.byteOffset + 2;
 | 
			
		||||
 | 
			
		||||
        if (length !== count) {
 | 
			
		||||
          console.error("Handling TCP packets > 512 bytes not implemented.");
 | 
			
		||||
          c.end();
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO pad two bytes for lengths
 | 
			
		||||
        dnsd.onMessage(nb, function (err, newAb, dbgmsg) {
 | 
			
		||||
          var lenbuf = Buffer.from([ newAb.length >> 8, newAb.length & 255 ]);
 | 
			
		||||
          // TODO XXX generate legit error packet
 | 
			
		||||
          if (err) { console.error("Error", err); c.end(); return; }
 | 
			
		||||
          console.log('TCP ' + dbgmsg);
 | 
			
		||||
 | 
			
		||||
          c.write(lenbuf);
 | 
			
		||||
          c.end(newAb);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      c.on('end', function () {
 | 
			
		||||
        console.log('TCP client disconnected from server');
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    tcpServer.on('error', function (err) {
 | 
			
		||||
      if ('EADDRINUSE' === err.code) {
 | 
			
		||||
        console.error("Port '" + cli.port + "' is already in use.");
 | 
			
		||||
        tcpServer.close();
 | 
			
		||||
        process.exit(0);
 | 
			
		||||
      }
 | 
			
		||||
      if ('EACCES' === err.code) {
 | 
			
		||||
        console.error("Could not bind on port '" + cli.port + "': EACCESS (you probably need root permissions)");
 | 
			
		||||
        tcpServer.close();
 | 
			
		||||
        process.exit(0);
 | 
			
		||||
      }
 | 
			
		||||
      console.error("TCP Server Error:");
 | 
			
		||||
      console.error(err);
 | 
			
		||||
      tcpServer.close(function () {
 | 
			
		||||
        setTimeout(runTcp, 1000);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    tcpServer.listen(cli.port, function () {
 | 
			
		||||
      console.log('TCP Server bound');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return tcpServer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return runTcp();
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										58
									
								
								lib/udpd.js
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								lib/udpd.js
									
									
									
									
									
								
							@ -1,58 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (cli, dnsd) {
 | 
			
		||||
  var server = require('dgram').createSocket({
 | 
			
		||||
    type: cli.udp6 ? 'udp6' : 'udp4'
 | 
			
		||||
  , reuseAddr: true
 | 
			
		||||
  });
 | 
			
		||||
  server.bind({
 | 
			
		||||
    port: cli.port
 | 
			
		||||
  , address: cli.address
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  var handlers = {};
 | 
			
		||||
  handlers.onError = function (err) {
 | 
			
		||||
    if ('EACCES' === err.code) {
 | 
			
		||||
      console.error("");
 | 
			
		||||
      console.error("EACCES: Couldn't bind to port. You probably need to use sudo, authbind, or setcap.");
 | 
			
		||||
      console.error("");
 | 
			
		||||
      process.exit(123);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    console.error("error:", err.stack);
 | 
			
		||||
    server.close();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handlers.onMessage = function (nb, rinfo) {
 | 
			
		||||
    //console.log('[DEBUG] got a UDP message', nb.length);
 | 
			
		||||
    //console.log(nb.toString('hex'));
 | 
			
		||||
 | 
			
		||||
    dnsd.onMessage(nb, function (err, newAb, dbgmsg) {
 | 
			
		||||
      // TODO send legit error message
 | 
			
		||||
      if (err) { server.send(Buffer.from([0x00])); return; }
 | 
			
		||||
      server.send(newAb, rinfo.port, rinfo.address, function () {
 | 
			
		||||
        console.log(dbgmsg, rinfo.port, rinfo.address);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handlers.onListening = function () {
 | 
			
		||||
    /*jshint validthis:true*/
 | 
			
		||||
    var server = this;
 | 
			
		||||
 | 
			
		||||
    if (cli.mdns || '224.0.0.251' === cli.nameserver) {
 | 
			
		||||
      server.setBroadcast(true);
 | 
			
		||||
      server.addMembership(cli.nameserver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.log('');
 | 
			
		||||
    console.log('Bound and Listening:');
 | 
			
		||||
    console.log(server.address().address + '#' + server.address().port + ' (' + server.type + ')');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  server.on('error', handlers.onError);
 | 
			
		||||
  server.on('message', handlers.onMessage);
 | 
			
		||||
  server.on('listening', handlers.onListening);
 | 
			
		||||
 | 
			
		||||
  return server;
 | 
			
		||||
};
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "digd.js",
 | 
			
		||||
  "version": "1.2.1",
 | 
			
		||||
  "version": "1.2.0",
 | 
			
		||||
  "description": "A lightweight DNS / mDNS daemon (server) for creating and capturing DNS and mDNS query and response packets to disk as binary and/or JSON. Options are similar to the Unix dig command.",
 | 
			
		||||
  "main": "bin/digd.js",
 | 
			
		||||
  "homepage": "https://git.coolaj86.com/coolaj86/digd.js",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user