aboutsummaryrefslogtreecommitdiffstats
path: root/src/protocol/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol/README.md')
-rw-r--r--src/protocol/README.md136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/protocol/README.md b/src/protocol/README.md
new file mode 100644
index 0000000..c6b4512
--- /dev/null
+++ b/src/protocol/README.md
@@ -0,0 +1,136 @@
+This is a walk-through of the protocol implementation. Hope it will be
+helpful if you want to review/hack on it.
+
+## `anti_replay.rs`
+
+Anti replay algorithm from RFC 6479. It is mostly a straightforward
+translation from the C code there, with only one notable difference:
+the handling of seq number zero.
+
+It is reasonably well tested.
+
+## `cookie.rs`
+
+Cookie signing, verification, cookie reply message generation and
+parsing.
+
+It is reasonably well tested.
+
+## `timer.rs`
+
+Timer facility. Uses the hashed timing wheel algorithm. It is
+optimized for WireGuard use cases (frequent operations on a mostly
+fixed set of timers) with the "activated" atomic boolean flag.
+
+It is under tested.
+
+## `ip.rs`
+
+Parsing of IP(v6) packets.
+
+## `types.rs`
+
+Some common types and constants.
+
+## `handshake.rs`
+
+Handshake initiation and response message generation and parsing.
+
+It is reasonably well tested.
+
+## `controller.rs`
+
+This beast is the most complex... It manages all the states, timers
+and does the actuall IO. It also has a lot of locks and `Arc`s.
+
+`WgState` represents the state of a WireGuard interface. It contains a
+hash table that maps pubkeys to peers, another hash table that maps
+session IDs to peers, and routing tables that map allowed IP(v6)
+addresses to peers.
+
+The ID table changes often and needs to be carefully kept in sync with
+actuall peer states. (Or we will leak memory.) For this we use
+`IdMapGuard` which when dropped will automatically remove an ID from
+the map.
+
+`PeerState` represents the state of a peer. It is shared across the
+maps and timers with `Arc<RwLock<_>>` (or `Weak<RwLock<>>` for
+timers).
+
+The actually IO happens in two threads, one for processing UDP
+datagrams, another for processing packets from the TUN device. (It is
+possible to use more threads, but there does not seem to be much
+benefit without also using SO_REUSEPORT or multi queue tun device.)
+
+The UDP thread repeatedly `recv_from` the socket, and take action
+based the type of the message.
+
+The TUN thread repeatedly `read` packets from the TUN device, find the
+corresponding peer by looking up the route tables, encrypt them and
+send them out if a valid session exists, and/or initiate handshake if
+necessary.
+
+### Lock Order
+
+Because we use a lot of locks, care must be taken to avoid deadlock.
+We adhere to the following partial order:
+
+ info > pubkey_map > any peers > id_map > anything else
+ any peers > rt4 > rt6
+
+Locks whose order are not defined should not be held at the same time.
+
+### Timer Management
+
+Each peer is associated with the following timers:
+
+#### `rekey_no_recv`
+
+Initiate handshake because we have send a transport message but
+haven't received any in 15s (KEEPALIVE_TIMEOUT + REKEY_TIMEOUT).
+
+It is activated and set to 15s when we send a (non-keep-alive)
+transport message, unless it is already activated.
+
+It is de-activated when we receive a transport message.
+
+#### `keep_alive`
+
+Send a keep-alive message because we have received a transport message
+but haven't sent any in 10s (KEEPALIVE_TIMEOUT).
+
+It is activated and set to 10s when we receive a (non-keep-alive)
+transport message, unless it is already activated.
+
+It is de-activated when we send a transport message.
+
+#### `persistent_keep_alive`
+
+Persistent keep-alive.
+
+It is activated and set to the configured interval when a new session
+is established, or when we send a transport message.
+
+#### `clear`
+
+Clear handshake and all transport sessions, and de-activate all
+timers, because no new session has been established in 9min (3 *
+REJECT_AFTER_TIME).
+
+It is activated and set to 9 min when we initiate a handshake, unless
+it is already activated.
+
+It is activated and set to 9 min when a new session is established.
+
+#### Not managed by timer
+
+`REKEY_AFTER_TIME` is not managed by a timer. Instead, a `created`
+time-stamp is stored within each transport session, and compared with
+when sending messages, to decide on whether to rekey.
+
+The secret used to calculate cookies, which is supposed to change
+every two minutes, is also handled this way.
+
+### Testing
+
+This module is under tested.