updated the documentation and validation for DDNS settings

This commit is contained in:
tigerbot 2017-10-18 12:06:01 -06:00
parent cfaa8d4959
commit 6b2b91ba26
4 changed files with 98 additions and 21 deletions

View File

@ -403,17 +403,50 @@ tunnel_server:
- 'api.tunnel.example.com' - 'api.tunnel.example.com'
``` ```
### tunnel ### DDNS
The tunnel client is meant to be run from behind a firewalls, carrier-grade NAT, The DDNS module watches the network environment of the unit and makes sure the
or otherwise inaccessible devices to allow them to be accessed publicly on the device is always accessible on the internet using the domains listed in the
internet. config. If the device has a public address or if it can automatically set up
port forwarding the device will periodically check its public address to ensure
the DNS records always point to it. Otherwise it will to connect to a tunnel
server and set the DNS records to point to that server.
### ddns The `loopback` setting specifies how the unit will check its public IP address
and whether connections can reach it. Currently only `tunnel@oauth3.org` is
supported. If the loopback setting is not defined it will default to using
`oauth3.org`.
TODO The `tunnel` setting can be used to specify how to connect to the tunnel.
Currently only `tunnel@oauth3.org` is supported. The token specified in the
`tunnel` setting will be used to acquire the tokens that are used directly with
the tunnel server. If the tunnel setting is not defined it will default to try
using the tokens in the modules for the relevant domains.
### mdns If a particular DDNS module has been disabled the device will still try to set
up port forwarding (and connect to a tunnel if that doesn't work), but the DNS
records will not be updated to point to the device. This is to allow a setup to
be tested before transitioning services between devices.
```yaml
ddns:
disabled: false
loopback:
type: 'tunnel@oauth3.org'
domain: oauth3.org
tunnel:
type: 'tunnel@oauth3.org'
token: user_token_id
modules:
- type: 'dns@oauth3.org'
token: user_token_id
domains:
- www.example.com
- api.example.com
- test.example.com
```
### mDNS
enabled by default enabled by default

View File

@ -311,7 +311,6 @@ function fillConfig(config, args) {
config.debug = config.debug || args.debug; config.debug = config.debug || args.debug;
config.socks5 = config.socks5 || { enabled: false }; config.socks5 = config.socks5 || { enabled: false };
config.ddns = config.ddns || { enabled: false };
// Use Object.assign to copy any real config values over the default values so we can // Use Object.assign to copy any real config values over the default values so we can
// easily make sure all the fields we need exist . // easily make sure all the fields we need exist .
@ -338,6 +337,7 @@ function fillConfig(config, args) {
fillComponent('tcp', true); fillComponent('tcp', true);
fillComponent('http', false); fillComponent('http', false);
fillComponent('tls', false); fillComponent('tls', false);
fillComponent('ddns', false);
config.device = { hostname: require('os').hostname() }; config.device = { hostname: require('os').hostname() };

View File

@ -91,8 +91,16 @@ tunnel_server:
- 'tunnel.localhost.com' - 'tunnel.localhost.com'
ddns: ddns:
enabled: true loopback:
domains: type: 'tunnel@oauth3.org'
- www.example.com domain: oauth3.org
- api.example.com tunnel:
- test.example.com type: 'tunnel@oauth3.org'
token: user_token_id
modules:
- type: 'dns@oauth3.org'
token: user_token_id
domains:
- www.example.com
- api.example.com
- test.example.com

View File

@ -48,6 +48,16 @@ var moduleSchemas = {
, challenge_type: { type: 'string' } , challenge_type: { type: 'string' }
} }
} }
// the dns control modules for DDNS
, dns_oauth3_org: {
name: 'dns@oauth3.org'
, type: 'object'
, required: [ 'token' ]
, properties: {
token: { type: 'string' }
}
}
}; };
// forward is basically the same as proxy, but specifies the relevant incoming port(s). // forward is basically the same as proxy, but specifies the relevant incoming port(s).
// only allows for the raw transport layers (TCP/UDP) // only allows for the raw transport layers (TCP/UDP)
@ -57,6 +67,10 @@ moduleSchemas.forward.properties.ports = { type: 'array', items: portSchema };
Object.keys(moduleSchemas).forEach(function (name) { Object.keys(moduleSchemas).forEach(function (name) {
var schema = moduleSchemas[name]; var schema = moduleSchemas[name];
if (schema.name) {
name = schema.name;
delete schema.name;
}
schema.id = '/modules/'+name; schema.id = '/modules/'+name;
schema.required = ['id', 'type'].concat(schema.required || []); schema.required = ['id', 'type'].concat(schema.required || []);
schema.properties.id = { type: 'string' }; schema.properties.id = { type: 'string' };
@ -72,12 +86,13 @@ var moduleRefs = {
, tls: [ 'proxy', 'acme' ].map(toSchemaRef) , tls: [ 'proxy', 'acme' ].map(toSchemaRef)
, tcp: [ 'forward' ].map(toSchemaRef) , tcp: [ 'forward' ].map(toSchemaRef)
, udp: [ 'forward' ].map(toSchemaRef) , udp: [ 'forward' ].map(toSchemaRef)
, ddns: [ 'dns@oauth3.org' ].map(toSchemaRef)
}; };
function addDomainRequirement(itemSchema) { function addDomainRequirement(itemSchema) {
itemSchema.required = (itemSchema.required || []).concat('domains'); itemSchema.required = (itemSchema.required || []).concat('domains');
itemSchema.properties = itemSchema.properties || {}; itemSchema.properties = itemSchema.properties || {};
itemSchema.domains = { type: 'array', items: { type: 'string' }, minLength: 1}; itemSchema.properties.domains = { type: 'array', items: { type: 'string' }, minLength: 1};
return itemSchema; return itemSchema;
} }
@ -93,6 +108,7 @@ var domainSchema = {
, properties: { , properties: {
tls: { type: 'array', items: { oneOf: moduleRefs.tls }} tls: { type: 'array', items: { oneOf: moduleRefs.tls }}
, http: { type: 'array', items: { oneOf: moduleRefs.http }} , http: { type: 'array', items: { oneOf: moduleRefs.http }}
, ddns: { type: 'array', items: { oneOf: moduleRefs.ddns }}
} }
, additionalProperties: false , additionalProperties: false
} }
@ -158,7 +174,23 @@ var mdnsSchema = {
var ddnsSchema = { var ddnsSchema = {
type: 'object' type: 'object'
, properties: { , properties: {
enabled: { type: 'boolean' } loopback: {
type: 'object'
, required: [ 'type', 'domain' ]
, properties: {
type: { type: 'string', const: 'tunnel@oauth3.org' }
, domain: { type: 'string'}
}
}
, tunnel: {
type: 'object'
, required: [ 'type', 'token' ]
, properties: {
type: { type: 'string', const: 'tunnel@oauth3.org' }
, token: { type: 'string'}
}
}
, modules: { type: 'array', items: { oneOf: moduleRefs.ddns }}
} }
}; };
var socks5Schema = { var socks5Schema = {
@ -265,6 +297,7 @@ class DomainList extends IdList {
dom.modules = { dom.modules = {
http: new ModuleList((dom.modules || {}).http) http: new ModuleList((dom.modules || {}).http)
, tls: new ModuleList((dom.modules || {}).tls) , tls: new ModuleList((dom.modules || {}).tls)
, ddns: new ModuleList((dom.modules || {}).ddns)
}; };
}); });
} }
@ -280,14 +313,16 @@ class DomainList extends IdList {
var modLists = { var modLists = {
http: new ModuleList() http: new ModuleList()
, tls: new ModuleList() , tls: new ModuleList()
, ddns: new ModuleList()
}; };
// We add these after instead of in the constructor to run the validation and manipulation // We add these after instead of in the constructor to run the validation and manipulation
// in the ModList add function since these are all new modules. // in the ModList add function since these are all new modules.
if (dom.modules && Array.isArray(dom.modules.http)) { if (dom.modules) {
dom.modules.http.forEach(modLists.http.add, modLists.http); Object.keys(modLists).forEach(function (key) {
} if (Array.isArray(dom.modules[key])) {
if (dom.modules && Array.isArray(dom.modules.tls)) { dom.modules[key].forEach(modLists[key].add, modLists[key]);
dom.modules.tls.forEach(modLists.tls.add, modLists.tls); }
});
} }
dom.id = require('crypto').randomBytes(4).toString('hex'); dom.id = require('crypto').randomBytes(4).toString('hex');
@ -306,6 +341,7 @@ class ConfigChanger {
this.tls.modules = new ModuleList(this.tls.modules); this.tls.modules = new ModuleList(this.tls.modules);
this.tcp.modules = new ModuleList(this.tcp.modules); this.tcp.modules = new ModuleList(this.tcp.modules);
this.udp.modules = new ModuleList(this.udp.modules); this.udp.modules = new ModuleList(this.udp.modules);
this.ddns.modules = new ModuleList(this.ddns.modules);
} }
update(update) { update(update) {
@ -314,7 +350,7 @@ class ConfigChanger {
if (update.domains) { if (update.domains) {
update.domains.forEach(self.domains.add, self.domains); update.domains.forEach(self.domains.add, self.domains);
} }
[ 'http', 'tls', 'tcp', 'udp' ].forEach(function (name) { [ 'http', 'tls', 'tcp', 'udp', 'ddns' ].forEach(function (name) {
if (update[name] && update[name].modules) { if (update[name] && update[name].modules) {
update[name].modules.forEach(self[name].modules.add, self[name].modules); update[name].modules.forEach(self[name].modules.add, self[name].modules);
delete update[name].modules; delete update[name].modules;