Trust model
Who can do what to a swarm, and what stands in the way. In short: the swarm key decides who is a member, and members are trusted with everything.
The boundaries
The network. Every transport authenticates the sender of every message, each by
its own key: Mycelium by the public key of the sending daemon, libp2p by the peer ID
of the connection, Tor by a challenge handshake on each connection, in which both sides
prove their node key (transports.md). So a node always knows which address sent it something, though not
who wrote what that message carries (changes are relayed). On top, a node proves its
node ID at each address with a signature by its node key (WHO and ME, peers.md), so a
node is known by its node ID whichever transport and address it uses. A private Mycelium
network (--mycelium-network-key-file, --mycelium-network-name) additionally keeps
other Mycelium nodes from reaching ours at all; on libp2p and Tor, anyone who knows an
address can connect, and the swarm key is what keeps them out.
The swarm key. With --swarm-key-file, a node proves the key in the handshake
before anything else it sends is acted on; until then it is a stranger. Without a
swarm key, every node that can reach a member can join: a joining node doesn't need to
know the swarm ID, and the swarm ID is no secret anyway. The key file should be readable
by its owner only; a node warns at startup if others may read it.
Public infrastructure. Nodes use none unless told to: Mycelium peers are those in
--mycelium-peers, and libp2p reaches only seeds, members and the relays of the swarm.
With --libp2p-public, a node joins the IPFS DHT and may use public relays: they see
whom it talks to and how much (the traffic itself is encrypted end to end), and the DHT
makes its peer ID and addresses public.
The node key. --node-key-file holds the node's own key, from which its node ID
(continuum:<hex>) derives: who the node is, whatever transport reaches it. It is a
secret like the swarm key: readable by its owner only (a node warns otherwise; a key
it creates is).
The HTTP API. Every endpoint but the API description needs a user from
--htpasswd. It listens on 127.0.0.1:3000 by default (--bind-addr) and speaks
plain HTTP: to expose it, put a TLS proxy in front. All users may read and write user
data and use the admin endpoints (remakes, forgetting peers, exports, log filters).
There are no read-only users: whoever may open the dashboard may also edit and delete
the document's data from it, and its writes reach the whole swarm.
Only the users in --protocol-writers may write protocol data through the store; epoch
metadata and the swarm ID are never writable. The /debug endpoints exist only with
--debug-api.
The configuration. Whoever can write a node's configuration file or its options can
run commands as the node's user: a cmd: (or command) value runs at startup, and a
file: value reads any file the node can (configuration.md, "Importing values").
Protect the configuration like the swarm key.
What members are trusted with
Everything in the document. A member syncs changes to and from its peers, and every node acts on what the document says:
- User data: any member can write or delete any path.
- Who wrote what (
GET /admin/changes): each change names its node and API user as the writing node says; nothing signs that, so a member can name another. The names of the users who write are in the document, and so on every node. - The member registry: each node writes its own entry, but nothing stops a member from writing others'. The registry decides the topology and, through the alive stamps, the electorate of a remake.
- Forget records: any member can make the swarm forget a peer (until it says HELLO again).
- Remakes: any member can propose one, vote, and, as coordinator, decide. Votes are not signed: the votes register says who voted, but any member could write any entry. Every node switches to a committed epoch without counting the votes again.
- Epochs it advertises: a rejoining node follows the epoch ready members advertise, corroborated by two of them once it was ready (one if only one is active, and one before it was ever ready), and downloads the epoch's snapshot from them, checked against its hash.
- What it says about itself: its keepalives and handshake replies say whether it is ready, whether it would sync with the recipient, and how long it last heard from it (which counts towards the recipient's stability tier). Nodes believe that: a member claiming to be ready can become a joining node's catch-up source (though one with an empty document can't make it ready: empty heads prove nothing), and one misreporting absences can move a node between tiers.
So a member that misbehaves, by a bug or on purpose, can rewrite or delete data, manipulate the registry and the electorate, forge votes, commit a remake without a majority, and make the swarm forget peers. Nothing but the swarm key protects against that; keep it to nodes you trust as much as your data.
What depends on clocks
Nodes don't agree on time; each judges by its own clock: voting periods, when a remake
expires and may be aborted by others, the replay window, alive stamps (and so the
electorate). Keep the clocks within a grace period (four keepalives) of each other,
e.g. with NTP. A node whose clock is further off can, together with an operator's
abort, make a remake contested (remakes.md, Limits). A node compares its clock with its
peers' and warns when its own is off (--clock-skew-warn; measurements.md, Clocks).
What a stranger can do
Send messages. Before it proves the swarm key, a node ignores everything from it but the handshake, and doesn't sync with it. A stranger can still cost a node the work of reading and dropping its messages.
What protects against mistakes
Not against a hostile member, but against honest ones getting in each other's way:
- Majority voting with one vote per member and epoch: two remakes can't both commit
(
remakes.md). - A snapshot every node builds itself and checks against the committed epoch, and downloads checked against their hashes.
- Protocol data writable through the API only by
--protocol-writers, and logged.
Not yet
Revoking a single member, or limiting what a member may do, needs per-node keys: a
member list in the document, with keys that sign what each node writes about itself
(its registry entry, its votes). See review-rejections.md, "Author binding for remake
votes and decisions".
