summaryrefslogtreecommitdiff
path: root/node/Packet.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Packet.hpp')
-rw-r--r--node/Packet.hpp202
1 files changed, 105 insertions, 97 deletions
diff --git a/node/Packet.hpp b/node/Packet.hpp
index cc3d323b..fb332b7d 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -34,11 +34,11 @@
#include "Utils.hpp"
#include "Buffer.hpp"
-#ifdef ZT_USE_SYSTEM_LZ4
-#include <lz4.h>
-#else
-#include "../ext/lz4/lz4.h"
-#endif
+//#ifdef ZT_USE_SYSTEM_LZ4
+//#include <lz4.h>
+//#else
+//#include "../ext/lz4/lz4.h"
+//#endif
/**
* Protocol version -- incremented only for major changes
@@ -59,15 +59,17 @@
* + Otherwise backward compatible with protocol v4
* 6 - 1.1.5 ... 1.1.10
* + Network configuration format revisions including binary values
- * 7 - 1.1.10 -- 1.2.0
+ * 7 - 1.1.10 ... 1.1.17
* + Introduce trusted paths for local SDN use
- * 8 - 1.2.0 -- CURRENT
+ * 8 - 1.1.17 ... 1.2.0
* + Multipart network configurations for large network configs
* + Tags and Capabilities
* + Inline push of CertificateOfMembership deprecated
* + Certificates of representation for federation and mesh
+ * 9 - 1.2.0 ... CURRENT
+ * + In-band encoding of packet counter for link quality measurement
*/
-#define ZT_PROTO_VERSION 8
+#define ZT_PROTO_VERSION 9
/**
* Minimum supported protocol version
@@ -351,7 +353,7 @@ namespace ZeroTier {
* ZeroTier packet
*
* Packet format:
- * <[8] 64-bit random packet ID and crypto initialization vector>
+ * <[8] 64-bit packet ID / crypto IV / packet counter>
* <[5] destination ZT address>
* <[5] source ZT address>
* <[1] flags/cipher/hops>
@@ -362,6 +364,14 @@ namespace ZeroTier {
*
* Packets smaller than 28 bytes are invalid and silently discarded.
*
+ * The 64-bit packet ID is a strongly random value used as a crypto IV.
+ * Its least significant 3 bits are also used as a monotonically increasing
+ * (and looping) counter for sending packets to a particular recipient. This
+ * can be used for link quality monitoring and reporting and has no crypto
+ * impact as it does not increase the likelihood of an IV collision. (The
+ * crypto we use is not sensitive to the nature of the IV, only that it does
+ * not repeat.)
+ *
* The flags/cipher/hops bit field is: FFCCCHHH where C is a 3-bit cipher
* selection allowing up to 7 cipher suites, F is outside-envelope flags,
* and H is hop count.
@@ -531,43 +541,53 @@ public:
VERB_NOP = 0x00,
/**
- * Announcement of a node's existence:
+ * Announcement of a node's existence and vitals:
* <[1] protocol version>
* <[1] software major version>
* <[1] software minor version>
* <[2] software revision>
- * <[8] timestamp (ms since epoch)>
+ * <[8] timestamp for determining latency>
* <[...] binary serialized identity (see Identity)>
- * <[1] destination address type>
- * [<[...] destination address to which packet was sent>]
- * <[8] 64-bit world ID of current world>
- * <[8] 64-bit timestamp of current world>
- *
- * This is the only message that ever must be sent in the clear, since it
- * is used to push an identity to a new peer.
- *
- * The destination address is the wire address to which this packet is
- * being sent, and in OK is *also* the destination address of the OK
- * packet. This can be used by the receiver to detect NAT, learn its real
- * external address if behind NAT, and detect changes to its external
- * address that require re-establishing connectivity.
- *
- * Destination address types and formats (not all of these are used now):
- * 0x00 - None -- no destination address data present
- * 0x01 - Ethernet address -- format: <[6] Ethernet MAC>
- * 0x04 - 6-byte IPv4 UDP address/port -- format: <[4] IP>, <[2] port>
- * 0x06 - 18-byte IPv6 UDP address/port -- format: <[16] IP>, <[2] port>
+ * <[...] physical destination address of packet>
+ * <[8] 64-bit world ID of current planet>
+ * <[8] 64-bit timestamp of current planet>
+ * [... remainder if packet is encrypted using cryptField() ...]
+ * <[2] 16-bit number of moons>
+ * [<[1] 8-bit type ID of moon>]
+ * [<[8] 64-bit world ID of moon>]
+ * [<[8] 64-bit timestamp of moon>]
+ * [... additional moon type/ID/timestamp tuples ...]
+ * <[2] 16-bit length of certificate of representation>
+ * [... certificate of representation ...]
+ *
+ * HELLO is sent in the clear as it is how peers share their identity
+ * public keys. A few additional fields are sent in the clear too, but
+ * these are things that are public info or are easy to determine. As
+ * of 1.2.0 we have added a few more fields, but since these could have
+ * the potential to be sensitive we introduced the encryption of the
+ * remainder of the packet. See cryptField(). Packet MAC is still
+ * performed of course, so authentication occurs as normal.
+ *
+ * Destination address is the actual wire address to which the packet
+ * was sent. See InetAddress::serialize() for format.
*
* OK payload:
- * <[8] timestamp (echoed from original HELLO)>
- * <[1] protocol version (of responder)>
- * <[1] software major version (of responder)>
- * <[1] software minor version (of responder)>
- * <[2] software revision (of responder)>
- * <[1] destination address type (for this OK, not copied from HELLO)>
- * [<[...] destination address>]
- * <[2] 16-bit length of world update or 0 if none>
- * [[...] world update]
+ * <[8] HELLO timestamp field echo>
+ * <[1] protocol version>
+ * <[1] software major version>
+ * <[1] software minor version>
+ * <[2] software revision>
+ * <[...] physical destination address of packet>
+ * <[2] 16-bit length of world update(s) or 0 if none>
+ * [[...] updates to planets and/or moons]
+ * <[2] 16-bit length of certificate of representation>
+ * [... certificate of representation ...]
+ *
+ * With the exception of the timestamp, the other fields pertain to the
+ * respondent who is sending OK and are not echoes.
+ *
+ * Note that OK is fully encrypted so no selective cryptField() of
+ * potentially sensitive fields is needed.
*
* ERROR has no payload.
*/
@@ -617,10 +637,8 @@ public:
* <[1] protocol address length (4 for IPv4, 16 for IPv6)>
* <[...] protocol address (network byte order)>
*
- * This is sent by a relaying node to initiate NAT traversal between two
- * peers that are communicating by way of indirect relay. The relay will
- * send this to both peers at the same time on a periodic basis, telling
- * each where it might find the other on the network.
+ * An upstream node can send this to inform both sides of a relay of
+ * information they might use to establish a direct connection.
*
* Upon receipt a peer sends HELLO to establish a direct link.
*
@@ -713,8 +731,7 @@ public:
/**
* Network credentials push:
- * <[...] serialized certificate of membership>
- * [<[...] additional certificates of membership>]
+ * [<[...] one or more certificates of membership>]
* <[1] 0x00, null byte marking end of COM array>
* <[2] 16-bit number of capabilities>
* <[...] one or more serialized Capability>
@@ -722,6 +739,8 @@ public:
* <[...] one or more serialized Tags>
* <[2] 16-bit number of revocations>
* <[...] one or more serialized Revocations>
+ * <[2] 16-bit number of certificates of ownership>
+ * <[...] one or more serialized CertificateOfOwnership>
*
* This can be sent by anyone at any time to push network credentials.
* These will of course only be accepted if they are properly signed.
@@ -891,8 +910,6 @@ public:
*/
VERB_MULTICAST_FRAME = 0x0e,
- // 0x0f is reserved for an old deprecated message
-
/**
* Push of potential endpoints for direct communication:
* <[2] 16-bit number of paths>
@@ -1023,8 +1040,7 @@ public:
* <[1] 8-bit packet hop count of received CIRCUIT_TEST>
* <[...] local wire address on which packet was received>
* <[...] remote wire address from which packet was received>
- * <[2] 16-bit length of additional fields>
- * <[...] additional fields>
+ * <[2] 16-bit path link quality of path over which packet was received>
* <[1] 8-bit number of next hops (breadth)>
* <[...] next hop information>
*
@@ -1045,49 +1061,6 @@ public:
VERB_CIRCUIT_TEST_REPORT = 0x12,
/**
- * Request proof of work:
- * <[1] 8-bit proof of work type>
- * <[1] 8-bit proof of work difficulty>
- * <[2] 16-bit length of proof of work challenge>
- * <[...] proof of work challenge>
- *
- * This requests that a peer perform a proof of work calucation. It can be
- * sent by highly trusted peers (e.g. root servers, network controllers)
- * under suspected denial of service conditions in an attempt to filter
- * out "non-serious" peers and remain responsive to those proving their
- * intent to actually communicate.
- *
- * If the peer obliges to perform the work, it does so and responds with
- * an OK containing the result. Otherwise it may ignore the message or
- * response with an ERROR_INVALID_REQUEST or ERROR_UNSUPPORTED_OPERATION.
- *
- * Proof of work type IDs:
- * 0x01 - Salsa20/12+SHA512 hashcash function
- *
- * Salsa20/12+SHA512 is based on the following composite hash function:
- *
- * (1) Compute SHA512(candidate)
- * (2) Use the first 256 bits of the result of #1 as a key to encrypt
- * 131072 zero bytes with Salsa20/12 (with a zero IV).
- * (3) Compute SHA512(the result of step #2)
- * (4) Accept this candiate if the first [difficulty] bits of the result
- * from step #3 are zero. Otherwise generate a new candidate and try
- * again.
- *
- * This is performed repeatedly on candidates generated by appending the
- * supplied challenge to an arbitrary nonce until a valid candidate
- * is found. This chosen prepended nonce is then returned as the result
- * in OK.
- *
- * OK payload:
- * <[2] 16-bit length of result>
- * <[...] computed proof of work>
- *
- * ERROR has no payload.
- */
- VERB_REQUEST_PROOF_OF_WORK = 0x13,
-
- /**
* A message with arbitrary user-definable content:
* <[8] 64-bit arbitrary message type ID>
* [<[...] message payload>]
@@ -1095,6 +1068,10 @@ public:
* This can be used to send arbitrary messages over VL1. It generates no
* OK or ERROR and has no special semantics outside of whatever the user
* (via the ZeroTier core API) chooses to give it.
+ *
+ * Message type IDs less than or equal to 65535 are reserved for use by
+ * ZeroTier, Inc. itself. We recommend making up random ones for your own
+ * implementations.
*/
VERB_USER_MESSAGE = 0x14
};
@@ -1133,10 +1110,8 @@ public:
};
#ifdef ZT_TRACE
- static const char *verbString(Verb v)
- throw();
- static const char *errorString(ErrorCode e)
- throw();
+ static const char *verbString(Verb v);
+ static const char *errorString(ErrorCode e);
#endif
template<unsigned int C2>
@@ -1334,11 +1309,22 @@ public:
/**
* Get this packet's unique ID (the IV field interpreted as uint64_t)
*
+ * Note that the least significant 3 bits of this ID will change when armor()
+ * is called to armor the packet for transport. This is because armor() will
+ * mask the last 3 bits against the send counter for QoS monitoring use prior
+ * to actually using the IV to encrypt and MAC the packet. Be aware of this
+ * when grabbing the packetId of a new packet prior to armor/send.
+ *
* @return Packet ID
*/
inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_IDX_IV); }
/**
+ * @return Value of link quality counter extracted from this packet's ID, range 0 to 7 (3 bits)
+ */
+ inline unsigned int linkQualityCounter() const { return (unsigned int)(reinterpret_cast<const uint8_t *>(data())[7] & 7); }
+
+ /**
* Set packet verb
*
* This also has the side-effect of clearing any verb flags, such as
@@ -1368,8 +1354,9 @@ public:
*
* @param key 32-byte key
* @param encryptPayload If true, encrypt packet payload, else just MAC
+ * @param counter Packet send counter for destination peer -- only least significant 3 bits are used
*/
- void armor(const void *key,bool encryptPayload);
+ void armor(const void *key,bool encryptPayload,unsigned int counter);
/**
* Verify and (if encrypted) decrypt packet
@@ -1384,6 +1371,27 @@ public:
bool dearmor(const void *key);
/**
+ * Encrypt/decrypt a separately armored portion of a packet
+ *
+ * This currently uses Salsa20/12, but any message that uses this should
+ * incorporate a cipher selector to permit this to be changed later. To
+ * ensure that key stream is not reused, the key is slightly altered for
+ * this use case and the same initial 32 keystream bytes that are taken
+ * for MAC in ordinary armor() are also skipped here.
+ *
+ * This is currently only used to mask portions of HELLO as an extra
+ * security precation since most of that message is sent in the clear.
+ *
+ * This must NEVER be used more than once in the same packet, as doing
+ * so will result in re-use of the same key stream.
+ *
+ * @param key 32-byte key
+ * @param start Start of encrypted portion
+ * @param len Length of encrypted portion
+ */
+ void cryptField(const void *key,unsigned int start,unsigned int len);
+
+ /**
* Attempt to compress payload if not already (must be unencrypted)
*
* This requires that the payload at least contain the verb byte already