Node.js bindings of getdns, a modern asynchronous DNS API.
getdns-node: NPM | Github | Examples | Issues |
getdns: Website | Github | Specification | Presentations | Releases
Features
getdns-node has a few advantages over the default DNS module in Node.js.
- DNS lookup security with Domain Name System Security Extensions
(DNSSEC) signature validation.
- Supports all DNS record types with constants for 80+ (
A
, AAAA
, MX
, TXT
, SSHFP
, OPENPGPKEY
, ...). - Configure as local recursive DNS server, or stub mode with upstream DNS resolvers.
- Perform both IPv4 and IPv6 lookups in a single call.
- Configure to perform lookups over TLS, TCP, or UDP, with fallbacks and long-lived connections.
- Configure to explicitly follow or explicitly not follow
CNAME
and DNAME
redirects. - Securely verify DNS-based security records such as
Installation and Requirements
# In your project directory.
npm install --save getdns
- Older versions/combinations of dependencies may be supported in the special
support/
branches. Support branches contain minimal patches to get that particular combination running — quite possibly with a restricted set of features. They are not actively maintained, and may be rebased if required. - See
.travis.yml
for exact Node.js versions used by Travis during build tests.
API Examples
See the samples/
folder for more.
var getdns = require("getdns");
var options = {
resolution_type: getdns.RESOLUTION_STUB,
upstream_recursive_servers: [
"8.8.8.8",
["127.0.0.1", 53],
],
timeout: 1000,
return_dnssec_status: true
};
var context = getdns.createContext(options);
var callback = function(err, result) {
if (err) {
console.error(err);
} else {
console.log(result.canonical_name, result.just_address_answers);
}
context.destroy();
};
var extensions = {
};
var transactionId = context.address("wikipedia.org", extensions, callback);
API usage
Most of the nodejs calls maps to the getdns API specification. If there are any differences, or questions about usage, please open an issue.
Context Cleanup
When a context object is garbage collected, the underlying resources are freed up. However, garbage collection is not guaranteed to trigger. The application will not exit until all contexts are destroyed.
Response format
A response to the callback is the javascript object representation of the getdns_dict
response dictionary.
Any bindata
objects are converted into Node.js buffers, or converted to strings when possible:
- Getdns IP address dictionary to IP string.
- Printable bindata.
- Wire format dname.
In the sample below buffers are represented as <Buffer length nnnn>
. Some lines have been removed; <Removed lines nnnn>
. Also see the output of the examples for reference.
{
"answer_type": 800,
"canonical_name": "getdnsapi.net.",
"just_address_answers": [
"2a04:b900:0:100::37",
"185.49.141.37"
],
"replies_full": [
"<Buffer length 677>",
"<Buffer length 677>"
],
"replies_tree": [
{
"additional": [
"<Removed lines 39>"
],
"answer": [
{
"class": 1,
"name": "getdnsapi.net.",
"rdata": {
"ipv6_address": "2a04:b900:0:100::37",
"rdata_raw": "<Buffer length 16>"
},
"ttl": 450,
"type": 28
},
{
"class": 1,
"name": "getdnsapi.net.",
"rdata": {
"algorithm": 7,
"key_tag": 32852,
"labels": 2,
"original_ttl": 450,
"rdata_raw": "<Buffer length 161>",
"signature": "<Buffer length 128>",
"signature_expiration": 1491862518,
"signature_inception": 1490027744,
"signers_name": "getdnsapi.net.",
"type_covered": 28
},
"ttl": 450,
"type": 46
}
],
"answer_type": 800,
"authority": [
"<Removed lines 48>"
],
"canonical_name": "getdnsapi.net.",
"dnssec_status": 400,
"header": {
"aa": 0,
"ad": 1,
"ancount": 2,
"arcount": 3,
"cd": 0,
"id": 0,
"nscount": 4,
"opcode": 0,
"qdcount": 1,
"qr": 1,
"ra": 1,
"rcode": 0,
"rd": 1,
"tc": 0,
"z": 0
},
"question": {
"qclass": 1,
"qname": "getdnsapi.net.",
"qtype": 28
}
},
{
"additional": [
"<Removed lines 69>"
],
"answer_type": 800,
"authority": [
"<Removed lines 48>"
],
"canonical_name": "getdnsapi.net.",
"dnssec_status": 400,
"header": {
"aa": 0,
"ad": 1,
"ancount": 2,
"arcount": 3,
"cd": 0,
"id": 0,
"nscount": 4,
"opcode": 0,
"qdcount": 1,
"qr": 1,
"ra": 1,
"rcode": 0,
"rd": 1,
"tc": 0,
"z": 0
},
"question": {
"qclass": 1,
"qname": "getdnsapi.net.",
"qtype": 1
}
}
],
"status": 900
}
Constants
All constants defined in <getdns/getdns.h>
and <getdns/getdns_extra.h>
are exposed in the module. The GETDNS_
prefix is removed. As an example, to get/filter out only secure replies, one may do something like:
var dnssecSecureReplies = result.replies_tree.filter(function(reply) {
return reply.dnssec_status === getdns.DNSSEC_SECURE;
});
Context functions
Most work is done in the async methods of a DNS context. Extensions are optional in the below method calls.
var context = getdns.createContext(options);
context.destroy();
context.cancel(transactionId);
var domainName = "subdomain.example.org";
var ipAddress = "111.222.33.44";
var ipAddress = "2620:0:862:ed1a::1";
var extensions = {
dnssec_return_only_secure: true
};
var request_type = getdns.RRTYPE_MX;
var request_type = getdns.RRTYPE_SSHFP;
function callback(err, result, transactionId) {
}
var transactionId = context.general(domainName, request_type, extensions, callback);
var transactionId = context.address(domainName, extensions, callback);
var transactionId = context.service(domainName, extensions, callback);
var transactionId = context.hostname(ipAddress, extensions, callback);
Context options
The below DNS context options are not complete; not all from the specification are listed, nor are all implemented in getdns-node. If there are any differences, or questions about usage, please open an issue.
getdns_context_set_timeout(context, 1000);
context.timeout = 1000;
context.resolution_type = getdns.RESOLUTION_RECURSING;
context.resolution_type = getdns.RESOLUTION_STUB;
context.upstream_recursive_servers = [
"8.8.8.8",
["127.0.0.1", 53],
];
context.follow_redirects = getdns.REDIRECTS_FOLLOW;
context.follow_redirects = getdns.REDIRECTS_DO_NOT_FOLLOW;
context.timeout = 1000;
context.use_threads = false;
context.return_dnssec_status = true;
context.dns_transport = getdns.TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
context.dns_transport_list = [
getdns.TRANSPORT_TLS,
getdns.TRANSPORT_TCP,
getdns.TRANSPORT_UDP
]
context.idle_timeout = ...;
context.edns_extended_rcode = 0;
context.edns_version = 0;
context.edns_do_bit = 0;
context.edns_maximum_udp_payloadSize = ...;
context.limit_outstanding_queries = ...;
context.namespaces = [
getdns.NAMESPACE_XXXX,
getdns.NAMESPACE_XXXX
];
Building and testing
- Development follows git-flow using the AVH edition of
git flow
. - Patches are welcome!
# Navigate to your getdns-node source folder.
# Enable git flow in your local clone.
git flow init -d
# Install dependencies, dev-dependencies, (re)build the package.
npm install
# If editing C++ code (and headers) in src/ either build (or rebuild) the module as necessary.
npm run --silent build
# Please add tests for any changes. More and diverse tests are better.
# See if there is a specific file matching your change, or create a new.
# NOTE: you can run tests per file.
npm run --silent test:run -- test/dnssec.js
# Run all tests against live DNS servers. The build server will also run these.
# NOTE: some tests may fail intermittently, depending on internet connection and upstream DNS servers. Rerun to verify.
npm run --silent test
# Now submit your pull request, and be ready for it to be scrutinized.
# Don't take comments nor change requests personally.
# Thank you in advance! =)
Note that the tests require an internet connection, getdns, and Unbound with a trust anchor to be installed to pass. Please consult the getdns documentation on the expected location of the trust anchor. Because of testing over the internet against live DNS servers, some tests may fail intermittently. If so, rerun to verify.
Contributors
See also getdns-node committers and getdns committers, contributors, and acknowledgements.
Want to be on this list? Fastest way is to fix a spelling mistake 😃
getdnsapi/getdns-node Copyright © 2014, 2015, 2016, 2017, 2018, Verisign, Inc. All rights reserved. Released under the BSD 3-clause License.