mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-16 12:06:55 +02:00
Doc updates and other fixes.
This commit is contained in:
parent
9bab49d2f9
commit
a1992d76f2
4 changed files with 51 additions and 45 deletions
|
@ -41,7 +41,7 @@ void DB::initNetwork(nlohmann::json &network)
|
|||
if (!network.count("tags")) network["tags"] = nlohmann::json::array();
|
||||
if (!network.count("routes")) network["routes"] = nlohmann::json::array();
|
||||
if (!network.count("ipAssignmentPools")) network["ipAssignmentPools"] = nlohmann::json::array();
|
||||
if (!network.count("anchors")) network["anchors"] = nlohmann::json::array();
|
||||
//if (!network.count("anchors")) network["anchors"] = nlohmann::json::array();
|
||||
if (!network.count("mtu")) network["mtu"] = ZT_DEFAULT_MTU;
|
||||
if (!network.count("remoteTraceTarget")) network["remoteTraceTarget"] = nlohmann::json();
|
||||
if (!network.count("removeTraceLevel")) network["remoteTraceLevel"] = 0;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
using json = nlohmann::json;
|
||||
|
||||
// API version reported via JSON control plane
|
||||
#define ZT_NETCONF_CONTROLLER_API_VERSION 3
|
||||
#define ZT_NETCONF_CONTROLLER_API_VERSION 4
|
||||
|
||||
// Min duration between requests for an address/nwid combo to prevent floods
|
||||
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
|
||||
|
|
|
@ -75,25 +75,32 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record)
|
|||
{
|
||||
char p1[4096],p2[4096],pb[4096];
|
||||
try {
|
||||
nlohmann::json rec(record);
|
||||
const std::string objtype = rec["objtype"];
|
||||
if (orig) {
|
||||
if (*orig != record) {
|
||||
record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1;
|
||||
}
|
||||
} else {
|
||||
record["revision"] = 1;
|
||||
}
|
||||
|
||||
const std::string objtype = record["objtype"];
|
||||
if (objtype == "network") {
|
||||
const uint64_t nwid = OSUtils::jsonIntHex(rec["id"],0ULL);
|
||||
const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
|
||||
if (nwid) {
|
||||
nlohmann::json old;
|
||||
get(nwid,old);
|
||||
|
||||
OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json.new",_networksPath.c_str(),nwid);
|
||||
OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid);
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(rec,-1)))
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
|
||||
fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
|
||||
OSUtils::rename(p1,p2);
|
||||
|
||||
_networkChanged(old,rec,true);
|
||||
_networkChanged(old,record,true);
|
||||
}
|
||||
} else if (objtype == "member") {
|
||||
const uint64_t id = OSUtils::jsonIntHex(rec["id"],0ULL);
|
||||
const uint64_t nwid = OSUtils::jsonIntHex(rec["nwid"],0ULL);
|
||||
const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
|
||||
const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
|
||||
if ((id)&&(nwid)) {
|
||||
nlohmann::json network,old;
|
||||
get(nwid,network,id,old);
|
||||
|
@ -101,20 +108,20 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record)
|
|||
OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid);
|
||||
OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json.new",pb,(unsigned long long)id);
|
||||
OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id);
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(rec,-1))) {
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
|
||||
OSUtils::mkdir(pb);
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(rec,-1)))
|
||||
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
|
||||
fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
|
||||
}
|
||||
OSUtils::rename(p1,p2);
|
||||
|
||||
_memberChanged(old,rec,true);
|
||||
_memberChanged(old,record,true);
|
||||
}
|
||||
} else if (objtype == "trace") {
|
||||
const std::string id = rec["id"];
|
||||
const std::string id = record["id"];
|
||||
if (id.length() > 0) {
|
||||
OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "trace" ZT_PATH_SEPARATOR_S "%s.json",_path.c_str(),id.c_str());
|
||||
OSUtils::writeFile(p1,OSUtils::jsonDump(rec,-1));
|
||||
OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1));
|
||||
}
|
||||
}
|
||||
} catch ( ... ) {} // drop invalid records missing fields
|
||||
|
|
|
@ -1,12 +1,28 @@
|
|||
Network Controller Microservice
|
||||
======
|
||||
|
||||
Every ZeroTier virtual network has a *network controller*. This is our reference controller implementation and is the same one we use to power our own hosted services at [my.zerotier.com](https://my.zerotier.com/). Network controllers act as configuration servers and certificate authorities for the members of networks. Controllers are located on the network by simply parsing out the first 10 digits of a network's 16-digit network ID: these are the address of the controller.
|
||||
Every ZeroTier virtual network has a *network controller* responsible for admitting members to the network, issuing certificates, and issuing default configuration information.
|
||||
|
||||
As of ZeroTier One version 1.2.0 this code is included in normal builds for desktop, laptop, and server (Linux, etc.) targets, allowing any device to create virtual networks without having to be rebuilt from source with special flags to enable this feature. While this does offer a convenient way to create ad-hoc networks or experiment, we recommend running a dedicated controller somewhere secure and stable for any "serious" use case.
|
||||
This is our reference controller implementation and is the same one we use to power our own hosted services at [my.zerotier.com](https://my.zerotier.com/). As of ZeroTier One version 1.2.0 this code is included in normal builds for desktop, laptop, and server (Linux, etc.) targets.
|
||||
|
||||
Controller data is stored in JSON format under `controller.d` in the ZeroTier working directory. It can be copied, rsync'd, placed in `git`, etc. The files under `controller.d` should not be modified in place while the controller is running or data loss may result, and if they are edited directly take care not to save corrupt JSON since that can also lead to data loss when the controller is restarted. Going through the API is strongly preferred to directly modifying these files.
|
||||
|
||||
See the API section below for information about controlling the controller.
|
||||
|
||||
### Scalability and Reliability
|
||||
|
||||
Controllers can in theory host up to 2^24 networks and serve many millions of devices (or more), but we recommend spreading large numbers of networks across many controllers for load balancing and fault tolerance reasons. Since the controller uses the filesystem as its data store we recommend fast filesystems and fast SSD drives for heavily loaded controllers.
|
||||
|
||||
Since ZeroTier nodes are mobile and do not need static IPs, implementing high availability fail-over for controllers is easy. Just replicate their working directories from master to backup and have something automatically fire up the backup if the master goes down. Modern orchestration tools like Nomad and Kubernetes can be of help here.
|
||||
|
||||
### Dockerizing Controllers
|
||||
|
||||
ZeroTier network controllers can easily be run in Docker or other container systems. Since containers do not need to actually join networks, extra privilege options like "--device=/dev/net/tun --privileged" are not needed. You'll just need to map the local JSON API port of the running controller and allow it to access the Internet (over UDP/9993 at a minimum) so things can reach and query it.
|
||||
|
||||
### RethinkDB Database Implementation
|
||||
|
||||
The default controller stores its data in the filesystem in `controller.d` under ZeroTier's home folder. There's an alternative implementation that stores data in RethinkDB that can be built with `make central-controller`. Right now this is only guaranteed to build and run on Linux and is designed for use with [ZeroTier Central](https://my.zerotier.com/). You're welcome to use it but we don't "officially" support it for end-user use and it could change at any time.
|
||||
|
||||
### Upgrading from Older (1.1.14 or earlier) Versions
|
||||
|
||||
Older versions of this code used a SQLite database instead of in-filesystem JSON. A migration utility called `migrate-sqlite` is included here and *must* be used to migrate this data to the new format. If the controller is started with an old `controller.db` in its working directory it will terminate after printing an error to *stderr*. This is done to prevent "surprises" for those running DIY controllers using the old code.
|
||||
|
@ -17,33 +33,15 @@ The migration tool is written in nodeJS and can be used like this:
|
|||
npm install
|
||||
node migrate.js </path/to/controller.db> </path/to/controller.d>
|
||||
|
||||
Very old versions of nodeJS may have issues. We tested it with version 7.
|
||||
|
||||
### Scalability and Reliability
|
||||
|
||||
Controllers can in theory host up to 2^24 networks and serve many millions of devices (or more), but we recommend spreading large numbers of networks across many controllers for load balancing and fault tolerance reasons. Since the controller uses the filesystem as its data store we recommend fast filesystems and fast SSD drives for heavily loaded controllers.
|
||||
|
||||
Since ZeroTier nodes are mobile and do not need static IPs, implementing high availability fail-over for controllers is easy. Just replicate their working directories from master to backup and have something automatically fire up the backup if the master goes down. Many modern orchestration tools have built-in support for this. It would also be possible in theory to run controllers on a replicated or distributed filesystem, but we haven't tested this yet.
|
||||
|
||||
### Dockerizing Controllers
|
||||
|
||||
ZeroTier network controllers can easily be run in Docker or other container systems. Since containers do not need to actually join networks, extra privilege options like "--device=/dev/net/tun --privileged" are not needed. You'll just need to map the local JSON API port of the running controller and allow it to access the Internet (over UDP/9993 at a minimum) so things can reach and query it.
|
||||
|
||||
### About the RethinkDB Connector
|
||||
|
||||
The default controller stores its data in the filesystem. There is also a direct RethinkDB connector that can be built on Linux with `make central-controller`.
|
||||
|
||||
This is designed for use with ZeroTier Central. You are free to build it and use it but don't be surprised if it changes without warning. It shouldn't be considered stable for external use.
|
||||
|
||||
### Network Controller API
|
||||
|
||||
The controller API is hosted via the same JSON API endpoint that ZeroTier One uses for local control (usually at 127.0.0.1 port 9993). All controller options are routed under the `/controller` base path.
|
||||
|
||||
The controller microservice does not implement any fine-grained access control (authentication is via authtoken.secret, simply append the value from authtoken.secret file, into a new querystring parameter named "auth" - for example `/controller/network?auth=6hdmozf8k5ds39kabcdefabc`) or other complex mangement features. It just takes network and network member configurations and reponds to controller queries. We have an enterprise product called [ZeroTier Central](https://my.zerotier.com/) that we host as a service (and that companies can license to self-host) that does this.
|
||||
The controller microservice itself does not implement any fine-grained access control. Access control is via the ZeroTier control interface itself and `authtoken.secret`. This can be sent as the `X-ZT1-Auth` HTTP header field or appended to the URL as `?auth=<token>`. Take care when doing the latter that request URLs are not being logged.
|
||||
|
||||
All working network IDs on a controller must begin with the controller's ZeroTier address. The API will *allow* "foreign" networks to be added but the controller will have no way of doing anything with them since nobody will know to query it. (In the future we might support secondaries, which would make this relevant.)
|
||||
While networks with any valid ID can be added to the controller's database, it will only actually work to control networks whose first 10 hex digits correspond with the network controller's ZeroTier ID. See [section 2.2.1 of the ZeroTier manual](https://zerotier.com/manual.shtml#2_2_1).
|
||||
|
||||
The JSON API is *very* sensitive about types. Integers must be integers and strings strings, etc. Incorrectly typed and unrecognized fields may result in ignored fields or a 400 (bad request) error.
|
||||
The controller JSON API is *very* sensitive about types. Integers must be integers and strings strings, etc. Incorrect types may be ignored, set to default values, or set to undefined values.
|
||||
|
||||
#### `/controller`
|
||||
|
||||
|
@ -84,30 +82,31 @@ Example:
|
|||
| Field | Type | Description | Writable |
|
||||
| --------------------- | ------------- | ------------------------------------------------- | -------- |
|
||||
| id | string | 16-digit network ID | no |
|
||||
| nwid | string | 16-digit network ID (old, but still around) | no |
|
||||
| nwid | string | 16-digit network ID (legacy) | no |
|
||||
| objtype | string | Always "network" | no |
|
||||
| name | string | A short name for this network | YES |
|
||||
| creationTime | integer | Time network record was created (ms since epoch) | no |
|
||||
| private | boolean | Is access control enabled? | YES |
|
||||
| enableBroadcast | boolean | Ethernet ff:ff:ff:ff:ff:ff allowed? | YES |
|
||||
| allowPassiveBridging | boolean | Allow any member to bridge (very experimental) | YES |
|
||||
| v4AssignMode | object | IPv4 management and assign options (see below) | YES |
|
||||
| v6AssignMode | object | IPv6 management and assign options (see below) | YES |
|
||||
| mtu | integer | Network MTU (default: 2800) | YES |
|
||||
| multicastLimit | integer | Maximum recipients for a multicast packet | YES |
|
||||
| creationTime | integer | Time network was first created | no |
|
||||
| revision | integer | Network config revision counter | no |
|
||||
| routes | array[object] | Managed IPv4 and IPv6 routes; see below | YES |
|
||||
| ipAssignmentPools | array[object] | IP auto-assign ranges; see below | YES |
|
||||
| rules | array[object] | Traffic rules; see below | YES |
|
||||
|
||||
Recent changes:
|
||||
|
||||
* The `ipLocalRoutes` field appeared in older versions but is no longer present. Routes will now show up in `routes`.
|
||||
* The `relays` field is gone since network preferred relays are gone. This capability is replaced by VL1 level federation ("federated roots").
|
||||
|
||||
Other important points:
|
||||
| capabilities | array[object] | Array of capability objects (see below) | YES |
|
||||
| tags | array[object] | Array of tag objects (see below) | YES |
|
||||
| remoteTraceTarget | string | 10-digit ZeroTier ID of remote trace target | YES |
|
||||
| remoteTraceLevel | integer | Remote trace verbosity level | YES |
|
||||
|
||||
* Networks without rules won't carry any traffic. If you don't specify any on network creation an "accept anything" rule set will automatically be added.
|
||||
* Managed IP address assignments and IP assignment pools that do not fall within a route configured in `routes` are ignored and won't be used or sent to members.
|
||||
* The default for `private` is `true` and this is probably what you want. Turning `private` off means *anyone* can join your network with only its 16-digit network ID. It's also impossible to de-authorize a member as these networks don't issue or enforce certificates. Such "party line" networks are used for decentralized app backplanes, gaming, and testing but are otherwise not common.
|
||||
* Changing the MTU can be disruptive and on some operating systems may require a leave/rejoin of the network or a restart of the ZeroTier service.
|
||||
|
||||
**Auto-Assign Modes:**
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue