mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-25 08:27:39 +02:00
Move default root set to network-hypervisor, add a priority level to roots.
This commit is contained in:
parent
188f404361
commit
d41e1b1c41
12 changed files with 170 additions and 111 deletions
14
zerotier-network-hypervisor/default-rootset/make-root-set.sh
Executable file
14
zerotier-network-hypervisor/default-rootset/make-root-set.sh
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is for internal use by ZeroTier, but obviously users can repurpose it to make their own.
|
||||
|
||||
# Usage: make-root-set.sh <identity.secret> [<...>]
|
||||
|
||||
for i in $*; do
|
||||
echo $i
|
||||
../../zerotier-system-service/target/debug/zerotier-system-service rootset sign root.zerotier.com.json $i >tmp.json
|
||||
mv -f tmp.json root.zerotier.com.json
|
||||
../../zerotier-system-service/target/debug/zerotier-system-service rootset marshal root.zerotier.com.json >root.zerotier.com.bin
|
||||
done
|
||||
|
||||
cat root.zerotier.com.json
|
Binary file not shown.
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "root.zerotier.com",
|
||||
"revision": 1,
|
||||
"members": [ {
|
||||
"identity": "62f865ae71:0:e2076c57de870e6288d7d5e7404408b1545efca37d67f77b87e9e54168c25d3ef1a9abf2905ea5e785c01dff23887ad4232d95c7a8fd2c27111a72bd159322dc",
|
||||
"endpoints": [ "udp:50.7.252.138/9993", "udp:2001:49f0:d0db:2::2/9993" ],
|
||||
"signature": [ 1, 250, 55, 178, 250, 221, 13, 136, 125, 246, 209, 222, 43, 154, 3, 87, 224, 202, 86, 154, 217, 132, 141, 77, 246, 233, 118, 35, 112, 37, 58, 226, 104, 232, 33, 180, 29, 159, 20, 100, 217, 129, 242, 16, 247, 253, 70, 245, 59, 22, 126, 148, 52, 7, 231, 5, 230, 252, 35, 204, 22, 12, 85, 122, 10 ],
|
||||
"priority": 0
|
||||
}, {
|
||||
"identity": "778cde7190:0:3f6681a99e5ad1895e9fba33e6212d4454e168bcec7112101bf000956ed8e92e42892cb6f2ec410881a84ab19da50e1287ba3d926c3a1f755cccf299a1207055",
|
||||
"endpoints": [ "udp:103.195.103.66/9993", "udp:2605:9880:400:c3:254:f2bc:a1f7:19/9993" ],
|
||||
"signature": [ 1, 115, 251, 30, 185, 137, 187, 219, 80, 35, 19, 117, 38, 241, 200, 137, 205, 208, 73, 54, 30, 158, 150, 64, 232, 214, 248, 54, 26, 180, 29, 68, 87, 34, 102, 251, 199, 158, 215, 199, 77, 8, 128, 93, 166, 199, 39, 139, 143, 20, 180, 29, 145, 232, 90, 181, 75, 237, 175, 238, 2, 124, 18, 124, 4 ],
|
||||
"priority": 0
|
||||
}, {
|
||||
"identity": "cafe04eba9:0:6c6a9d1dea55c1616bfe2a2b8f0ff9a8cacaf70374fb1f39e3bef81cbfebef17b7228268a0a2a29d3488c752565c6c965cbd6506ec24397cc8a5d9d15285a87f",
|
||||
"endpoints": [ "udp:84.17.53.155/9993", "udp:2a02:6ea0:d405::9993/9993" ],
|
||||
"signature": [ 1, 51, 245, 92, 49, 30, 240, 161, 49, 14, 233, 231, 237, 169, 55, 1, 171, 91, 121, 3, 157, 139, 135, 177, 212, 199, 26, 188, 98, 130, 138, 39, 193, 45, 190, 243, 146, 15, 234, 220, 203, 154, 39, 230, 88, 152, 164, 74, 44, 136, 125, 207, 23, 31, 112, 52, 16, 116, 179, 99, 93, 133, 133, 189, 6 ],
|
||||
"priority": 0
|
||||
}, {
|
||||
"identity": "cafe9efeb9:0:ccdef76bc7b97ded904eabc5df09886d9c1514a610036cb9139cc214001a2958978efcec15712dd3948c6e6b3a8e893df01ff493d1f8d9806a860c5420571bf0",
|
||||
"endpoints": [ "udp:104.194.8.134/9993", "udp:2605:9880:200:1200:30:571:e34:51/9993" ],
|
||||
"signature": [ 1, 237, 145, 250, 221, 80, 44, 48, 158, 74, 198, 149, 192, 96, 220, 223, 232, 141, 163, 254, 173, 190, 7, 16, 67, 234, 182, 183, 16, 36, 154, 40, 141, 98, 18, 253, 57, 186, 222, 71, 223, 247, 43, 131, 203, 38, 79, 36, 43, 52, 130, 80, 218, 188, 3, 175, 221, 108, 218, 139, 248, 37, 228, 112, 5 ],
|
||||
"priority": 0
|
||||
} ]
|
||||
}
|
|
@ -497,6 +497,20 @@ impl<const L: usize> AsMut<[u8]> for Buffer<L> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> From<[u8; L]> for Buffer<L> {
|
||||
#[inline(always)]
|
||||
fn from(a: [u8; L]) -> Self {
|
||||
Self(L, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> From<&[u8; L]> for Buffer<L> {
|
||||
#[inline(always)]
|
||||
fn from(a: &[u8; L]) -> Self {
|
||||
Self(L, a.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PooledBufferFactory<const L: usize>;
|
||||
|
||||
impl<const L: usize> PooledBufferFactory<L> {
|
||||
|
|
|
@ -18,34 +18,44 @@ use crate::vl1::Endpoint;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Description of a member of a root cluster.
|
||||
///
|
||||
/// Natural sort order is in order of identity address.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Root {
|
||||
/// Full identity of this node.
|
||||
/// Identity of this node (not including secret).
|
||||
pub identity: Identity,
|
||||
|
||||
/// Endpoints for this root or None if this is a former member attesting to an update that removes it.
|
||||
/// Endpoints for this root or None if this is a disabled entry.
|
||||
///
|
||||
/// Disabled entries typically exist when a former member is needed to sign a new revision to
|
||||
/// achieve N-1 quorum and issue an update.
|
||||
pub endpoints: Option<BTreeSet<Endpoint>>,
|
||||
|
||||
/// Signature of entire root set by this identity.
|
||||
///
|
||||
/// This is populated by the sign() method when the completed root set is signed by each member.
|
||||
/// All member roots must sign.
|
||||
#[serde(default)]
|
||||
pub signature: Vec<u8>,
|
||||
|
||||
/// Flags field (currently unused).
|
||||
/// Priority (higher number is lower priority, 0 is default).
|
||||
///
|
||||
/// Lower priority roots are only used if NO roots of a higher priority can be reached (in any root set).
|
||||
#[serde(default)]
|
||||
pub flags: u64,
|
||||
pub priority: u8,
|
||||
}
|
||||
|
||||
impl PartialOrd for Root {
|
||||
#[inline(always)]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.identity.partial_cmp(&other.identity)
|
||||
self.identity.address.partial_cmp(&other.identity.address)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Root {
|
||||
#[inline(always)]
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.identity.cmp(&other.identity)
|
||||
self.identity.address.cmp(&other.identity.address)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +77,8 @@ pub struct RootSet {
|
|||
pub revision: u64,
|
||||
|
||||
/// A set of Root nodes that are current or immediately former members of this cluster.
|
||||
/// This will always be sorted by member identity.
|
||||
///
|
||||
/// This will always be sorted by member identity address. Duplicate addresses are not allowed.
|
||||
pub members: Vec<Root>,
|
||||
}
|
||||
|
||||
|
@ -76,6 +87,12 @@ impl RootSet {
|
|||
Self { name, revision, members: Vec::new() }
|
||||
}
|
||||
|
||||
/// Get the ZeroTier default root set, which contains roots run by ZeroTier Inc.
|
||||
pub fn zerotier_default() -> Self {
|
||||
let mut cursor = 0;
|
||||
Self::unmarshal(&Buffer::from(include_bytes!("../../default-rootset/root.zerotier.com.json")), &mut cursor).unwrap()
|
||||
}
|
||||
|
||||
fn marshal_internal<const BL: usize>(&self, buf: &mut Buffer<BL>, include_signatures: bool) -> std::io::Result<()> {
|
||||
buf.append_u8(0)?; // version byte for future use
|
||||
buf.append_varint(self.name.as_bytes().len() as u64)?;
|
||||
|
@ -97,7 +114,8 @@ impl RootSet {
|
|||
buf.append_varint(m.signature.len() as u64)?;
|
||||
buf.append_bytes(m.signature.as_slice())?;
|
||||
}
|
||||
buf.append_varint(m.flags)?;
|
||||
buf.append_varint(0)?; // flags, currently always 0
|
||||
buf.append_u8(m.priority)?;
|
||||
buf.append_varint(0)?; // size of additional fields for future use
|
||||
}
|
||||
buf.append_varint(0)?; // size of additional fields for future use
|
||||
|
@ -127,9 +145,9 @@ impl RootSet {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Add a member to this definition, replacing any current entry for this identity.
|
||||
pub fn add<'a, I: Iterator<Item = &'a Endpoint>>(&mut self, member_identity: &Identity, endpoints: Option<I>) {
|
||||
self.members.retain(|m| !m.identity.eq(member_identity));
|
||||
/// Add a member to this definition, replacing any current entry with this address.
|
||||
pub fn add<'a, I: Iterator<Item = &'a Endpoint>>(&mut self, member_identity: &Identity, endpoints: Option<I>, priority: u8) {
|
||||
self.members.retain(|m| m.identity.address != member_identity.address);
|
||||
let _ = self.members.push(Root {
|
||||
identity: member_identity.clone_without_secret(),
|
||||
endpoints: endpoints.map(|endpoints| {
|
||||
|
@ -140,7 +158,7 @@ impl RootSet {
|
|||
tmp
|
||||
}),
|
||||
signature: Vec::new(),
|
||||
flags: 0,
|
||||
priority,
|
||||
});
|
||||
self.members.sort();
|
||||
}
|
||||
|
@ -162,7 +180,7 @@ impl RootSet {
|
|||
identity: unsigned_entry.identity,
|
||||
endpoints: unsigned_entry.endpoints,
|
||||
signature: signature.unwrap(),
|
||||
flags: unsigned_entry.flags,
|
||||
priority: unsigned_entry.priority,
|
||||
});
|
||||
self.members.sort();
|
||||
return true;
|
||||
|
@ -178,7 +196,7 @@ impl RootSet {
|
|||
/// root nodes can replace one member if three cluster members sign the update, but to
|
||||
/// remove two at a time one of the exiting members would have to sign. This is done by
|
||||
/// adding it with None as its address list, making it disabled. Disabled members function
|
||||
/// only as signers (witnesses).
|
||||
/// only as signers (witnesses) and only if they were enabled previously.
|
||||
///
|
||||
/// There is one edge case though. If a cluster definition has only one member, that one
|
||||
/// member must sign the next update. N-1 is not permitted to be less than one. If that was
|
||||
|
@ -237,7 +255,7 @@ impl Marshalable for RootSet {
|
|||
identity: Identity::unmarshal(buf, cursor)?,
|
||||
endpoints: None,
|
||||
signature: Vec::new(),
|
||||
flags: 0,
|
||||
priority: 0,
|
||||
};
|
||||
|
||||
let endpoint_count = buf.read_varint(cursor)?;
|
||||
|
@ -252,7 +270,8 @@ impl Marshalable for RootSet {
|
|||
let signature_size = buf.read_varint(cursor)?;
|
||||
let _ = m.signature.write_all(buf.read_bytes(signature_size as usize, cursor)?);
|
||||
|
||||
m.flags = buf.read_varint(cursor)?;
|
||||
let _ = buf.read_varint(cursor)?; // flags, currently unused
|
||||
m.priority = buf.read_u8(cursor)?;
|
||||
|
||||
*cursor += buf.read_varint(cursor)? as usize;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"name": "root.zerotier.com",
|
||||
"revision": 1,
|
||||
"members": [ {
|
||||
"identity": "62f865ae71:0:e2076c57de870e6288d7d5e7404408b1545efca37d67f77b87e9e54168c25d3ef1a9abf2905ea5e785c01dff23887ad4232d95c7a8fd2c27111a72bd159322dc",
|
||||
"endpoints": [ "udp:50.7.252.138/9993", "udp:2001:49f0:d0db:2::2/9993" ],
|
||||
"signature": [ 1, 45, 14, 211, 108, 240, 151, 85, 43, 241, 113, 18, 24, 45, 198, 197, 67, 254, 96, 138, 194, 77, 170, 156, 168, 31, 240, 55, 168, 108, 69, 135, 253, 198, 153, 36, 166, 200, 222, 157, 122, 50, 149, 149, 40, 35, 125, 93, 78, 228, 51, 245, 53, 238, 133, 84, 188, 190, 98, 145, 177, 19, 54, 154, 0 ],
|
||||
"flags": 0
|
||||
}, {
|
||||
"identity": "778cde7190:0:3f6681a99e5ad1895e9fba33e6212d4454e168bcec7112101bf000956ed8e92e42892cb6f2ec410881a84ab19da50e1287ba3d926c3a1f755cccf299a1207055",
|
||||
"endpoints": [ "udp:103.195.103.66/9993", "udp:2605:9880:400:c3:254:f2bc:a1f7:19/9993" ],
|
||||
"signature": [ 1, 202, 181, 145, 69, 58, 169, 42, 149, 210, 160, 77, 220, 56, 246, 54, 210, 161, 144, 158, 103, 70, 104, 236, 58, 66, 127, 100, 117, 242, 208, 70, 68, 87, 142, 163, 222, 231, 146, 60, 205, 180, 202, 18, 181, 137, 216, 204, 109, 118, 224, 86, 220, 26, 142, 61, 18, 50, 174, 173, 44, 167, 231, 249, 0 ],
|
||||
"flags": 0
|
||||
}, {
|
||||
"identity": "cafe04eba9:0:6c6a9d1dea55c1616bfe2a2b8f0ff9a8cacaf70374fb1f39e3bef81cbfebef17b7228268a0a2a29d3488c752565c6c965cbd6506ec24397cc8a5d9d15285a87f",
|
||||
"endpoints": [ "udp:84.17.53.155/9993", "udp:2a02:6ea0:d405::9993/9993" ],
|
||||
"signature": [ 1, 129, 31, 37, 249, 242, 179, 153, 184, 117, 15, 192, 41, 69, 112, 196, 189, 18, 57, 96, 33, 82, 31, 142, 57, 251, 151, 118, 86, 71, 11, 170, 197, 11, 20, 55, 74, 66, 10, 248, 133, 216, 88, 212, 34, 139, 128, 179, 246, 241, 8, 126, 105, 195, 126, 235, 140, 219, 66, 92, 166, 203, 111, 132, 0 ],
|
||||
"flags": 0
|
||||
}, {
|
||||
"identity": "cafe9efeb9:0:ccdef76bc7b97ded904eabc5df09886d9c1514a610036cb9139cc214001a2958978efcec15712dd3948c6e6b3a8e893df01ff493d1f8d9806a860c5420571bf0",
|
||||
"endpoints": [ "udp:104.194.8.134/9993", "udp:2605:9880:200:1200:30:571:e34:51/9993" ],
|
||||
"signature": [ 1, 254, 236, 249, 244, 29, 229, 55, 85, 171, 15, 42, 222, 51, 237, 237, 47, 54, 158, 123, 96, 24, 101, 207, 63, 82, 113, 254, 154, 225, 188, 147, 75, 115, 243, 200, 253, 221, 198, 234, 74, 168, 126, 13, 137, 143, 13, 56, 73, 206, 242, 29, 97, 8, 221, 31, 236, 187, 86, 190, 15, 65, 184, 253, 13 ],
|
||||
"flags": 0
|
||||
} ]
|
||||
}
|
|
@ -30,7 +30,7 @@ pub async fn cmd(flags: Flags, cmd_args: &ArgMatches) -> i32 {
|
|||
let path = path.unwrap();
|
||||
let secret_arg = secret_arg.unwrap();
|
||||
let secret = crate::utils::parse_cli_identity(secret_arg, true).await;
|
||||
let json_data = crate::utils::read_limit(path, 1048576).await;
|
||||
let json_data = crate::utils::read_limit(path, crate::utils::DEFAULT_FILE_IO_READ_LIMIT).await;
|
||||
if secret.is_err() {
|
||||
eprintln!("ERROR: unable to parse '{}' or read as a file.", secret_arg);
|
||||
return exitcode::ERR_IOERR;
|
||||
|
@ -66,7 +66,7 @@ pub async fn cmd(flags: Flags, cmd_args: &ArgMatches) -> i32 {
|
|||
let path = sc_args.value_of("path");
|
||||
if path.is_some() {
|
||||
let path = path.unwrap();
|
||||
let json_data = crate::utils::read_limit(path, 1048576).await;
|
||||
let json_data = crate::utils::read_limit(path, crate::utils::DEFAULT_FILE_IO_READ_LIMIT).await;
|
||||
if json_data.is_err() {
|
||||
eprintln!("ERROR: unable to read '{}'.", path);
|
||||
return exitcode::ERR_IOERR;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
use serde_json::ser::Formatter;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct JsonFormatter<'a> {
|
||||
current_indent: usize,
|
||||
has_value: bool,
|
||||
|
|
|
@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize};
|
|||
use zerotier_network_hypervisor::vl1::{Address, InetAddress};
|
||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||
|
||||
/// A list of unassigned or obsolete ports under 1024 that could possibly be squatted.
|
||||
pub const UNASSIGNED_PRIVILEGED_PORTS: [u16; 299] = [
|
||||
4, 6, 8, 10, 12, 14, 15, 16, 26, 28, 30, 32, 34, 36, 40, 60, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 285, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 323, 324, 325, 326, 327, 328,
|
||||
329, 330, 331, 332, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 703, 708, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 732, 733, 734, 735, 736, 737, 738, 739, 740, 743, 745, 746, 755, 756, 766, 768, 778, 779,
|
||||
|
@ -22,36 +23,37 @@ pub const UNASSIGNED_PRIVILEGED_PORTS: [u16; 299] = [
|
|||
954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1023,
|
||||
];
|
||||
|
||||
/// Default primary ZeroTier port.
|
||||
pub const DEFAULT_PORT: u16 = 9993;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigPhysicalPathConfig {
|
||||
pub struct PhysicalPathSettings {
|
||||
pub blacklist: bool,
|
||||
}
|
||||
|
||||
impl Default for LocalConfigPhysicalPathConfig {
|
||||
impl Default for PhysicalPathSettings {
|
||||
fn default() -> Self {
|
||||
LocalConfigPhysicalPathConfig { blacklist: false }
|
||||
Self { blacklist: false }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigVirtualConfig {
|
||||
pub struct VirtualNetworkSettings {
|
||||
#[serde(rename = "try")]
|
||||
pub try_: Vec<InetAddress>,
|
||||
}
|
||||
|
||||
impl Default for LocalConfigVirtualConfig {
|
||||
impl Default for VirtualNetworkSettings {
|
||||
fn default() -> Self {
|
||||
LocalConfigVirtualConfig { try_: Vec::new() }
|
||||
Self { try_: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigNetworkSettings {
|
||||
pub struct NetworkSettings {
|
||||
#[serde(rename = "allowManagedIPs")]
|
||||
pub allow_managed_ips: bool,
|
||||
#[serde(rename = "allowGlobalIPs")]
|
||||
|
@ -64,9 +66,9 @@ pub struct LocalConfigNetworkSettings {
|
|||
pub allow_default_route_override: bool,
|
||||
}
|
||||
|
||||
impl Default for LocalConfigNetworkSettings {
|
||||
impl Default for NetworkSettings {
|
||||
fn default() -> Self {
|
||||
LocalConfigNetworkSettings {
|
||||
Self {
|
||||
allow_managed_ips: true,
|
||||
allow_global_ips: false,
|
||||
allow_managed_routes: true,
|
||||
|
@ -78,78 +80,43 @@ impl Default for LocalConfigNetworkSettings {
|
|||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigLogSettings {
|
||||
pub path: Option<String>,
|
||||
#[serde(rename = "maxSize")]
|
||||
pub max_size: usize,
|
||||
pub vl1: bool,
|
||||
pub vl2: bool,
|
||||
#[serde(rename = "vl2TraceRules")]
|
||||
pub vl2_trace_rules: bool,
|
||||
#[serde(rename = "vl2TraceMulticast")]
|
||||
pub vl2_trace_multicast: bool,
|
||||
pub debug: bool,
|
||||
pub stderr: bool,
|
||||
}
|
||||
|
||||
impl Default for LocalConfigLogSettings {
|
||||
fn default() -> Self {
|
||||
// TODO: change before release to saner defaults
|
||||
LocalConfigLogSettings {
|
||||
path: None,
|
||||
max_size: 131072,
|
||||
vl1: true,
|
||||
vl2: true,
|
||||
vl2_trace_rules: true,
|
||||
vl2_trace_multicast: true,
|
||||
debug: true,
|
||||
stderr: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfigSettings {
|
||||
pub struct GlobalSettings {
|
||||
#[serde(rename = "primaryPort")]
|
||||
pub primary_port: u16,
|
||||
#[serde(rename = "portMapping")]
|
||||
pub port_mapping: bool,
|
||||
#[serde(rename = "log")]
|
||||
pub log: LocalConfigLogSettings,
|
||||
#[serde(rename = "interfacePrefixBlacklist")]
|
||||
pub interface_prefix_blacklist: Vec<String>,
|
||||
#[serde(rename = "explicitAddresses")]
|
||||
pub explicit_addresses: Vec<InetAddress>,
|
||||
}
|
||||
|
||||
impl Default for LocalConfigSettings {
|
||||
impl Default for GlobalSettings {
|
||||
fn default() -> Self {
|
||||
let mut bl: Vec<String> = Vec::new();
|
||||
bl.reserve(LocalConfigSettings::DEFAULT_PREFIX_BLACKLIST.len());
|
||||
for n in LocalConfigSettings::DEFAULT_PREFIX_BLACKLIST.iter() {
|
||||
bl.reserve(Self::DEFAULT_PREFIX_BLACKLIST.len());
|
||||
for n in Self::DEFAULT_PREFIX_BLACKLIST.iter() {
|
||||
bl.push(String::from(*n));
|
||||
}
|
||||
|
||||
LocalConfigSettings {
|
||||
Self {
|
||||
primary_port: DEFAULT_PORT,
|
||||
port_mapping: true,
|
||||
log: LocalConfigLogSettings::default(),
|
||||
interface_prefix_blacklist: bl,
|
||||
explicit_addresses: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalConfigSettings {
|
||||
impl GlobalSettings {
|
||||
#[cfg(target_os = "macos")]
|
||||
const DEFAULT_PREFIX_BLACKLIST: [&'static str; 9] = ["lo", "utun", "gif", "stf", "iptap", "pktap", "feth", "zt", "llw"];
|
||||
pub const DEFAULT_PREFIX_BLACKLIST: [&'static str; 9] = ["lo", "utun", "gif", "stf", "iptap", "pktap", "feth", "zt", "llw"];
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const DEFAULT_PREFIX_BLACKLIST: [&'static str; 5] = ["lo", "tun", "tap", "ipsec", "zt"];
|
||||
pub const DEFAULT_PREFIX_BLACKLIST: [&'static str; 5] = ["lo", "tun", "tap", "ipsec", "zt", "tailscale"];
|
||||
|
||||
#[cfg(windows)]
|
||||
const DEFAULT_PREFIX_BLACKLIST: [&'static str; 0] = [];
|
||||
pub const DEFAULT_PREFIX_BLACKLIST: [&'static str; 0] = [];
|
||||
|
||||
pub fn is_interface_blacklisted(&self, ifname: &str) -> bool {
|
||||
for p in self.interface_prefix_blacklist.iter() {
|
||||
|
@ -163,21 +130,66 @@ impl LocalConfigSettings {
|
|||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(default)]
|
||||
pub struct LocalConfig {
|
||||
pub physical: BTreeMap<InetAddress, LocalConfigPhysicalPathConfig>,
|
||||
pub struct Config {
|
||||
pub physical: BTreeMap<InetAddress, PhysicalPathSettings>,
|
||||
#[serde(rename = "virtual")]
|
||||
pub virtual_: BTreeMap<Address, LocalConfigVirtualConfig>,
|
||||
pub network: BTreeMap<NetworkId, LocalConfigNetworkSettings>,
|
||||
pub settings: LocalConfigSettings,
|
||||
pub virtual_: BTreeMap<Address, VirtualNetworkSettings>,
|
||||
pub network: BTreeMap<NetworkId, NetworkSettings>,
|
||||
pub settings: GlobalSettings,
|
||||
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
file_content_hash: [u8; 48],
|
||||
}
|
||||
|
||||
impl Default for LocalConfig {
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
LocalConfig {
|
||||
Self {
|
||||
physical: BTreeMap::new(),
|
||||
virtual_: BTreeMap::new(),
|
||||
network: BTreeMap::new(),
|
||||
settings: LocalConfigSettings::default(),
|
||||
settings: GlobalSettings::default(),
|
||||
file_content_hash: [0_u8; 48],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Load this configuration from disk.
|
||||
pub async fn load(path: &str) -> std::io::Result<Self> {
|
||||
let mut t = Self::default();
|
||||
t.reload(path).await.map(|_| t)
|
||||
}
|
||||
|
||||
/// Load this configuration from disk if its contents have changed.
|
||||
///
|
||||
/// This returns true if a new configuration was loaded, false if the file hasn't changed, or an error.
|
||||
pub async fn reload(&mut self, path: &str) -> std::io::Result<bool> {
|
||||
let config_data = crate::utils::read_limit(path, crate::utils::DEFAULT_FILE_IO_READ_LIMIT).await?;
|
||||
let hash = zerotier_core_crypto::hash::SHA384::hash(config_data.as_slice());
|
||||
Ok(if hash != self.file_content_hash {
|
||||
let config = serde_json::from_slice(config_data.as_slice());
|
||||
if config.is_err() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, config.err().unwrap().to_string()));
|
||||
}
|
||||
*self = config.unwrap();
|
||||
self.file_content_hash = hash;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
/// Write this configuration to a file (with human-friendly formatting).
|
||||
///
|
||||
/// This is mutable because it updates an external state if the write is successful.
|
||||
pub async fn save(&mut self, path: &str) -> std::io::Result<()> {
|
||||
let config_data = crate::utils::to_json_pretty(self);
|
||||
let result = tokio::fs::write(path, &config_data).await;
|
||||
if result.is_ok() {
|
||||
self.file_content_hash = zerotier_core_crypto::hash::SHA384::hash(config_data.as_bytes());
|
||||
Ok(())
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,6 @@ Advanced Operations:
|
|||
· list List root sets in use
|
||||
sign <path> <?identity secret> Sign a root set with an identity
|
||||
verify <path> Load and verify a root set
|
||||
marshal <path> Dump root set as binary to stdout
|
||||
|
||||
service Start local service
|
||||
(usually not invoked manually)
|
||||
|
@ -105,12 +104,12 @@ pub fn print_help() {
|
|||
let _ = std::io::stdout().write_all(h.as_bytes());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn platform_default_home_path() -> String {
|
||||
"/Library/Application Support/ZeroTier".into()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn platform_default_home_path() -> String {
|
||||
"/var/lib/zerotier".into()
|
||||
}
|
||||
|
|
|
@ -6,22 +6,24 @@
|
|||
* https://www.zerotier.com/
|
||||
*/
|
||||
|
||||
use std::error::Error;
|
||||
use std::str::FromStr;
|
||||
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use tokio::fs::File;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
use crate::jsonformatter::JsonFormatter;
|
||||
|
||||
use zerotier_network_hypervisor::vl1::Identity;
|
||||
|
||||
/// Default sanity limit parameter for read_limit() used throughout the service.
|
||||
pub const DEFAULT_FILE_IO_READ_LIMIT: usize = 1048576;
|
||||
|
||||
lazy_static! {
|
||||
static ref STARTUP_INSTANT: Instant = Instant::now();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue