Skip to content

Commit

Permalink
node: accept --no-dns and --no-rs configuration option to disable NS …
Browse files Browse the repository at this point in the history
…and RS
  • Loading branch information
pinheadmz committed Mar 23, 2021
1 parent 33be3ad commit 7660280
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 44 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,15 @@
- Root server DNSSEC has been fixed. It is only authoritative over DS and TXT records,
and only returns TXT if no NS (referral) is present in the zone.

### Node changes

- `FullNode` and `SPVNode` accept configuration parameter `--no-dns` (or `no-dns: true` in
`hsd.conf`) which launches the node without either DNS server (the root authoritative
server and the recursive resolver). This avoids some port collisions with other HNS resolvers
like hnsd running locally, and generally separates and reduces security concerns around
running unneeded servers when a node is just used for transactions and blocks.
`--no-rs` is also accepted to disable the recursive DNS resolver (but keep the root server).

### Wallet API changes

- Adds new wallet HTTP endpoint `/wallet/:id/auction` based on `POST /wallet/:id/bid`.
Expand Down
57 changes: 35 additions & 22 deletions lib/node/fullnode.js
Expand Up @@ -147,24 +147,28 @@ class FullNode extends Node {
cors: this.config.bool('cors')
});

this.ns = new RootServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('ns-host'),
port: this.config.uint('ns-port', this.network.nsPort),
lookup: key => this.chain.db.tree.get(key),
publicHost: this.config.str('public-host')
});

this.rs = new RecursiveServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('rs-host'),
port: this.config.uint('rs-port', this.network.rsPort),
stubHost: this.ns.host,
stubPort: this.ns.port,
noUnbound: this.config.bool('rs-no-unbound')
});
if (!this.config.bool('no-dns')) {
this.ns = new RootServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('ns-host'),
port: this.config.uint('ns-port', this.network.nsPort),
lookup: key => this.chain.db.tree.get(key),
publicHost: this.config.str('public-host')
});

if (!this.config.bool('no-rs')) {
this.rs = new RecursiveServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('rs-host'),
port: this.config.uint('rs-port', this.network.rsPort),
stubHost: this.ns.host,
stubPort: this.ns.port,
noUnbound: this.config.bool('rs-no-unbound')
});
}
}

this.init();
}
Expand Down Expand Up @@ -259,8 +263,13 @@ class FullNode extends Node {
await this.openPlugins();

await this.http.open();
await this.ns.open();
await this.rs.open();

if (this.ns)
await this.ns.open();

if (this.rs)
await this.rs.open();

await this.handleOpen();

if (this.has('walletdb')) {
Expand All @@ -286,8 +295,12 @@ class FullNode extends Node {

await this.handlePreclose();
await this.http.close();
await this.rs.close();
await this.ns.close();

if (this.rs)
await this.rs.close();

if (this.ns)
await this.ns.close();

await this.closePlugins();

Expand Down
57 changes: 35 additions & 22 deletions lib/node/spvnode.js
Expand Up @@ -93,24 +93,28 @@ class SPVNode extends Node {
cors: this.config.bool('cors')
});

this.ns = new RootServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('ns-host'),
port: this.config.uint('ns-port', this.network.nsPort),
lookup: key => this.pool.resolve(key),
publicHost: this.config.str('public-host')
});

this.rs = new RecursiveServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('rs-host'),
port: this.config.uint('rs-port', this.network.rsPort),
stubHost: this.ns.host,
stubPort: this.ns.port,
noUnbound: this.config.bool('rs-no-unbound')
});
if (!this.config.bool('no-dns')) {
this.ns = new RootServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('ns-host'),
port: this.config.uint('ns-port', this.network.nsPort),
lookup: key => this.pool.resolve(key),
publicHost: this.config.str('public-host')
});

if (!this.config.bool('no-rs')) {
this.rs = new RecursiveServer({
logger: this.logger,
key: this.identityKey,
host: this.config.str('rs-host'),
port: this.config.uint('rs-port', this.network.rsPort),
stubHost: this.ns.host,
stubPort: this.ns.port,
noUnbound: this.config.bool('rs-no-unbound')
});
}
}

this.init();
}
Expand Down Expand Up @@ -172,8 +176,13 @@ class SPVNode extends Node {
await this.openPlugins();

await this.http.open();
await this.ns.open();
await this.rs.open();

if (this.ns)
await this.ns.open();

if (this.rs)
await this.rs.open();

await this.handleOpen();

this.logger.info('Node is loaded.');
Expand All @@ -190,8 +199,12 @@ class SPVNode extends Node {

await this.handlePreclose();
await this.http.close();
await this.rs.close();
await this.ns.close();

if (this.rs)
await this.rs.close();

if (this.ns)
await this.ns.close();

await this.closePlugins();

Expand Down
129 changes: 129 additions & 0 deletions test/dns-test.js
@@ -0,0 +1,129 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */

'use strict';

const assert = require('bsert');
const Network = require('../lib/protocol/network');
const FullNode = require('../lib/node/fullnode');
const SPVNode = require('../lib/node/spvnode');
const network = Network.get('regtest');

const {Resolver} = require('dns').promises;

const rootResolver = new Resolver({timeout: 1000});
const recursiveResolver = new Resolver({timeout: 1000});
rootResolver.setServers([`127.0.0.1:${network.nsPort}`]);
recursiveResolver.setServers([`127.0.0.1:${network.rsPort}`]);

describe('Server Configuration', function() {
describe('Full Node', function() {
let node;

afterEach(async () => {
await node.close();
});

it('should open full node with both DNS servers', async () => {
node = new FullNode({
memory: true,
network: network.type
});

await node.open();
const res1 = await rootResolver.resolveSoa('.');
assert(res1);
const res2 = await recursiveResolver.resolveSoa('.');
assert(res2);
});

it('should open full node with neither DNS server', async () => {
node = new FullNode({
memory: true,
network: network.type,
noDns: true
});

await node.open();
await assert.rejects(
rootResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
await assert.rejects(
recursiveResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
});

it('should open full node only with root name server', async () => {
node = new FullNode({
memory: true,
network: network.type,
noRs: true
});

await node.open();
const res1 = await rootResolver.resolveSoa('.');
assert(res1);
await assert.rejects(
recursiveResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
});
});

describe('SPV Node', function() {
let node;

afterEach(async () => {
await node.close();
});

it('should open SPV node with both DNS servers', async () => {
node = new SPVNode({
memory: true,
network: network.type
});

await node.open();
const res1 = await rootResolver.resolveSoa('.');
assert(res1);
const res2 = await recursiveResolver.resolveSoa('.');
assert(res2);
});

it('should open SPV node with neither DNS server', async () => {
node = new SPVNode({
memory: true,
network: network.type,
noDns: true
});

await node.open();
await assert.rejects(
rootResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
await assert.rejects(
recursiveResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
});

it('should open SPV node only with root name server', async () => {
node = new SPVNode({
memory: true,
network: network.type,
noRs: true
});

await node.open();
const res1 = await rootResolver.resolveSoa('.');
assert(res1);
await assert.rejects(
recursiveResolver.resolveSoa('.'),
{message: 'querySoa ECONNREFUSED .'}
);
});
});
});

0 comments on commit 7660280

Please sign in to comment.