Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node: accept --no-dns configuration option to disable NS and RS #554

Merged
merged 1 commit into from Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 .'}
);
});
});
});