feda/doc/protocol.txt
2026-03-19 06:21:19 +05:00

373 lines
10 KiB
Plaintext

ZERO BYTE (the byte at zero offset of the datagram):
00--BF: first byte of an encrypted message within an established connection
(that is, the first byte of the obfuscated nonce)
C0--DF: means that the actual encrypted message starts with a byte
C0..FF, hence the message begins at the next byte
E0--FF: a message outside of an established connection
Please note the particular value for C0..DF or E0..FF must be randomly
generated for each individual datagram.
MESSAGES OUTSIDE OF ENCRYPTED CONNECTIONS
The least significant half-byte of the Zero Byte is duplicated to form a
byte (e.g., 0xE8 becomes 0x88); the second byte is XOR'ed with this value.
The result of the XOR is the command:
14 ("Introduce Yourself") request for the peer's credentials
2 1 0 (in future, this might change)
3..363 361 random padding
1A ("I Am") self-introduction
2..33 32 master_pub
34..65 32 master_hash
66..129 64 master_hash_sign
130 1 point id
131 1 "signed-by" code (0x00 or 0xff)
132..183 52 zero point cert (for signed-by==0x00 only)
184..247 64 signature for zp cert (... -- // -- ...)
248..299 52 this point cert
300..363 64 signature for this point cert
57 ("STub") senseless datagram to raise "response credit"
2..127 126 random padding
7E ("TEst") I'm willing to test my NAT (and here's my public key)
2..33 32 the public key
34..127 94 random padding
7F reply on 7E
2..33 32 the kex public key of the responder
(the rest is a cryptobox)
34..41 8 nonce
42..57 16 MAC
(the rest is encrypted)
58..63 6 your (visible) addr/port, MSBF
64 1 your current stub credit
65 1 reserved (zero)
66..125 60 up to 10 ip/port pairs of the friendly peers
126..127 2 random padding
# 9A ("please ask") please ask to contact me (unassoc. peers)
# 2..7 6 addr/port to ask, MSBF
# 8..127 120 random padding
#
#
# 9C ("please contact") please contact the given address (unassoc. peers)
# SENSELESS! One can't "ask" a restricted cone
# peer unless it's associated, and there's no
# point in asking a fullcone/nonNAT peer for
# anything
# 2..7 6 addr/port to contact, MSBF
# 8..127 120 random padding
A5 ("ASsociate") here's my public key for Diffie-Hellman, I know yours
(you perhaps know mine, as well, but you could forget it)
2..33 32 the kex public key
(the rest is a cryptobox)
34..41 8 nonce
42..57 16 MAC
(the rest is encrypted)
58..67 (0) 10 node id
68 (10) 1 point id
69 (11) 1 "signed-by" code (0x00 or 0xff)
70..121 (12) 52 zero point cert (for signed-by==0x00 only)
122..185 (64) 64 signature for zp cert (... -- // -- ...)
186..237 (128) 52 this point cert
238..301 (180) 64 signature for this point cert
302..305 (244) 4 timemark (minutes since Epoch)
306..313 (248) 8 nonce2
314..377 (256) 64 signature for: kex_pubkey+timemark+nonce2
(320)
C4 ("Change keY") your encrypted dgram looks strange, here's the actual key
2..33 32 the kex public key
34..41 8 nonce from the err. packet, obfuscated
42..45 4 timemark (minutes)
46..53 8 nonce2 (from our counter)
54..117 64 signature for all the previous
118..127 10 random padding
E8 ("error") You sent me something strange or unsupported
2 1 error code
3..127 125 random padding
EC ("echo") echo request
2..33 32 the public key
34..37 4 timemark (minutes)
38..45 8 nonce
46..127 82 random padding
ED ("echoeD") echo reply
2..33 32 the kex public key of the responder
(the rest is a cryptobox)
34..41 8 nonce
42..57 16 MAC
(the rest is encrypted)
58..63 (0) 6 your (visible) addr/port, MSBF
64..67 (6) 4 timemark (minutes) FROM THE REQ.
68..75 (10) 8 echo request's nonce
76..85 (18) 10 node_id (our)
86 (28) 1 point (our)
87 (29) 1 minpref (our)
88..95 (30) 8 nonce2 (from our counter)
96..159 (38) 64 signature for the kex key
for the echo reply, the kex public key from the request is always
used, even when we have an established association with the peer
and its key differs; this is because the peer could have restarted
thus loosing (changing) its kex credentials, and now tries to
reestablish the association with us
F0 ("forward") Not used in the present version of the protocol;
intended for (encrypted) messages that should be
forwarded to another node without decrypting
ENCRYPTED MESSAGE STRUCTURE
[-16..-1] (not in the message, only in the buffer) the part of the
nonce to be zeroed; the byte at [-1] may become a part of
the datagram in case the first byte of the nonce is >= 0xC0
0..7 8 nonce (last 8 bytes, obfuscated; the first 16 are 0s)
8..23 16 MAC
(the rest is ciphertext)
24 1 message type
25..end ? payload
ENCRYPTED MESSAGE TYPES
03 keep alive
25..127 103 random padding
0A please ask to contact me // not implemented yet
25 1 zero
26..31 6 ip/port to ask
32..127 96 random padding
0C please contact
25 1 zero
26..31 6 ip/port to contact
32..127 96 random padding
0E error
25 1 error code
26..127 102 random padding
8x "respond me" -- messages to be responded,
resent in case there's no response
25 1 zero
26..29 4 random cookie
30..507 478 (max) the payload
8C do you know this node?
25 1 zero
26..29 4 random cookie
30..39 10 node id
40..237 198 random padding
9x "so I respond" -- responses for the respective 9x
25 1 zero
26..29 4 the cookie from the request
30..507 478 (max) the payload
9C I do/don't know the node
25 1 zero
26..29 4 the cookie from the request
30..39 10 node id
40 1 status: 0:dunno 1:yes (possibly more in future)
41 1 rank: if 'yes', the rank for the node in q.
if 'no', the responder's min. rank to
be stored in the database
42..73 32 public key (or zeroes for 'no')
74..105 32 hash (or zeroes for 'no')
106..169 64 hsign (or zeroes for 'no')
170..173 4 timestamp (or zeroes for 'no')
174..237 64 sender's signature for 41..173 (or zeroes)
B0 Proxy Outbound (packet from proxyuser to proxy server)
25..30 6 ip/port to forward to
31..507 477 (max) the forwarded datagram
B1 Proxy Inbound (packet from proxy server to proxy user)
25..30 6 ip/port of the original source
31..507 477 (max) the forwarded datagram
Dx data (carries an encapsulated IPv6 packet)
24 1 0xD0 | ((part_cnt-1) << 2) | part_num
25..27 3 peer-local sequential number (wraps)
28..475 448 (max) the payload
The max. payload size is choosen keeping in mind that
we should remain to be able to enclose our packets
(full enclrypted dgrams) into other packets and still
not overcome the 508 bytes limit. The 448 bytes limit
for the payload (476 for the whole dgram) leaves 32
bytes for the encapsulating dgram. Okay, 8 bytes of
nonce, 16 bytes of MAC, 1 byte msg type, 4 bytes to
identify the forwarging stream somehow, and remember
that one byte to escape in case the obfuscated nonce
starts with 0xC0..0xFF... well, still 2 bytes are left
until The Limit. 4+2 may also be the ip:port, but in
this case we'll have no reserve.
Besides that, we keep in mind that one day we may implement
the MTU path discovery as it should be, and after that we'll
use dgrams of greater size, such as 1500 bytes. So we implement
reassembling of dgrams without imposing any size limits. Only
the sending procedures are affected with the limits.
MESSAGE EXCHANGE
***************
* Establishing crypto association
Client Server
echo request (EC) --->
<--- echo reply (ED)
(*if* client doesn't know the server's node)
[failure] (XXX to be changed)
(*if* client has the server's node, but not the server's point)
please introduce (14) --->
<--- i am (1A)
(*if* the client has the server's point cert, initially or after 1A)
associate (A5) --->
(*if* the servers knows at least the node of the client)
<--- keep alive (enc.03)
[ok]
(*if* the server doesn't know the client's node)
[failure] (XXX to be changed)
***************
* Checking NAT
Client Server Sibling(s)
stub (57) ---> *
stub (57) ---> *
stub (57) ---> *
stub (57) ---> *
stub (57) ---> *
test (7E) ---> *
* <--- test R (7F)
plz cnt (enc.0C) ---> *
* <---------------------------- stub (57)
(*if* client received all expected dgrams)
[done]
(*if* client's waiting timed out, only got the server's reply)
("second stage")
echo rq (EC) ----------------------------> *
* <---------------------------- echo rpl (ED)
[done]
***************
* Generic messages
Messages of the types "error" (E8) and "change key" (C4) are sent whenever
it is appropriate, which effectively means something went wrong.
The C4 type is used in situations when an incoming _encrypted_ datagram can
not be decrypted. It is used as indication for the error, but, unlike the
E8 type, it contains the actual KEX public key of the party which detected
the error, and the key is signed by the point's key together with the
current timemark. In (a very common) case when the error was caused by
restarting of the fedaserv instance, this makes it possible for the partner
to recover the cryptographic association with a single datagram of the A5
type ("associate"):
Alice Bob
(any encrypted dgram) --->
<--- change key (C4)
associate (A5) --->
<--- keep alive (enc.03)
[ok]
Unlike the C4 type, a datagram of the E8 type ("error") contains no
authentication info, so it can not be used for automated recovery of any
kind: otherwise, it would be possible for anyone on the Internet to spoof
such a datagram and fool random fedaserv instances into believing something
goes wrong and there's a need for recovery, thus effectively breaking
existing and normally functioning associations. Hence, E8 type dgrams can
only serve as a source of information for human operators, and they are
only sent in situations the software has no recovery procedure for the
error in question (as of now this means all errors except the inability to
decrypt an encrypted dgram). The only thing the receiving party does upon
receiving them is logging a message.
***************
* Established crypto association
There are no exchange procedures for the case of an established
cryptographic association; each type of the encrypted datagrams is used in
the respective situation and is expected to be reacted upon accordingly.