"Thee packets that are chosen needeth not fear purgatory, for theeshall be safe with my blessing. Confess thy sins and thy shall enterthe heavens."
Sanctum 1:1
This is a very small, reviewable, capable, experimental and fully privilegeseperated VPN daemon capable of transporting encrypted network trafficbetween two peers.
WARNING: This code uses an experimental AEAD cipher based onKeccak-f[1600,24] to provide confidentiality and integrityfor transmitted session keys during the key exchange.
Due to its privilege separated design, sanctum guarantees thatall of its important assets are separated from the processesthat talk to the internet or handle non-cryptography relatedthings.
Whats with the weird mythology around this project?
It's fun, but it doesn't make it less of a serious project.
There are several processes that make up a sanctum instance:
Process name | Description |
---|
bless | The process responsible for encrypting packets. |
confess | The process responsible for decrypting packets. |
chapel | The process responsible for deriving new TX/RX keys from a key. |
heaven-rx | The process receiving packets on the inner interface. |
heaven-tx | The process sending packets on the inner interface. |
purgatory-rx | The process receiving packets on the outer interface. |
purgatory-tx | The process sending packets on the outer interface. |
pilgrim | The process handling TX keys when running in pilgrim mode. |
shrine | The process handling RX keys when running in shrine mode. |
cathedral | The process forwarding traffic when running in cathedral mode. |
liturgy | The process responsible for autodiscovery of peers in a cathedral. |
bishop | The process responsible for configuring autodiscovered tunnels. |
Each process can run as its own user.
Each process is sandboxed and only has access to the system callsrequired to perform its task. There are two exceptions, guardian(the main process) is not sandboxed nor seccomped, and bishop.
The guardian process is only monitoring its child processes and has noother external interfaces. The bishop process must be privileged due tothe fact it is fork+exec'ing the hymn configuration tool for setting upnew tunnels.
The processes share packets between each other in a very well defined way.
For incoming packets:
purgatory-rx (black) -> confess (decryption) -> heaven-tx (red)
For outgoing packets:
heaven-rx (red) -> bless (encrypt) -> purgatory-tx (black)
When the processes start they will remove any of the queues they do notneed for operating.
As an example of why this is important, it is impossible for a packetthat arrives on the plaintext interface to be moved to the ciphertextinterface without passing the encryption process.
A sanctum instance is responsible for sending itsRX key tothe other side. It does this by periodically generating a newkey uniformly at random and wrapping it with a secret derivedfrom the underlying shared secret between both parties.
See docs/crypto.md for details on the session key and shared secrets.
Note that sanctum only supports symmetrical keying and does notimplement any asymmetrical key exchange method.
Your shared secret must be handled withgreat care andmust be rotatedoften. When using a cathedral you can usethe Ambry distribution to update shared secrets.
The encrypted traffic is encapsulated with ESP in tunnel mode, usingincrementing 64-bit sequence numbers. The traffic is either encryptedwith AES256-GCM or Agelas and are encrypted under keys exchanged as describedabove.
In both cases a 96-bit nonce constructed as follows is used:
nonce = 32-bit salt from key exchange || 64-bit packet counter
You can select what cipher to use by specifying a CIPHER environmentvariable at compile time with either:
- nyfe-agelas (Agelas as provided by Nyfe).
- openssl-aes-gcm (AES256-GCM via OpenSSL its low level API).
- intel-aes-gcm (AES256-GCM via Intel its highly performant libisal_crypto lib).
Sanctum supports unidirectional tunnels, this is called the pilgrimor shrine mode.
In pilgrim mode, sanctum will be able to send encrypted traffic to itsshrine peer. It will however never send anRX key to its peer (a shrine).
In shrine mode, sanctum will be able to verify and decrypt the arriving trafficbut will never receive aTX key from its peer.
This allows one-way traffic to flow from a pilgrim to the shrinewith a strong guarantee that the shrine cannot send data back(there are no keys).
A cathedral is a sanctum mode that can run on a machine somewhereand will relay packets between tunnel end-points without being ableto read, inject or modify packets.
Peers can use a cathedral to move to a peer-to-peer end-to-end encryptedconnection if both peers are behind a not too restrictive NAT.
A cathedral may also be used as an Ambry distribution point forshared secret rollover.
Please read docs/cathedral.md for more.
A default build requires pkg-config and libssl-dev.
$ git clone https://github.com/jorisvink/sanctum$ cd sanctum$ make# make install
If this is to complicated for you, this isn't your software.
Sanctum builds on MacOS 13+, OpenBSD 6.8+ and Linux-y things like Ubuntu 22.04.
Sanctum uses a configuration file. Find an example ofa simple configuration below.
# Name of this sanctum instance.instance laptop# Uncomment if you want l2 instead of l3.#tap yes# Path to the shared secret.secret /etc/sanctum/laptop_secret.key# The control socket for pontifex.run control as joriscontrol /tmp/sanctum-control joris# The tunnel configurationtunnel 1.0.0.1/30 1422# Add additional routes over the tunnelroute 2.0.0.0/24# The local address to which sanctum binds.local x.x.x.x:2333# Optional peer address, ignore if you have a peer that# moves networks a lot.peer y.y.y.y:2333# The encryption and decryption processes.run bless as _blessrun confess as _confess# Run the internal io processes as one user.run heaven-rx as _heavenrun heaven-tx as _heaven# Run the external io processes as another.run purgatory-rx as _purgatoryrun purgatory-tx as _purgatory# Run the bishop as privileged root.run bishop as root# Run chapel for the key exchange as yet another user.run chapel as _chapel