ZeroTier Backend
The ZeroTier
backend generates JSON configurations that can be used
with the ZeroTier Service API
to manage ZeroTier networks on Self-hosted ZeroTier controllers.
Its schema is limited to a subset of the features available in ZeroTier and it doesn’t recognize interfaces, radios, wireless settings and so on.
The main methods work just like the OpenWrt backend:
__init__
render
generate
write
json
The main differences are in the resulting configuration and in its schema.
See an example of initialization and rendering below:
from netjsonconfig import ZeroTier
config = ZeroTier(
{
"zerotier": [
{
"id": "9536600adf654321",
"nwid": "9536600adf654321",
"objtype": "network",
"revision": 1,
"creationTime": 1632012345,
"name": "zerotier-openwisp-network",
"private": True,
"enableBroadcast": True,
"v4AssignMode": {"zt": True},
"v6AssignMode": {
"6plane": False,
"rfc4193": True,
"zt": True,
},
"mtu": 2700,
"multicastLimit": 16,
"routes": [{"target": "10.0.0.0/24", "via": "10.0.0.1"}],
"ipAssignmentPools": [
{
"ipRangeStart": "10.0.0.10",
"ipRangeEnd": "10.0.0.100",
}
],
"dns": {
"domain": "zerotier.openwisp.io",
"servers": ["10.147.20.3"],
},
"rules": [
{
"etherType": 2048,
"not": True,
"or": False,
"type": "MATCH_ETHERTYPE",
},
{"type": "ACTION_DROP"},
],
"capabilities": [
{
"default": True,
"id": 1,
"rules": [
{
"etherType": 2048,
"not": True,
"or": False,
"type": "MATCH_ETHERTYPE",
}
],
}
],
"tags": [{"default": 1, "id": 1}],
"remoteTraceTarget": "7f5d90eb87",
"remoteTraceLevel": 1,
"client_options": {
"allow_managed": True,
"allowed_global": False,
"allowed_default": False,
"allowed_dns": False,
},
}
]
}
)
print(config.render())
Will return the following output:
// zerotier controller config: 9536600adf654321.json
{
"capabilities": [
{
"default": true,
"id": 1,
"rules": [
{
"etherType": 2048,
"not": true,
"or": false,
"type": "MATCH_ETHERTYPE"
}
]
}
],
"creationTime": 1632012345,
"dns": {
"domain": "zerotier.openwisp.io",
"servers": [
"10.147.20.3"
]
},
"enableBroadcast": true,
"id": "9536600adf654321",
"ipAssignmentPools": [
{
"ipRangeEnd": "10.0.0.100",
"ipRangeStart": "10.0.0.10"
}
],
"mtu": 2700,
"multicastLimit": 16,
"name": "zerotier-openwisp-network",
"nwid": "9536600adf654321",
"objtype": "network",
"private": true,
"remoteTraceLevel": 1,
"remoteTraceTarget": "7f5d90eb87",
"revision": 1,
"routes": [
{
"target": "10.0.0.0/24",
"via": "10.0.0.1"
}
],
"rules": [
{
"etherType": 2048,
"not": true,
"or": false,
"type": "MATCH_ETHERTYPE"
},
{
"type": "ACTION_DROP"
}
],
"tags": [
{
"default": 1,
"id": 1
}
],
"v4AssignMode": {
"zt": true
},
"v6AssignMode": {
"6plane": false,
"rfc4193": true,
"zt": true
}
}
ZeroTier backend schema
The ZeroTier
backend schema is limited, it only recognizes an
zerotier
key with a list of dictionaries representing vpn instances.
The structure of these dictionaries is described below.
Alternatively you may also want to take a look at the ZeroTier JSON-Schema source code.
According to the NetJSON spec, any unrecognized property will be ignored.
Server specific settings
Required properties:
name
key name |
type |
default |
description |
|||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
string |
name of the network |
||||||||||||||||
|
string |
16-digit hexadecimal Network ID |
||||||||||||||||
|
string |
16-digit hexadecimal Network ID (legacy field) |
||||||||||||||||
|
string |
|
specifies the type of object |
|||||||||||||||
|
integer |
revision number of the network configuration |
||||||||||||||||
|
integer |
time when the network was created |
||||||||||||||||
|
boolean |
whether or not the network is private if members will NOT need to be authorized to join |
||||||||||||||||
|
boolean |
enable broadcast packets on the network |
||||||||||||||||
|
object |
|
|
|||||||||||||||
|
dict |
|
|
|||||||||||||||
|
integer |
MTU to set on the client virtual network adapter |
||||||||||||||||
|
integer |
maximum number of recipients per multicast or broadcast, warning - Setting this to |
||||||||||||||||
|
list |
|
list of route dictionaries
|
|||||||||||||||
|
list |
|
list that contains dictionaries specifying
a range of IP addresses for the auto assign pool
|
|||||||||||||||
|
dict |
|
|
|||||||||||||||
|
list |
|
list of network rules dictionaries |
|||||||||||||||
|
list |
|
list of network tags dictionaries |
|||||||||||||||
|
string |
remote target ID for network tracing |
||||||||||||||||
|
integer |
level of network tracing |
||||||||||||||||
|
dict |
|
These options are only used for client configurations
|
Client specific settings
Required properties:
name
networks
key name |
type |
default |
description |
---|---|---|---|
|
string |
|
name of the zerotier network |
|
list |
|
list of dictionaries containing strings with 16-digit hexadecimal network IDs for joining, along with a corresponding custom 10-digit ZeroTier interface name for each network note: ensure that the list includes at least one such dictionary |
|
string |
|
path to the persistent configuration directory |
|
string |
|
specifies whether to copy the configuration file to RAM
|
|
string |
|
identity secret of the zerotier client (network member), leave it blank to be automatically determined |
|
integer |
|
port number of the zerotier service |
|
string |
path of the local zerotier configuration (only used for advanced configuration) |
Working around schema limitations
The schema does not include all the possible ZeroTier settings, but it can render appropiately any property not included in the schema as long as its type is one the following:
boolean
integer
strings
lists
Automatic generation of clients
Example (with custom zerotier interface name):
from netjsonconfig import OpenWrt
client_config = OpenWrt.zerotier_auto_client(
name="ow_zt",
networks=[{"id": "9536600adf654321", "ifname": "owzt654321"}],
)
print(OpenWrt(client_config).render())
Will be rendered as:
package zerotier
config zerotier 'ow_zt'
option config_path '/etc/openwisp/zerotier'
option copy_config_path '1'
option enabled '1'
list join '9536600adf654321'
option secret '{{secret}}'
# ---------- files ---------- #
# path: /etc/openwisp/zerotier/devicemap
# mode: 0644
# network_id=interface_name
9536600adf654321=owzt654321
Note
The current implementation of ZeroTier VPN backend is implemented with OpenWrt backend. Hence, the example above shows configuration generated for OpenWrt.
Useful resources
The default flow rules used in zerotier/schema.py for the ZeroTier self-hosted controller are taken from the flow rules mentioned in the documentation below.
To explore a comprehensive list of all available ZeroTier network configuration settings, please refer to the following OpenAPI API specifications.
Advanced configuration
If you want to use advanced configuration options that apply to your
OpenWrt device, such as setting up trusted paths, blacklisting physical
paths, setting up physical path hints for certain nodes, and defining
trusted upstream devices, this can be achieved by creating a file named
local.conf
in a persistent filesystem location, such as
/etc/openwisp/zerotier/local.conf
and then adding the
local_conf_path
option to the ZeroTier UCI configuration.
For example, let’s create a local configuration file at
/etc/openwisp/zerotier/local.conf
(JSON) to blacklist a specific
physical network path (10.0.0.0/24) from all ZeroTier traffic.
{
"physical": {
"10.0.0.0/24": {
"blacklist": true
}
}
}
Now add local_conf_path
option to /etc/config/zerotier
:
package zerotier
config zerotier 'ow_zt'
option enabled '1'
list join '9536600adf654322'
option secret '{{secret}}'
option local_conf_path '/etc/openwisp/zerotier/local.conf'
More information