API Driven Dynamic DNS Server in Nodejs

Phil Dougherty
ContainerShip Articles
3 min readAug 31, 2015

--

Introduction to Quarry: A dynamic DNS server with swappable backends and CRUD API.

What is Quarry?

Quarry is a dynamic DNS server with swappable backends for persistence, and statsd integration, that can be run standalone as an executable, or used as a module in your node apps. When run in executable mode, Quarry provides a remote API for adding and updating DNS records and forwarders. When used as a module, records and forwarders are managed via exposed functions.

The ContainerShip service-discovery Plugin makes use of Quarry to automatically register DNS records for every application and container that gets launched on one of your server clusters, but it can be just as effective when used on its own.

Supported Persistence Layers

  • Disk
  • Memory
  • MongoDB
  • S3
  • Redis

Installation

Run the following command to install Quarry as an executable:

npm install -g quarry-dns

To use Quarry as a required module in your application, run the following in the root of your node app:

npm install quarry-dns --save 

We also provide a Docker image that you can use to run Quarry in executable mode.

docker pull containership/docker-quarry
docker run -d -p 5353:5353 -p 10053:53 containership/quarry memory

Executable Mode

Usage

quarry --help can be used for a comprehensive list of available commands and options. To run Quarry on a priviliged port such as 53, it must be start as root. Below are some usage examples:

Disk

sudo quarry disk --file-location /path/to/quarry/config.json

Memory

sudo quarry memory

MongoDB

sudo quarry mongo — mongo-host ds028017.mongolab.com

Redis

sudo quarry redis --redis-host \
quarry.abcdef.0001.use1.cache.amazonaws.com

S3

sudo quarry s3 --access-key-id $AWS_ACCESS_KEY_ID --secret-access-key $AWS_SECRET_ACCESS_KEY --bucket quarry

Examples

Get Records

curl http://quary.server:5353/v1/records -X GET -H “Content-Type: application/json”

Get Record

curl http://quary.server:5353/v1/records/www.domain.com -X GET -H “Content-Type: application/json”

Create Record

curl http://quary.server:5353/v1/records/www.domain.com -X POST -d ‘{“address”: “1.2.3.4”, “type”: “A”, “ttl”: 60}’ -H “Content-Type: application/json”

Update Record

curl http://quary.server:5353/v1/records/www.domain.com -X PUT -d ‘{“address”: [“1.2.3.4”, “5.6.7.8”], “type”: “A”, “ttl”: 60}’ -H “Content-Type: application/json”

Delete Record

curl http://quary.server:5353/v1/records/www.domain.com -X DELETE

Get Forwarders

curl http://quary.server:5353/v1/forwarders -X GET -H “Content-Type: application/json”

Get Forwarder

curl http://quary.server:5353/v1/forwarders/8.8.8.8 -X GET -H “Content-Type: application/json”

Create Forwarder

curl http://quary.server:5353/v1/forwarders/8.8.8.8 -X POST -d ‘{“timeout”: 500, “port”: 53}’ -H “Content-Type: application/json”

Update Forwarder

curl http://quary.server:5353/v1/forwarders/8.8.8.8 -X PUT -d ‘{“timeout”: 1000, “port”: 53}’ -H “Content-Type: application/json”

Delete Forwarder

curl http://quary.server:5353/v1/forwarders/8.8.8.8 -X DELETE

Module Mode

Usage

var Quarry = require("quarry-dns");
var quarry = new Quarry({
persistence: "memory"
});
if(quarry){
quarry.listen(function(){
console.log("quarry is now listening");
});
}

Disk

var quarry = new Quarry({
persistence: "disk",
"file-location": "/tmp/quarry.json"
});

Memory

var quarry = new Quarry({
persistence: "memory"
});

MongoDB

var quarry = new Quarry({
persistence: "mongo",
"mongo-host": "ds028017.mongolab.com"
});

Redis

var quarry = new Quarry({
persistence: "redis",
"redis-host": "quarry.abcdef.0001.use1.cache.amazonaws.com"
});

S3

var quarry = new Quarry({
persistence: "s3",
"access-key-id": process.env["AWS_ACCESS_KEY_ID"],
"secret-access-key": process.env["AWS_SECRET_ACCESS_KEY"],
bucket: "quarry"
});

Examples

Get Records

quarry.persistence.get_configuration(function(err, configuration){
if(err)
throw err;
var records = configuration.records;
});

Get Record

quarry.persistence.get_configuration(function(err, configuration){
if(err)
throw err;
var record = configuration.records["www.domain.com"];
});

Create Record

quarry.persistence.create_record("www.domain.com", { address: "1.2.3.4", type: "A", ttl: 60 }, function(err){
if(err)
throw err;
});

Update Record

quarry.persistence.update_record("www.domain.com", { address: ["1.2.3.4", "5.6.7.8"], type: "A", ttl: 60 }, function(err){
if(err)
throw err;
});

Delete Record

quarry.persistence.delete_record("www.domain.com", function(err){
if(err)
throw err;
});

Get Forwarders

quarry.persistence.get_configuration(function(err, configuration){
if(err)
throw err;
var forwarders = configuration.forwarders;
});

Get Forwarder

quarry.persistence.get_configuration(function(err, configuration){
if(err)
throw err;
var forwarder = configuration.forwarders["8.8.8.8"];
});

Create Forwarder

quarry.persistence.create_forwarder("8.8.8.8", { timeout: 500, port: 53 }, function(err){
if(err)
throw err;
});

Update Forwarder

quarry.persistence.update_forwarder("8.8.8.8", { timeout: 1000, port: 53 }, function(err){
if(err)
throw err;
});

Delete Forwarder

quarry.persistence.delete_forwarder("8.8.8.8", function(err){
if(err)
throw err;
});

Find Out More

https://github.com/containership/

--

--

Phil Dougherty
ContainerShip Articles

Co-Founder @containershipio, Husband, Systems Engineer, Manager, Pittsburgher, Pitbull lover.