add ANAME resolution
This commit is contained in:
parent
d32dba2a75
commit
a089bfc8e5
|
@ -155,6 +155,7 @@ module.exports = {
|
||||||
|
|
||||||
// A, AAAA
|
// A, AAAA
|
||||||
, address: '127.0.0.1'
|
, address: '127.0.0.1'
|
||||||
|
, aname: 'some-device.example.com' // See "A Note on ANAMEs" below
|
||||||
|
|
||||||
// CAA
|
// CAA
|
||||||
, flag: 0
|
, flag: 0
|
||||||
|
@ -194,6 +195,14 @@ Note: Because it's possible to that delegated subdomains could have delegated su
|
||||||
original nameserver, **NS** records will be replaced with an SOA record if any of the NS records match any of
|
original nameserver, **NS** records will be replaced with an SOA record if any of the NS records match any of
|
||||||
the server's primary nameservers or if vanity nameservers are used.
|
the server's primary nameservers or if vanity nameservers are used.
|
||||||
|
|
||||||
|
### A Note on ANAMES
|
||||||
|
|
||||||
|
ANAMEs serve two purposes in this system:
|
||||||
|
|
||||||
|
1. Traditional ANAME. Just a CNAME that is automatically resolved to an A record for the "bare domain" problem, and efficiency.
|
||||||
|
2. Dynamic DNS. When a record on the system is updated, any records that match it by ANAME are also updated
|
||||||
|
|
||||||
|
TODO: use dns0x20 for ANAME resolutions
|
||||||
|
|
||||||
Other Resources
|
Other Resources
|
||||||
---------------
|
---------------
|
||||||
|
|
8
TESTS.md
8
TESTS.md
|
@ -23,8 +23,16 @@ Send malformed packets (both as queries and as answers):
|
||||||
- compression pointers to wrong bits (throw error on non-ascii / unsafe chars)
|
- compression pointers to wrong bits (throw error on non-ascii / unsafe chars)
|
||||||
|
|
||||||
Test that ANY queries return records of all types matching the domain
|
Test that ANY queries return records of all types matching the domain
|
||||||
|
|
||||||
Test that A queries only return A records, not others matching the domain
|
Test that A queries only return A records, not others matching the domain
|
||||||
|
|
||||||
|
Test that A queries for ANAME-enabled records (but no address) recurse (regardless of general recursion settings).
|
||||||
|
* 0-anames.example.com
|
||||||
|
* 1-aname.example.com
|
||||||
|
* 2-anames.example.com
|
||||||
|
|
||||||
|
Generally speaking test the cases of 0, 1, and 2 records of any given type (null case, single case, multi case)
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# Sample Data:
|
# Sample Data:
|
||||||
|
|
|
@ -367,6 +367,12 @@ cli.main(function (args, cli) {
|
||||||
|
|
||||||
// TODO get local answer first, if available
|
// TODO get local answer first, if available
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
if (!cli.input) {
|
||||||
|
console.warn('[WARN] no db path given, must recurse if enabled');
|
||||||
|
recurse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
require('../lib/dns-store').query(path.resolve(cli.input), query, function (err, resp) {
|
require('../lib/dns-store').query(path.resolve(cli.input), query, function (err, resp) {
|
||||||
|
|
||||||
if (err) { console.log('[DEV] answer not found in local db, recursing'); console.error(err); recurse(); return; }
|
if (err) { console.log('[DEV] answer not found in local db, recursing'); console.error(err); recurse(); return; }
|
||||||
|
|
|
@ -11,7 +11,12 @@ var NXDOMAIN = 3;
|
||||||
var REFUSED = 5;
|
var REFUSED = 5;
|
||||||
|
|
||||||
function getRecords(db, qname, cb) {
|
function getRecords(db, qname, cb) {
|
||||||
var myRecords = db.records.filter(function (r) {
|
var delMe = {};
|
||||||
|
var dns = require('dns');
|
||||||
|
// SECURITY XXX TODO var dig = require('dig.js/dns-request');
|
||||||
|
var count;
|
||||||
|
var myRecords = db.records.slice(0).filter(function (r) {
|
||||||
|
|
||||||
if ('string' !== typeof r.name) {
|
if ('string' !== typeof r.name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -23,9 +28,52 @@ function getRecords(db, qname, cb) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
process.nextTick(function () {
|
function checkCount() {
|
||||||
cb(null, myRecords);
|
count -= 1;
|
||||||
|
if (count <= 0) {
|
||||||
|
myRecords = myRecords.filter(function (r) {
|
||||||
|
return !delMe[r.id];
|
||||||
|
});
|
||||||
|
cb(null, myRecords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRecord(r) {
|
||||||
|
// TODO allow multiple records to be returned(?)
|
||||||
|
return function (err, addresses) {
|
||||||
|
if (err || !addresses.length) {
|
||||||
|
r.id = r.id || Math.random();
|
||||||
|
delMe[r.id] = true;
|
||||||
|
} else if (addresses.length > 1) {
|
||||||
|
r._address = addresses[Math.floor(Math.random() * addresses.length)];
|
||||||
|
} else {
|
||||||
|
r._address = addresses[0];
|
||||||
|
}
|
||||||
|
checkCount();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
count = myRecords.length;
|
||||||
|
myRecords.forEach(function (r) {
|
||||||
|
if (r.aname && !r.address) {
|
||||||
|
if ('A' === r.type) {
|
||||||
|
// SECURITY XXX TODO dig.resolveJson(query, opts);
|
||||||
|
dns.resolve4(r.aname, getRecord(r));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('AAAA' === r.type) {
|
||||||
|
// SECURITY XXX TODO dig.resolveJson(query, opts);
|
||||||
|
dns.resolve6(r.aname, getRecord(r));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCount();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!myRecords.length) {
|
||||||
|
checkCount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbToResourceRecord(r) {
|
function dbToResourceRecord(r) {
|
||||||
|
@ -47,7 +95,7 @@ function dbToResourceRecord(r) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A, AAAA
|
// A, AAAA
|
||||||
, address: -1 !== [ 'A', 'AAAA' ].indexOf(r.type) ? (r.address || r.value) : undefined
|
, address: -1 !== [ 'A', 'AAAA' ].indexOf(r.type) ? (r._address || r.address || r.value) : undefined
|
||||||
|
|
||||||
// CNAME, NS, PTR || TXT
|
// CNAME, NS, PTR || TXT
|
||||||
, data: -1 !== [ 'CNAME', 'NS', 'PTR', 'TXT' ].indexOf(r.type) ? (r.data || r.value || r.values) : undefined
|
, data: -1 !== [ 'CNAME', 'NS', 'PTR', 'TXT' ].indexOf(r.type) ? (r.data || r.value || r.values) : undefined
|
||||||
|
|
|
@ -15,6 +15,9 @@ module.exports = {
|
||||||
, { "zone": "daplie.me", "name": "www.daplie.me", "tld": "me", "sld": "daplie", "sub": "www"
|
, { "zone": "daplie.me", "name": "www.daplie.me", "tld": "me", "sld": "daplie", "sub": "www"
|
||||||
, "type": "A", "address": "23.228.168.108", "aname": "tardigrade.devices.daplie.me" }
|
, "type": "A", "address": "23.228.168.108", "aname": "tardigrade.devices.daplie.me" }
|
||||||
|
|
||||||
|
, { "zone": "daplie.me", "name": "aname.daplie.me", "tld": "me", "sld": "daplie", "sub": "aname"
|
||||||
|
, "type": "A", "aname": "google.com" }
|
||||||
|
|
||||||
, { "zone": "daplie.me", "name": "email.daplie.me", "tld": "me", "sld": "daplie", "sub": "email"
|
, { "zone": "daplie.me", "name": "email.daplie.me", "tld": "me", "sld": "daplie", "sub": "email"
|
||||||
, "type": "CNAME", "data": "mailgun.org" }
|
, "type": "CNAME", "data": "mailgun.org" }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue