Note: This README is written about what mesher will become. It's not yet there. Take this README as an end goal, not as a current, up-to-date reference.
It's also not so much documentation as it is a scratch pad for my ideas, but nonetheless feel free to leave issues requesting clarification or suggesting improvements. I'll need to write real docs at some point, and that feedback will be useful.
If this note is still present after 1.0, please open an issue for it to be removed.
Mesher is a system -- primarily a library, but also some executables which use it -- to make anonymized communication between members of a mesh network simpler. It focuses mostly on one-way message delivery, but does provide a way to give a reply route, so a tunnel could be built, given sufficient forethought. The project is largely divided into two parts: The primary focus, the mesher library, and the mesher-node binary, which provides a "generally good enough" wrapper around the binary so mesher can be incorporated quickly.
Designed to be secure in transit, mesher messages are encrypted with open-source, well-vetted algorithms and code. Mesher itself contains no crypto math, instead using open-source and vetted libraries, and common, vetted algorithms within them. The portions using crypto primitives are well-separated into their own submodule for easy auditing, and are based off well-explored concepts. It uses normal [X25519] for key agreement, then [chacha20-poly1305@openssl.com] through [ring] for authenticated encryption. All random generation is done through the OS's CSRNG, e.g. /dev/urandom on Linux. If the message is unsigned, sender public keys will be randomly generated per instruction and sent in cleartext as part of the message. If it's signed, then the sender public key for each instruction will be the same one used to sign the whole message, since the public key is already [recoverable] anyway and it's much less work on both ends. Signatures are handled with [Ed25519]1.
Designed to be flexible, mesher has a robust plugin system.
The library itself has a rich set of hooks to allow for custom send and receive transports, as well as custom message types.
The mesher-node
binary takes plugins in shared library form (.so/.dll/.dylib, depending on platform) and so is compatible with any language that can compile to those.
See its section for more information on the specific format.
1:
Note that mesher uses ed25519-dalek
's stronger verify_strict
functionality.
Because the same crate is used at both ends, compatibility is not a concern, but your use case may differ.
If so, please see [A Note on Signature Malleability] from the ed25519-dalek
documentation.
Some sections left to do, generally because I can't yet or it wouldn't make sense to think about them yet:
The core of this project is the mesher library, which provides:
c_api
feature.There are also a binary and some examples that can be compiled directly from this repo.
Enable them with the binaries
feature.
Note that building them might take much longer than just the library, so they're off by default.
The binary is mesher-node
, which is installed when you cargo install mesher
.
It provides a simple but entirely functional node for a mesher network, and essentially just wraps the library in a ready-to-use executable.
It can be communicated with over HTTP to localhost, the details of which are in the mesher-node section below.
The examples are setup
, send
and recv
, examples which just show how to launch and communicate with mesher-node
, allowing you to send strings and show received strings.
Because they're designed as demos, they're included as Cargo examples, rather than binaries.
They're incredibly insecure due to the way they generate keys, and must be replaced in any production usage, but generating and managing keys corrctly would be significantly more complex and obscure the actual point, demonstrating how to use mesher-node
.
The core of mesher's networking is, of course, the messages it sends. They're structured as a list of "instructions", which can be one of two types:
TODO: Settle on and describe the byte format. KISS.
In transit, each instruction is encrypted with its intended recipient's public key. Any intermediate node can see all of the encrypted instructions, but unless they have a backdoor for Curve25519 or they compromise the key somehow, they won't be able to access the actual contents. On receipt of a message, the library attempts to decrypt all of the instructions. Any instructions not encrypted with one of that node's keys will, of course fail, and are ignored, but not discarded.
Messages can also be signed. Nodes are configured to expect signatures or not, and there's nothing in the message format itself to say whether or not it's signed. Nodes configured to accept signed messages will only respond at all to messages signed with the correct key, and ignore both unsigned and incorrectly signed messages. The signature, if present, is the last 64 bytes, signing the raw message rather than any construction of its instructions.
The way routes are described is slightly different from things like Tor. Rather than providing a list of nodes, and a standard way to transport data between nodes, mesher routes are described by lists of transports. If you're familiar with graph theory, this is analogous to describing a path by its edges. This opens up two interesting opportunities:
There are no compromises to this method that affect mesher's goal. However, it would likely be unsuitable for general mesh networking, mostly because it's more complication than is necessary in most cases. Most mesh networks will be built out of identical nodes with identical communication capabilities. Again: mesher makes no attempt to be a general-purpose mesh networking library, and its design reflects that.
While constructing the routes at the sender, more information is needed: Which node should execute each instruction. Nodes are identified at the sender by their public key, since that's all the sender really cares about. When the entire bundle is received, the node will try to decrypt each message, and the ones it can, the ones encrytped with its key, are the ones it interprets. Each transport has to be matched with a public key, but public keys can be reused. This allows a single node to send the same message out multiple times, along multiple routes, in case part of the route may be unreliable. Mesher will automatically ignore duplicate messages received, within configurable limits, to make this simpler to handle.
TODO: Describe how to communicate with this: JSON over HTTP over
localhost:[port]
.Remember to mention that mesher-node assumes its computer isn't hostile!