Documentation in Packet, more work on path push, and clean up ancient legacy support code in Switch.

This commit is contained in:
Adam Ierymenko 2015-07-06 12:34:35 -07:00
parent df08c2cfab
commit e5f7c55c54
4 changed files with 116 additions and 38 deletions

View file

@ -595,9 +595,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id()); TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id());
return true; return true;
} }
} } else if (to != network->mac()) {
if (to != network->mac()) {
if (!network->permitsBridging(RR->identity.address())) { 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()); 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; return true;

View file

@ -51,7 +51,7 @@ const char *Packet::verbString(Verb v)
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER"; case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME"; case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
case VERB_SET_EPHEMERAL_KEY: return "SET_EPHEMERAL_KEY"; 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)"; return "(unknown)";
} }

View file

@ -71,13 +71,14 @@
/** /**
* Maximum hop count allowed by packet structure (3 bits, 0-7) * Maximum hop count allowed by packet structure (3 bits, 0-7)
* *
* This is not necessarily the maximum hop counter after which * This is a protocol constant. It's the maximum allowed by the length
* relaying is no longer performed. * 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 #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 * 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, * 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) * This message is encrypted with the latest negotiated ephemeral (PFS)
* key pair and cipher suite. If authentication fails, VERB_SET_EPHEMERAL_KEY * key pair and cipher suite. If authentication fails, VERB_SET_EPHEMERAL_KEY
* may be sent to renegotiate ephemeral keys. To prevent attacks, this * may be sent to renegotiate ephemeral keys.
* attempted renegotiation should be limited to some sane rate such as
* once per second.
*/ */
#define ZT_PROTO_CIPHER_SUITE__EPHEMERAL 7 #define ZT_PROTO_CIPHER_SUITE__EPHEMERAL 7
@ -113,7 +112,7 @@
* DEPRECATED payload encrypted flag, will be removed for re-use soon. * DEPRECATED payload encrypted flag, will be removed for re-use soon.
* *
* This has been replaced by the two-bit cipher suite selection field where * 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 #define ZT_PROTO_FLAG_ENCRYPTED 0x80
@ -132,11 +131,68 @@
/** /**
* Rounds used for Salsa20 encryption in ZT * 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 #define ZT_PROTO_SALSA20_ROUNDS 12
// Indices of fields in normal packet header -- do not change as this // Field indexes in packet header
// might require both code rework and will break compatibility.
#define ZT_PACKET_IDX_IV 0 #define ZT_PACKET_IDX_IV 0
#define ZT_PACKET_IDX_DEST 8 #define ZT_PACKET_IDX_DEST 8
#define ZT_PACKET_IDX_SOURCE 13 #define ZT_PACKET_IDX_SOURCE 13
@ -147,16 +203,19 @@
/** /**
* Packet buffer size (can be changed) * 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) #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 #define ZT_PROTO_MIN_PACKET_LENGTH ZT_PACKET_IDX_PAYLOAD
// Indexes of fields in fragment header -- also can't be changed without // Indexes of fields in fragment header
// breaking compatibility.
#define ZT_PACKET_FRAGMENT_IDX_PACKET_ID 0 #define ZT_PACKET_FRAGMENT_IDX_PACKET_ID 0
#define ZT_PACKET_FRAGMENT_IDX_DEST 8 #define ZT_PACKET_FRAGMENT_IDX_DEST 8
#define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR 13 #define ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR 13
@ -165,7 +224,7 @@
#define ZT_PACKET_FRAGMENT_IDX_PAYLOAD 16 #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 #define ZT_PACKET_FRAGMENT_INDICATOR ZT_ADDRESS_RESERVED_PREFIX
@ -175,23 +234,26 @@
#define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD #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 #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 #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_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_IPV4 4
#define ZT_PROTO_DEST_ADDRESS_TYPE_LTE_DIRECT 5 // future use
#define ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 6 #define ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 6
// Ephemeral key record flags // 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 // Ephemeral key record symmetric cipher types
#define ZT_PROTO_EPHEMERAL_KEY_SYMMETRIC_CIPHER_SALSA2012_POLY1305 0x01 #define ZT_PROTO_EPHEMERAL_KEY_SYMMETRIC_CIPHER_SALSA2012_POLY1305 0x01
@ -680,10 +742,8 @@ public:
/* Network configuration refresh request: /* Network configuration refresh request:
* <[...] array of 64-bit network IDs> * <[...] array of 64-bit network IDs>
* *
* This message can be sent by the network configuration master node * This can be sent by the network controller to inform a node that it
* to request that nodes refresh their network configuration. It can * should now make a NETWORK_CONFIG_REQUEST.
* thus be used to "push" updates so that network config changes will
* take effect quickly.
* *
* It does not generate an OK or ERROR message, and is treated only as * It does not generate an OK or ERROR message, and is treated only as
* a hint to refresh now. * a hint to refresh now.
@ -769,7 +829,7 @@ public:
*/ */
VERB_MULTICAST_FRAME = 14, 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] flags (unused and reserved, must be 0)>
* <[2] length of padding / extra field section> * <[2] length of padding / extra field section>
* <[...] padding / extra field section> * <[...] padding / extra field section>
@ -826,21 +886,35 @@ public:
VERB_SET_EPHEMERAL_KEY = 15, VERB_SET_EPHEMERAL_KEY = 15,
/* Push of potential endpoints for direct communication: /* 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> * <[1] flags>
* <[2] number of addresses> * <[1] metric from 0 (highest priority) to 255 (lowest priority)>
* <[...] address types and addresses> * <[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 types and addresses are of the same format as the destination
* address type and address in HELLO. * address type and address in HELLO.
* *
* The receiver may, upon receiving a push, attempt to establish a * The receiver may, upon receiving a push, attempt to establish a
* direct link to one or more of the indicated addresses. Senders should * direct link to one or more of the indicated addresses. It is the
* only send address pushes to peers that they have some relationship * responsibility of the sender to limit which peers it pushes direct
* with such as a shared network membership or a mutual trust. * paths to to those with whom it has a trust relationship.
* *
* OK/ERROR are not generated. * OK/ERROR are not generated.
*/ */
VERB_PHYSICAL_ADDRESS_PUSH = 16 VERB_PUSH_DIRECT_PATHS = 16
}; };
/** /**

View file

@ -167,6 +167,8 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
Address toZT(to.toAddress(network->id())); Address toZT(to.toAddress(network->id()));
if (network->isAllowed(toZT)) { if (network->isAllowed(toZT)) {
const bool includeCom = network->peerNeedsOurMembershipCertificate(toZT,RR->node->now());
/*
if (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 // TODO: once there are no more <1.0.0 nodes around, we can
// bundle this with EXT_FRAME instead of sending two packets. // bundle this with EXT_FRAME instead of sending two packets.
@ -174,12 +176,17 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
nconf->com().serialize(outp); nconf->com().serialize(outp);
send(outp,true,network->id()); send(outp,true,network->id());
} }
*/
if (fromBridged) { if ((true)||(fromBridged)||(includeCom)) {
// EXT_FRAME is used for bridging or if we want to include a COM
Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME); Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(network->id()); 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); to.appendTo(outp);
from.appendTo(outp); from.appendTo(outp);
outp.append((uint16_t)etherType); outp.append((uint16_t)etherType);
@ -187,7 +194,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
outp.compress(); outp.compress();
send(outp,true,network->id()); send(outp,true,network->id());
} else { } 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); Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME);
outp.append(network->id()); outp.append(network->id());
outp.append((uint16_t)etherType); outp.append((uint16_t)etherType);
@ -196,7 +202,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
send(outp,true,network->id()); 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 { } 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)); 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));
} }