Every node is an anchor, and every anchor is the same
The anchor protocol is the only thing that carries traffic on a VeilNet network. This is the model it follows: what an anchor is, who it will talk to, how it finds and reaches the others, and what it does and does not promise.
On this page
What an anchor is
An anchor is a node on the overlay, and every node is one. There are no node classes. Whichever anchor happens to be reachable will help a newcomer find the realm, introduce two peers that cannot see each other, and carry traffic for a pair that cannot connect directly.
To what runs on top of it, the overlay is one Ethernet segment, and each anchor's segment holds only the members it may exchange data with. Its switch is filled in from the membership rather than learned, so a frame for an address nobody holds is dropped rather than flooded, and broadcast and multicast are flooded one hop at a capped rate.
Through a host interface the segment carries IP alone. The overlay is IPv6, IPv4 is translated into IPv6 before it enters, and there is no ARP: every neighbour is already known. An application with an anchor built in can put any other EtherType on the segment directly.
IP runs over the overlay unchanged, and an application with an anchor built in can send any EtherType. Beneath it, every frame is sealed for its destination, and beneath that, only admitted members can open a connection at all.
Identity is a key
An anchor's identity is an ML-DSA public key. There is no registry and no naming authority above it. The AnchorID is derived from the key, so claiming an identity means holding the private key for it, and nothing else does.
The key pair comes from a 32-byte seed, and the seed is the identity. Anyone holding it holds the anchor, so it is treated like an SSH host key, and it is small enough to back up on paper. An identity is never rotated: a new key is a new anchor.
The address works like IPv6 SLAAC, with the AnchorID standing in for the hardware address. Every member can compute every other member's address, so nothing hands addresses out. The key shown is the default suite's.
Addresses follow from the same keys. The overlay's IPv6 prefix, a /48 inside the unique-local range, is derived from the identifier of the tree's genesis root, so the whole tree shares it, two trees never collide, and nobody draws up an address plan. An anchor's address inside that prefix is derived from its AnchorID, so every member can compute every other member's address before either has started.
Realms and credentials
A realm is a root key, and a tree of realms grows from one, the genesis. What members must agree on before either has proved anything, such as the address space and the taint tags, is derived from the genesis root that every member of the tree pins, a sub-realm's members included, so a realm needs no configuration beyond that one key. There is no shared secret, anywhere.
Membership is a credential: a signature, from the realm's root or from a key it delegated to, saying that this anchor belongs. An anchor presents its chain of credentials to each peer, and the peer checks it back to the root before any data flows. It is the arrangement a certificate authority already is: a root, a chain, and nothing held in common.
- Every credential has an expiry, chosen by whoever signs it.
- Renewing is signing a fresh credential. A running anchor takes it in place, without dropping a session.
- A renewal must keep the anchor in the same realm, with the same taints. Moving it to another realm is a fresh start, and moving its compartments is a Taints order.
- It is a post-quantum PKI tree, not a blockchain: every link is an ML-DSA signature, and there is no ledger, no consensus and no history.
Delegation, and the cut
A realm can delegate. Its root hands a realm of its own to another key, which admits its own anchors and may delegate again, as many levels as its delegation allows. That is how an organisation's root node runs a sub-realm for each site beneath its own realm.
Delegate. A root signs a credential for each realm beneath it, and each of those realms admits its own anchors. A delegation has an expiry, like any other credential.
Lapse. When a delegation is not renewed, the tree is cut at that edge, and nothing is revoked. The realm beneath carries on as a tree of its own, its members still admitting each other.
Its operators are told it has been cut off; its members carry on.
Renew. Renewing a delegation is one signature, installed on one anchor. The rest of the realm learns it by gossip, and the edge is whole again.
Powers
A credential also says what its holder may do to the other members of its realm. Each power is named, and a credential grants only the powers it names.
| Power | Lets its holder |
|---|---|
telemetry | Ask another member how it is: its status, its routes and its counters |
subnets | Read or rewrite the networks another member forwards for the realm |
block | Make an anchor of its own realm an outsider to every member, and lift a block |
taint | Read or move another member's compartments while it runs |
all | Every power, including any a later build defines |
- A chain grants what every link on it grants. Powers are intersected down the chain, so a realm delegated without a power cannot grant it however it signs, and nor can anything beneath it.
- A delegation grants
allunless-capsnames less, because it hands a realm the right to run itself. An anchor credential grants none unless-capsnames some, so an ordinary member can do nothing to another. - The root node is the anchor whose credential carries every power in its realm. It uses them through the gossip controls.
What crosses a realm boundary
| Permission | Allowed between |
|---|---|
| Connect | The same realm, or two realms on one line of descent |
| Serve: carry a circuit | The same realm, or a realm anywhere above carrying for one below |
| Collect telemetry | The same realm only, and only by an asker whose credential carries telemetry. It is an order |
| Block | The same realm only, and only with the block power |
| Exchange data | The same realm only |
A realm above may relay its descendants' traffic: sealed end to end, it can neither read it nor send any of its own into that realm. Two realms side by side never exchange anything at all.
Data does not widen. A realm above can carry its descendants' traffic without being able to read it or send any into it, which is also what lets two realms reuse one address range. Two realms side by side never meet at all, so one organisation's anchors never become another's transit.
Nor does running a realm. Blocking and collecting follow data's rule rather than serving's: delegating a realm hands over the running of it. A realm above may carry a descendant's traffic, and may neither shut it out nor question it.
Taints
Inside a realm, taints decide which anchors may exchange data. A taint is a label such as prod, lab or a generated string, and the rule is containment, not overlap: two anchors exchange data only if one of them carries every taint the other does.
Taints are granted by the credential. The root that admits an anchor puts it in its compartments: the credential commits to a digest of the set, and the anchor must start under exactly that set or it is refused. A renewal that grants other taints is refused too, so a member cannot put itself in a compartment.
The hub carries only the label every spoke has, so it reaches them all; spokes with different second labels cannot reach each other.
- A ↔ BA's set is contained in B's
- C ↔ Dnothey share {x}, but neither contains the other
- A ↔ CA's set is contained in C's
- B ↔ Dthe same set
- A ↔ DA's set is contained in D's
- B ↔ Cnothey share {x}, but neither contains the other
Taints decide data and nothing else: machines in different compartments still connect, find each other, relay for each other, and receive the realm's orders and knowledge. They just cannot exchange data. A real anchor carries up to 32 taints, each granted by its credential.
- Generality is reach. An anchor with fewer taints reaches more of the realm, so the label everyone shares is the one worth choosing carefully.
- An anchor with no taints is not exempt. It carries the realm's default compartment, so starting to taint a realm means tainting all of it.
- Taint names are not secrets. Anyone who knows the tree can compute the tag for a name they can guess: a generated name is unguessable, and
prodis not. A member that guesses one learns which peers are in it, and cannot join it. - An anchor carries at most 32 taints. A name is 1 to 64 bytes of printing characters, in any script, with no whitespace and no
@or+, which bind a served network to compartments.
Moving a member while it runs
A member holding the taint power can move another to other compartments with a Taints order. The member moved writes the grant down, moves at once, and publishes a taint record into the realm's knowledge, and every peer holds it to the newest record. A member started without a state directory refuses to be moved, since it would forget the move at its next start.
A data send to a moved member whose record has not reached the sender yet waits for it, for as long as the sender's deadline allows. Control traffic does not wait, because taints do not gate it.
Admission, in three stages
An anchor admits a peer in three stages, and nothing is admitted before the third one completes.
The knock. Before anything else, the dialler sends a sealed knock carrying proof of membership. A member's knock is answered.
Anyone else gets silence, not even a refusal. The port behaves like port security on a switch, and a scanner cannot tell that anything is listening.
The handshake. A TLS 1.3 handshake with hybrid post-quantum key exchange proves each side's identity. It proves who an anchor is, not yet that it belongs.
Membership. Each side checks the other's credential chain back to the root, and its taints, bound to the session just opened. Only then does data flow.
Post-quantum, on every connection
| Layer | With | So that |
|---|---|---|
| Key exchange | Hybrid ML-KEM, the only group offered | Post-quantum key exchange is required on every connection, never merely preferred |
| Identity | ML-DSA-87 | An anchor's name and its signatures are post-quantum |
| End to end | ML-KEM-1024 and AES-256-GCM, with keys rotating every ten minutes | Relays carry traffic they cannot read, and recorded traffic stays unreadable |
A tree can instead be generated in suite 0x02, which uses ML-DSA-65 with ML-KEM-768 at category 3 for a smaller handshake. The suite is chosen once, when the genesis is generated, and every key in the tree follows it.
Every hop between two anchors is encrypted, and the whole path is sealed end to end, separately. That second layer is what makes a relay blind rather than merely trusted. Recorded traffic is not decryptable by a future quantum computer.
Finding and reaching peers
An anchor starts knowing one address and ends up knowing the whole realm. There is no directory server: a realm is a known, bounded set of members, so finding a peer is a lookup in what gossip has already delivered.
Bootstrap. Any member's address is a usable starting point. The new anchor dials it, and news of the arrival spreads peer to peer.
On a local network, a sealed probe finds members of the same tree with no address at all. The probe decides who is worth dialling, never who is let in.
Learn your address. An anchor cannot see the address it appears from behind a NAT, so its peers tell it. Their reports are weighed one peer, one vote, which also reveals whether the address changes with the destination.
Punch through. Two anchors behind NATs coordinate through a peer they share, then dial each other at the same moment. Most home and office NATs open a direct path this way.
Or relay. Where a NAT gives a new address for every destination, no punch can land. Traffic stays relayed through a member both ends can reach, sealed end to end as always.
Changes travel as soon as the network can carry them, never on a timer. An anchor that is leaving says so; silence is never passed on as a departure, so a network that splits heals by itself.
Routing
Reaching another anchor is a computation, not a protocol. The sender plans the whole route from what gossip has told it, so routes are loop-free by construction. Which route it takes, it learns from measurement.
A direct connection, where there is one, is one of the paths the anchor scores, and the first it tries. A path costs the sum of the round trips on every leg, the last one to the destination included, so a direct path and a relayed one are compared like with like. Traffic stays on the path it is using until the learner rates another clearly better, twenty times over and for long enough to count. Then it moves, off a direct connection as readily as off a relayed path, and the direct connection stays up.
The sender computes the route itself, from what gossip has told it. A direct connection is one of the paths it scores, and traffic leaves one only for a path rated clearly better. The circuit's onion header is the same size whatever the route, so no relay can tell how far it is from either end.
- Relaying is offered, never requested. Anchors relay by default, except where they are known to sit behind a NAT that makes them a poor relay.
- A relay is not a hub. Once two anchors punch through, their traffic moves to the direct path, and goes back through a relay only if a relayed path is rated clearly better.
Addresses on the overlay
IPv6 is the overlay's own address family, and every anchor's IPv6 address is derived from its identity. IPv4 is different. Thirty-two bits are too few to derive without collisions, so an anchor's IPv4 is whatever its operator chooses, another anchor's included, because it never reaches the overlay as IPv4: traffic sent from it is translated into IPv6 from the derived address.
- The same IPv4 can exist in two realms without conflict. An overlay address means nothing without its realm.
- Several anchors at one IPv4 are one destination. Each flow, one host talking to that address, is given one of them by what reaching each costs, and keeps it.
- A private IPv4 is advertised, and peers reach the anchor at it. A public one is sent from and never advertised.
Subnet routers and exits
An anchor can offer more than itself. A subnet router offers a private network it is attached to, so machines with no anchor at all can be reached across the overlay. An exit offers the public internet. The client's only setting is whether to use an exit.
A subnet router offers a private network it is attached to; an exit offers the internet. Both offers spread by gossip, and a client's taints decide which router it may use. On Linux with a host interface, the anchor sets its host up to forward as it starts and puts it back as it stops; without one, it forwards from its own process.
- Offers spread by gossip, so clients need no per-router configuration. The compartments choose the router: an offer is usable only by anchors whose taints permit it, and a router can narrow one network to some of its compartments, as
-serve-subnets lab0@labdoes. -serve-subnetsalone serves every private network the host is on, and follows them as they come and go. A holder of thesubnetspower can rewrite what a router serves while it runs, and an anchor started with nothing to serve starts forwarding when it is given something.- Load is shared per flow: one host talking to one destination. A new flow's router is chosen by weighted rendezvous hashing on what reaching the destination through each costs, and the flow keeps it until it has been idle for fifteen minutes or the router leaves, so a connection never changes hands mid-way.
- The networks an anchor offers are its egress filter. An exit refuses private ranges, and traffic that arrived from the overlay never leaves by it again.
A hole in the realm's edge, opened deliberately
Offering a route is the operator's decision, and it is the one that changes the host. On Linux with a host interface, a router sets its own host up as it starts and puts it back as it stops: forwarding, router advertisements, masquerade of the translation pool and the overlay, MSS clamping, and accepting forwarded traffic past the firewall. All of it is runtime only, and nothing is saved to survive a reboot. On other systems the anchor names the commands and leaves them to the operator.
Without a host interface, a router forwards TCP and UDP from its own process, with no privilege and nothing on the host set up. Separately, every anchor with a host interface lets its own UDP ports in past the host's firewall while it runs, and takes them out as it stops.
Ways to run an anchor
| Mode | What the host sees | When to use it |
|---|---|---|
| Interface | A network interface that any program can use | Servers and laptops that should simply be on the network. Needs administrator rights and the host's IPv6. One per host; a second runs in a container of its own. |
| Userspace | Nothing; the overlay lives inside the anchor | Containers, CI, and applications that only talk to other anchors. Needs no privilege, and can still be an exit or a subnet router, carrying TCP and UDP from its own process. |
| Reverse proxy | Nothing, except the services it publishes | Publishing a service at an overlay port, with no interface. The service needs no changes. |
| Uplink | A serial line, instead of a network | Machines with no IP network beneath them. One link carries one peer. |
| Low latency | No difference | Real-time traffic: a lost frame stays lost rather than holding up the ones behind it. |
| Embedded | Whatever the app or phone chooses | Apps and phones carrying an anchor of their own. An embedded anchor starts with credentials it was given and cannot issue any. |
Conflux runs the first two of these as conflux up and conflux proxy, and either of them over an uplink.
Gossip controls
A realm is run by its own members. The gossip controls are its control plane, in two forms: an order, which one member gives one other and is over when it is answered, and the realm's knowledge, which every member holds for as long as it lasts. A member holding a power uses it through them. On a private network the root node holds them all.
| Control | Form | What it does | Needs |
|---|---|---|---|
| Telemetry | Order | Reads one member's status, routes and counters, never its peers or its traffic | telemetry |
| Subnets | Order | Reads or rewrites what one router serves, which it keeps across restarts | subnets |
| Taints | Order, then a taint record | Moves one member to other compartments; the member publishes the record | taint |
| Block and unblock | Knowledge | Makes an anchor an outsider to every member, or lifts that | block |
Orders
An order is signed by the member giving it and carries that member's credential chain, so the member it names checks it against the root both pin and trusts nothing about whoever carried it. It goes to that member alone, end to end, so a relay of any realm carries it and reads none of it. It lives as long as its sender waits for the answer, ten minutes at most, and is not carried out after that.
The realm's knowledge
Knowledge is signed entries that every member holds. A member with a state directory writes them down there, so when it restarts it holds them before it meets anybody. Blocks, unblocks and taint records are knowledge.
- It spreads as a tree, not an epidemic. The issuer splits the members it knows into up to eight groups and hands the entry to one member of each, which does the same with its share. Every member is handed it once, in about log₈(N) hand-overs for a realm of N members, each bounded at 25 seconds.
- A member that was away is caught up. Two members compare fingerprints of what they hold whenever they link up, and exchange only what differs.
- Nothing deleted comes back. An entry carries a horizon, how long it must be remembered after it stops being true, and members keep a deletion at least as long as what it replaced. An entry can also silence an issuer: a block makes what its target signs from then on count for nothing.
- It is checked as of when it was signed. Every member checks an entry against the root it pins, with the issuer's chain as it stood at signing, so an entry outlives its issuer's credential. One signed more than ten minutes ahead of a member's clock is refused.
- It is not a ledger. A member holds the latest word from each issuer about each subject, and forgets an entry once nothing needs it. There is no history and no consensus.
- Some things only an anchor may say about itself. Its taint record is signed by the anchor it is about and carries the order that moved it. Its departure, which travels with the membership gossip rather than as knowledge, is signed by the anchor leaving.
What they reach
Control traffic is not gated by taints. Orders and knowledge pass the realm gate alone, so a member is reachable by its realm whatever compartment it is in, including by the order that moves it.
They stop at the realm boundary. Orders and knowledge never leave the realm they belong to. A realm above carries a descendant's traffic, and can neither shut it out nor question it. Each realm is run by the members of it that hold its powers, and the root node holds every power in its own.
Revocation: expiry and blocks
There are two ways to remove an anchor from a realm, and they answer different needs. Expiry is permanent, and takes as long as the anchor's credential has left to run. A block makes the anchor an outsider on each member as it spreads, and lasts until a member lifts it or the days it names run out. It leaves the credential untouched. To remove a machine now and for good, use both.
| Expiry | Block | Both | |
|---|---|---|---|
| How | The issuer stops renewing the anchor's credential | A member holding the block power signs an entry in the realm's knowledge naming the anchor | Block it, and stop renewing it |
| Who can | Whoever issues the anchor's credential | A member of the anchor's own realm whose credential carries block | The issuer, and a holder of block in the same realm |
| Takes effect | When the credential lapses: within its lifetime, thirty days by default | On each member as the block reaches it, in a handful of hand-overs | As the block spreads, and for good at the lapse |
| Can it be undone | Yes, by issuing a fresh credential | Yes. Any holder of block may unblock, whoever issued it | Only by lifting the block and issuing a fresh credential |
| How long it lasts | For good: a lapsed credential stays lapsed | Until a member unblocks it, or for the days it names | For good |
| Needs the target reachable | No. Nothing is sent anywhere | No. Every member holds the block and hands it to members that were away | No |
Expiry is permanent but waits out the credential's lifetime. A block holds on each member as it arrives and lasts until its end or until a member lifts it, and it leaves the credential untouched. Together they shut a machine out now and remove it for good.
Expiry
A credential that is not renewed lapses, and from that moment every peer refuses its holder, and live connections are closed. Nothing is distributed and no list is kept. The credential's lifetime is the removal window, and whoever issues credentials chooses it: a shorter lifetime removes a machine sooner, and is renewed more often.
Blocks
A block does not stop an anchor, and the anchor is told nothing. It makes the anchor an outsider to its realm: every member the block reaches treats it as it treats an anchor of another tree. Its knock is refused, its connections are closed, nothing is dialled, routed, carried or sealed to it, and what it signs from the block on counts for nothing.
It is one command, block -target ID [-days N] [-reason TEXT]. unblock -target ID lifts one, and blocks lists them.
- It needs the power and a proved target. The issuer's credential must carry
block, and the target must have been proved to be in the issuer's own realm, by a connection or a fetched credential chain. An AnchorID nothing has met is refused rather than blocked on trust. - The realm holds it, not the issuer. A block is an entry in the realm's knowledge. Every member holds it, writes it down and hands it to a member that was away, so no connection to the target is ever needed. It spreads member to member in a handful of hand-overs.
- It can be lifted. Without
-daysit lasts until a member unblocks it, and any holder ofblockmay unblock, whoever issued it. With-daysit ends at that instant on every member. A mistyped AnchorID is one unblock away from being undone. - It outlives its issuer's credential. A block is checked against the issuer's chain as of when it was signed, so it stays in force after that credential lapses.
- It is not a revocation. The credential still verifies, and a member the block has not reached yet still admits the anchor. Removing a machine for good is still expiry. A block is what to reach for when expiry is too long to wait.
- It stays in the realm. A realm above may carry a descendant's traffic and may not block it, whatever its own credential carries.
What it does not promise
Each of these is a deliberate boundary, not an oversight.
- Timing and volume are untouched. Nothing here hides traffic analysis; only cover traffic would.
- A relay is an admitted member, and it is not trusted. It cannot read, alter or impersonate what it carries, but it can see the hops beside it and how much passes, and it can drop traffic.
- Taint names and the tree's identifier are public to anyone who knows the realm.
- Removal is not instant. Expiry takes as long as the credential has left. A block is in force on each member as it arrives, and a member it has not reached yet still admits the anchor.
- During pre-release, the protocol may change incompatibly between versions.
Where next
The guardian stack is an optional console beside the root node: it manages the credentials in an organisation's own realm and shows their telemetry, and issues no gossip controls itself. Conflux is how a machine runs an anchor.