diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 7e2bcdaa8..f45a1279d 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -595,9 +595,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id()); return true; } - } - - if (to != network->mac()) { + } else if (to != network->mac()) { if (!network->permitsBridging(RR->identity.address())) { TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id()); return true; diff --git a/node/Packet.cpp b/node/Packet.cpp index 4d58815e0..2c73a087b 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -51,7 +51,7 @@ const char *Packet::verbString(Verb v) case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY"; - case VERB_PHYSICAL_ADDRESS_PUSH: return "PHYSICAL_ADDRESS_PUSH"; + case VERB_PUSH_DIRECT_PATHS: return "PUSH_DIRECT_PATHS"; } return "(unknown)"; } diff --git a/node/Packet.hpp b/node/Packet.hpp index d9f8d8885..eeeef720c 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -71,13 +71,14 @@ /** * Maximum hop count allowed by packet structure (3 bits, 0-7) * - * This is not necessarily the maximum hop counter after which - * relaying is no longer performed. + * This is a protocol constant. It's the maximum allowed by the length + * of the hop counter -- three bits. See node/Constants.hpp for the + * pragmatic forwarding limit, which is typically lower. */ #define ZT_PROTO_MAX_HOPS 7 /** - * Cipher suite: Curve25519/Poly1305/Salsa20/12 without payload encryption + * Cipher suite: Curve25519/Poly1305/Salsa20/12/NOCRYPT * * This specifies Poly1305 MAC using a 32-bit key derived from the first * 32 bytes of a Salsa20/12 keystream as in the Salsa20/12 cipher suite, @@ -103,9 +104,7 @@ * * This message is encrypted with the latest negotiated ephemeral (PFS) * key pair and cipher suite. If authentication fails, VERB_SET_EPHEMERAL_KEY - * may be sent to renegotiate ephemeral keys. To prevent attacks, this - * attempted renegotiation should be limited to some sane rate such as - * once per second. + * may be sent to renegotiate ephemeral keys. */ #define ZT_PROTO_CIPHER_SUITE__EPHEMERAL 7 @@ -113,7 +112,7 @@ * DEPRECATED payload encrypted flag, will be removed for re-use soon. * * This has been replaced by the two-bit cipher suite selection field where - * a value of 0 indicated unencrypted (but authenticated) messages. + * a value of 0 indicates unencrypted (but authenticated) messages. */ #define ZT_PROTO_FLAG_ENCRYPTED 0x80 @@ -132,11 +131,68 @@ /** * Rounds used for Salsa20 encryption in ZT + * + * Discussion: + * + * DJB (Salsa20's designer) designed Salsa20 with a significant margin of 20 + * rounds, but has said repeatedly that 12 is likely sufficient. So far (as of + * July 2015) there are no published attacks against 12 rounds, let alone 20. + * + * In cryptography, a "break" means something different from what it means in + * common discussion. If a cipher is 256 bits strong and someone finds a way + * to reduce key search to 254 bits, this constitues a "break" in the academic + * literature. 254 bits is still far beyond what can be leveraged to accomplish + * a "break" as most people would understand it -- the actual decryption and + * reading of traffic. + * + * Nevertheless, "attacks only get better" as cryptographers like to say. As + * a result, they recommend not using anything that's shown any weakness even + * if that weakness is so far only meaningful to academics. It may be a sign + * of a deeper problem. + * + * So why choose a lower round count? + * + * Turns out the speed difference is nontrivial. On a Macbook Pro (Core i3) 20 + * rounds of SSE-optimized Salsa20 achieves ~508mb/sec/core, while 12 rounds + * hits ~832mb/sec/core. ZeroTier is designed for multiple objectives: + * security, simplicity, and performance. In this case a deference was made + * for performance. + * + * Meta discussion: + * + * The cipher is not the thing you should be paranoid about. + * + * I'll qualify that. If the cipher is known to be weak, like RC4, or has a + * key size that is too small, like DES, then yes you should worry about + * the cipher. + * + * But if the cipher is strong and your adversary is anyone other than the + * intelligence apparatus of a major superpower, you are fine in that + * department. + * + * Go ahead. Search for the last ten vulnerabilities discovered in SSL. Not + * a single one involved the breaking of a cipher. Now broaden your search. + * Look for issues with SSH, IPSec, etc. The only cipher-related issues you + * will find might involve the use of RC4 or MD5, algorithms with known + * issues or small key/digest sizes. But even weak ciphers are difficult to + * exploit in the real world -- you usually need a lot of data and a lot of + * compute time. No, virtually EVERY security vulnerability you will find + * involves a problem with the IMPLEMENTATION not with the cipher. + * + * A flaw in ZeroTier's protocol or code is incredibly, unbelievably + * more likely than a flaw in Salsa20 or any other cipher or cryptographic + * primitive it uses. We're talking odds of dying in a car wreck vs. odds of + * being personally impacted on the head by a meteorite. Nobody without a + * billion dollar budget is going to break into your network by actually + * cracking Salsa20/12 (or even /8) in the field. + * + * So stop worrying about the cipher unless you are, say, the Kremlin and your + * adversary is the NSA and the GCHQ. In that case... well that's above my + * pay grade. I'll just say defense in depth. */ #define ZT_PROTO_SALSA20_ROUNDS 12 -// Indices of fields in normal packet header -- do not change as this -// might require both code rework and will break compatibility. +// Field indexes in packet header #define ZT_PACKET_IDX_IV 0 #define ZT_PACKET_IDX_DEST 8 #define ZT_PACKET_IDX_SOURCE 13 @@ -147,16 +203,19 @@ /** * Packet buffer size (can be changed) + * + * The current value is big enough for ZT_MAX_PACKET_FRAGMENTS, the pragmatic + * packet fragment limit, times the default UDP MTU. Most packets won't be + * this big. */ #define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_UDP_DEFAULT_PAYLOAD_MTU) /** - * Minimum viable packet length (also length of header) + * Minimum viable packet length (a.k.a. header length) */ #define ZT_PROTO_MIN_PACKET_LENGTH ZT_PACKET_IDX_PAYLOAD -// Indexes of fields in fragment header -- also can't be changed without -// breaking compatibility. +// Indexes of fields in fragment header #define ZT_PACKET_FRAGMENT_IDX_PACKET_ID 0 #define ZT_PACKET_FRAGMENT_IDX_DEST 8 #define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR 13 @@ -165,7 +224,7 @@ #define ZT_PACKET_FRAGMENT_IDX_PAYLOAD 16 /** - * Value found at ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR in fragments + * Magic number found at ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR */ #define ZT_PACKET_FRAGMENT_INDICATOR ZT_ADDRESS_RESERVED_PREFIX @@ -175,23 +234,26 @@ #define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD /** - * Length of LAN beacon packets + * DEPRECATED: length of LAN beacon packets */ #define ZT_PROTO_BEACON_LENGTH 13 /** - * Index of address in a LAN beacon + * DEPRECATED: index of address in a LAN beacon */ #define ZT_PROTO_BEACON_IDX_ADDRESS 8 -// Destination address types from HELLO and OK(HELLO) +// Destination address types from HELLO, OK(HELLO), and other message types #define ZT_PROTO_DEST_ADDRESS_TYPE_NONE 0 -#define ZT_PROTO_DEST_ADDRESS_TYPE_ETHERNET 1 +#define ZT_PROTO_DEST_ADDRESS_TYPE_ZEROTIER 1 // reserved but unused +#define ZT_PROTO_DEST_ADDRESS_TYPE_ETHERNET 2 // future use +#define ZT_PROTO_DEST_ADDRESS_TYPE_BLUETOOTH 3 // future use #define ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 4 +#define ZT_PROTO_DEST_ADDRESS_TYPE_LTE_DIRECT 5 // future use #define ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 6 // Ephemeral key record flags -#define ZT_PROTO_EPHEMERAL_KEY_FLAG_FIPS 0x01 +#define ZT_PROTO_EPHEMERAL_KEY_FLAG_FIPS 0x01 // future use // Ephemeral key record symmetric cipher types #define ZT_PROTO_EPHEMERAL_KEY_SYMMETRIC_CIPHER_SALSA2012_POLY1305 0x01 @@ -680,10 +742,8 @@ public: /* Network configuration refresh request: * <[...] array of 64-bit network IDs> * - * This message can be sent by the network configuration master node - * to request that nodes refresh their network configuration. It can - * thus be used to "push" updates so that network config changes will - * take effect quickly. + * This can be sent by the network controller to inform a node that it + * should now make a NETWORK_CONFIG_REQUEST. * * It does not generate an OK or ERROR message, and is treated only as * a hint to refresh now. @@ -769,7 +829,7 @@ public: */ VERB_MULTICAST_FRAME = 14, - /* Ephemeral (PFS) key push: + /* Ephemeral (PFS) key push: (UNFINISHED, NOT IMPLEMENTED YET) * <[2] flags (unused and reserved, must be 0)> * <[2] length of padding / extra field section> * <[...] padding / extra field section> @@ -826,21 +886,35 @@ public: VERB_SET_EPHEMERAL_KEY = 15, /* Push of potential endpoints for direct communication: + * <[1] flags (unused, must be zero)> + * <[2] 16-bit number of paths> + * <[...] paths> + * + * Path record format: * <[1] flags> - * <[2] number of addresses> - * <[...] address types and addresses> + * <[1] metric from 0 (highest priority) to 255 (lowest priority)> + * <[1] address type> + * <[...] address> + * + * Path record flags: + * 0x01 - Blacklist this path, do not use + * 0x02 - Reliable path (no keepalives, etc. necessary) + * 0x04 - Trusted path (encryption and authentication optional) + * + * None of the above flags are implemented yet as of 1.0.4. They're + * reserved for future use. * * Address types and addresses are of the same format as the destination * address type and address in HELLO. * * The receiver may, upon receiving a push, attempt to establish a - * direct link to one or more of the indicated addresses. Senders should - * only send address pushes to peers that they have some relationship - * with such as a shared network membership or a mutual trust. + * direct link to one or more of the indicated addresses. It is the + * responsibility of the sender to limit which peers it pushes direct + * paths to to those with whom it has a trust relationship. * * OK/ERROR are not generated. */ - VERB_PHYSICAL_ADDRESS_PUSH = 16 + VERB_PUSH_DIRECT_PATHS = 16 }; /** diff --git a/node/Switch.cpp b/node/Switch.cpp index 236c1e660..18e17a605 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -167,6 +167,8 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c Address toZT(to.toAddress(network->id())); if (network->isAllowed(toZT)) { + const bool includeCom = network->peerNeedsOurMembershipCertificate(toZT,RR->node->now()); + /* if (network->peerNeedsOurMembershipCertificate(toZT,RR->node->now())) { // TODO: once there are no more <1.0.0 nodes around, we can // bundle this with EXT_FRAME instead of sending two packets. @@ -174,12 +176,17 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c nconf->com().serialize(outp); send(outp,true,network->id()); } + */ - if (fromBridged) { - // EXT_FRAME is used for bridging or if we want to include a COM + if ((true)||(fromBridged)||(includeCom)) { Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME); outp.append(network->id()); - outp.append((unsigned char)0); + if (includeCom) { + outp.append((unsigned char)0x01); // 0x01 -- COM included + nconf->com().serialize(outp); + } else { + outp.append((unsigned char)0x00); + } to.appendTo(outp); from.appendTo(outp); outp.append((uint16_t)etherType); @@ -187,7 +194,6 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.compress(); send(outp,true,network->id()); } else { - // FRAME is a shorter version that can be used when there's no bridging and no COM Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME); outp.append(network->id()); outp.append((uint16_t)etherType); @@ -196,7 +202,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c send(outp,true,network->id()); } - //TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged); + //TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d includeCom==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged,(int)includeCom); } else { TRACE("%.16llx: UNICAST: %s -> %s etherType==%s dropped, destination not a member of private network",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); }