diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-02-22 15:32:55 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-02-22 15:32:55 -0800 |
commit | b679ebde3b05efeb3346e20dfb216cf3b3bc2b1d (patch) | |
tree | eb0c0aaa1ac071eed6c30e3304f108a6584176dd | |
parent | b475bf4a2129239a1143efb41d8ee3fa5e9037fa (diff) | |
download | infinitytier-b679ebde3b05efeb3346e20dfb216cf3b3bc2b1d.tar.gz infinitytier-b679ebde3b05efeb3346e20dfb216cf3b3bc2b1d.zip |
Ad-hoc networks, a cool and easy to implement little feature that allows controllerless networks. These only allow IPv6 6plane, no multicast, and the network ID encodes the allowed port range.
-rw-r--r-- | include/ZeroTierOne.h | 12 | ||||
-rw-r--r-- | node/Network.cpp | 66 | ||||
-rw-r--r-- | rule-compiler/package.json | 2 |
3 files changed, 73 insertions, 7 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 9690489a..e2380a7b 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -610,15 +610,15 @@ enum ZT_VirtualNetworkRuleType typedef struct { /** - * Least significant 7 bits: ZT_VirtualNetworkRuleType, most significant 1 bit is NOT bit + * Type and flags * - * If the NOT bit is set, then matches will be interpreted as "does not - * match." The NOT bit has no effect on actions. + * Bits are: NOTTTTTT * - * Use "& 0x7f" to get the enum and "& 0x80" to get the NOT flag. + * N - If true, sense of match is inverted (no effect on actions) + * O - If true, result is ORed with previous instead of ANDed (no effect on actions) + * T - Rule or action type * - * The union 'v' is a variant type, and this selects which field in 'v' is - * actually used and valid. + * AND with 0x3f to get type, 0x80 to get NOT bit, and 0x40 to get OR bit. */ uint8_t t; diff --git a/node/Network.cpp b/node/Network.cpp index 461e1c20..290ceaf9 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1099,6 +1099,72 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk) void Network::requestConfiguration() { + /* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless + * network IDs. Controllerless network IDs only support unicast IPv6 using the 6plane + * addressing scheme and have the following format: 0xffSSSSEEEE000000 where SSSS + * is the 16-bit starting IP port range allowed and EEEE is the 16-bit ending IP port + * range allowed. Remaining digits are reserved for future use and must be zero. */ + if ((_id >> 56) == 0xff) { + const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff); + const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff); + if (((_id & 0xffffff) == 0)&&(endPortRange >= startPortRange)) { + NetworkConfig *const nconf = new NetworkConfig(); + + nconf->networkId = _id; + nconf->timestamp = RR->node->now(); + nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; + nconf->revision = 1; + nconf->issuedTo = RR->identity.address(); + nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; + nconf->staticIpCount = 1; + nconf->ruleCount = 14; + nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt()); + + // Drop everything but IPv6 + nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80; // NOT + nconf->rules[0].v.etherType = 0x86dd; // IPv6 + nconf->rules[1].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; + + // Allow ICMPv6 + nconf->rules[2].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; + nconf->rules[2].v.ipProtocol = 0x3a; // ICMPv6 + nconf->rules[3].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; + + // Allow destination ports within range + nconf->rules[4].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL; + nconf->rules[4].v.ipProtocol = 0x11; // UDP + nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40; // OR + nconf->rules[5].v.ipProtocol = 0x06; // TCP + nconf->rules[6].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE; + nconf->rules[6].v.port[0] = startPortRange; + nconf->rules[6].v.port[1] = endPortRange; + nconf->rules[7].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; + + // Allow non-SYN TCP packets to permit non-connection-initiating traffic + nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80; // NOT + nconf->rules[8].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN; + nconf->rules[9].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; + + // Also allow SYN+ACK which are replies to SYN + nconf->rules[10].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; + nconf->rules[10].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN; + nconf->rules[11].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS; + nconf->rules[11].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_ACK; + nconf->rules[12].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT; + + nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP; + + nconf->type = ZT_NETWORK_TYPE_PUBLIC; + Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange); + + this->setConfiguration(*nconf,false); + delete nconf; + } else { + this->setNotFound(); + } + return; + } + const Address ctrl(controller()); Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd; diff --git a/rule-compiler/package.json b/rule-compiler/package.json index 6fe70696..16f7a23f 100644 --- a/rule-compiler/package.json +++ b/rule-compiler/package.json @@ -1,6 +1,6 @@ { "name": "zerotier-rule-compiler", - "version": "1.1.17-0", + "version": "1.1.17-1", "description": "ZeroTier Rule Script Compiler", "main": "cli.js", "scripts": { |