root: TCP relay server
zetok opened this issue · comments
zetok commented
https://zetok.github.io/tox-spec/#tcp-server
Everything for server is done except for Onion packets.
- Onion packets parsing #99
- Onion packets nop-handling (it is possible for tcp relay to ignore Onion packets)
- Onion packets handling
Packet parsing
- |
handshake
| - |
0x0
| RouteRequest - |
0x1
| RouteResponse - |
0x2
| ConnectNotification - |
0x3
| DisconnectNotification - |
0x4
| PingRequest - |
0x5
| PongResponse - |
0x6
| OobSend - |
0x7
| OobReceive - |
0x8
| OnionDataRequest - |
0x9
| OnionDataResponse - |
0x10
-0xF0
| Data
Logic
- |
handshake
| - |
0x0
| RouteRequest - |
0x1
| RouteResponse - |
0x2
| ConnectNotification - |
0x3
| DisconnectNotification - |
0x4
| PingRequest - |
0x5
| PongResponse - |
0x6
| OobSend - |
0x7
| OobReceive - |
0x8
| OnionDataRequest - |
0x9
| OnionDataResponse - |
0x10
-0xF0
| Data
Network
- |
handshake
| - |
0x0
| RouteRequest - |
0x1
| RouteResponse - |
0x2
| ConnectNotification - |
0x3
| DisconnectNotification - |
0x4
| PingRequest - |
0x5
| PongResponse - |
0x6
| OobSend - |
0x7
| OobReceive - |
0x8
| OnionDataRequest - |
0x9
| OnionDataResponse - |
0x10
-0xF0
| Data
Roman commented
I reverse engineered TCP handshake. Here it is.
pk = public key
sk = secret key
TCP handshake
1. Client:
Has:
* client_pk
* client_sk
* server_pk
Computes and Stores:
* client_sent_nonce = random nonce()
Computes:
* shared_key = encrypt_precompute(server_pk, client_sk)
* (temp_client_pk, temp_client_sk) = crypto_box_keypair()
Stores:
* temp_client_sk
Computes:
* payload = [temp_client_pk, client_sent_nonce]
* nonce = random nonce()
* encrypted_payload = encrypt_data_symmetric(shared_key, nonce, payload)
* handshake_packet = [client_pk, nonce, encrypted_payload]
Sends:
* handshake_packet
By now client has:
* server_pk
* client_pk
* client_sk
* client_sent_nonce
* temp_client_sk
2. Server:
Receives:
* handshake_packet
Has:
* server_pk
* server_sk
Computes and Stores:
* server_sent_nonce = random nonce()
Computes:
* [client_pk, nonce, encrypted_payload] = handshake_packet
* shared_key = encrypt_precompute(client_pk, server_sk)
* payload = decrypt_data_symmetric(shared_key, nonce, encrypted_payload)
* [temp_client_pk, server_recv_nonce=client_sent_nonce] = payload
* (temp_server_pk, temp_server_sk) = crypto_box_keypair()
* common_shared_key = encrypt_precompute(temp_client_pk, temp_server_sk)
Stores:
* server_recv_nonce
* common_shared_key
* client_pk
Computes:
* payload = [temp_server_pk, server_sent_nonce]
* nonce = random nonce()
* encrypted_payload = encrypt_data_symmetric(shared_key, nonce, payload)
* handshake_packet = [nonce, encrypted_payload]
Sends:
* handshake_packet
By now server has:
* client_pk
* server_pk
* server_sk
* server_sent_nonce
* server_recv_nonce
* common_shared_key
3. Client:
Receives:
* handshake_packet
Computes:
* shared_key = encrypt_precompute(server_pk, client_sk)
* [nonce, encrypted_payload] = handshake_packet
* payload = decrypt_data_symmetric(shared_key, nonce, encrypted_payload)
* [temp_server_pk, client_recv_nonce=server_sent_nonce] = payload
* common_shared_key = encrypt_precompute(temp_server_pk, temp_client_sk)
Stores:
* client_recv_nonce
* common_shared_key
Removes:
* temp_client_sk
By now client has:
* server_pk
* client_pk
* client_sk
* client_sent_nonce
* client_recv_nonce
* common_shared_key
TCP Communication
Client:
1.
encrypted = encrypt_data_symmetric(common_shared_key, client_sent_nonce, data)
send(encrypted)
increment_nonce(client_sent_nonce) if could encrypt and send
Server:
2.
receive(encrypted)
data = decrypt_data_symmetric(common_shared_key, server_recv_nonce, encrypted)
increment_nonce(server_recv_nonce) if could receive and decrypt
3.
encrypted = encrypt_data_symmetric(common_shared_key, server_sent_nonce, data)
send(encrypted)
increment_nonce(server_sent_nonce) if could encrypt and send
Client:
4.
receive(encrypted)
data = decrypt_data_symmetric(common_shared_key, client_recv_nonce, encrypted)
increment_nonce(client_recv_nonce) if decrypted if could receive and decrypt
Roman commented
Handshake
PK + PublicKey
SK + SecretKey
PcK + PrecomputedKey
Client Network Server
+----------------------------------------------------------+----------------------------------------------------------------------+
+----------------------+ | +----------------------+
| crypto_box_keypair() | | | crypto_box_keypair() |
+----+-------------+---+ | +----+-------------+---+
| | | | |
+-------v----+ +---v--------+ | +-------v----+ +---v--------+
+-+ Session SK | | Session PK +-----+ | +----+ Session PK | | Session SK +---------------------+
| +------------+ +------------+ | | | +------------+ +------------+ |
| +--------------+ | | | +--------------+ |
| | new nonce() | | | | | new nonce() | |
| +------+-------+ | | | +------+-------+ |
| | | | | | |
| +--------v--------+ | | | +--------v--------+ |
| |client_sent_nonce| | | | +-------+server_sent_nonce| |
| +-----+-----------+ | | | | +-----------------+ |
| | | | | | |
| | | +------------+ | | | +------------+ |
| | +-----------------+ | | Server PK | | | | | Server SK +-------------------+ |
| +--------+Payload | | +--+---------+ | | | +------------+ | |
| | | +-----------------+ | | | | | | |
| | | |Session PK <-----+ | | | | | |
| | | +-----------------+ | | | | | |
| | +->client_sent_nonce| | | | | +-----------------+ | |
| | +-----------------+ | | +------------------>Packet | | |
| | +--------------+ | | | | | +-----------------+ +----v--------+ |
| | | new nonce() | | | | | | |Client PK +----------->precomputed()| |
| | +-------+------+ | | | | | +-----------------+ +----+--------+ |
| | | | | | | | +---+Nonce | | |
| | +-------v------+ | | | | | | +-----------------+ +--+----+ |
| | +-------+ Nonce +---------------+ | | | | | |Encrypted Payload| +----------+ PcK | |
| | | +--------------+ | | | | | | | +----------+------+ | +--+----+ |
| | | +------------+ +----------+ | | | | | | | | | | |
| | | | Client SK | |Client PK +---------+ | | | | | +----v---------v---+ | +-----v------+
| | | +-------+----+ +----------+ | | | | | | | +--------->open_precomputed()| | +-->precompute()|
| | | | | | | | | | | +--------+---------+ | | +-----+------+
| | | +--------------+ | | | | | | | | | | |
| | | | | | | | | | | +--------v--------+ | | +-----v-----------+
| | | | | | | | | | | |Payload | | | |Session PcK |
| | | +-------+ +----v------v-+ | | | | | | +-----------------+ | | +-----------------+
| | | | PcK <---------+precomputed()| | | | | | | |Session PK +-------------+
| | | +-+---+-+ +-------------+ | | | | | | +-----------------+ | +-----------------+
| | | | | | | | | | | |client_sent_nonce+---------------->server_recv_nonce|
| | | | +-----+ | | | | | | +-----------------+ | +-----------------+
| | | | | | | | | | | |
| | | | +------v------------+ | | | | | | +--------------+ |
| +------------->seal_precomputed() <---------+ | | | | | | new nonce() | |
| | | +---------+---------+ | | | | | +-------+------+ |
| | | | | | | | | | |
| | | | | | | | | +-------v------+ |
| | | +--------v--------+ | | | | | +-------+ Nonce +---------------+
| | | |Encrypted Payload+------+ | | | | | | +--------------+ | |
| | | +-----------------+ | | | | | | | | |
| | | | | | | | | | | |
| | | +-----------------+ | | | | | | | +------------------+ | |
| | | |Packet +-------------------------+ | | | |Payload +-+ | |
| | | +-----------------+ | | | | | | +------------------+ | | |
| | | |Client PK <------------+ | +------------------->Session PK | | | |
| | | +-----------------+ | | | | +------------------+ | | |
| +--------->Nonce | | | +----------------->server_sent_nonce | | | |
| | +-----------------+ | | | +------------------+ | | |
| | |Encrypted Payload<------+ | | +-----------+ | |
| | +-----------------+ | | | | |
| | | | +--------v---------+ | |
| | +-----------------+ | +------->seal_precomputed()<------+ |
| +----+ |Packet <--------------------------+ +--------+---------+ |
| | +-----------------+ | | | |
| | +-----+Nonce | | | +--------v---------+ |
| | | +-----------------+ | | |Encrypted Payload +----+ |
| | | +---+Encrypted Payload| | | +------------------+ | |
| | | | +-----------------+ | | | |
| +-------v--v-v-----+ | | +------------------+ | |
| |open_precomputed()| | +--------------------------+Packet | | |
| +---------+--------+ | +------------------+ | |
| | | |Nonce <-----------+
| +---------------+ | +------------------+ |
| +--------v--------+ | |Encrypted Payload <----+
| |Payload | | +------------------+
| +-----------------+ |
+------------+ +---+Session PK | |
| | +-----------------+ |
| | |server_sent_nonce+----+ |
| | +-----------------+ | |
| | | |
| | | |
+---v---v----+ | |
|precompute()| +-----+ |
+-----+------+ | |
| | |
+-----v------+ +--------v--------+ |
|Session PcK | |client_recv_nonce| |
+------------+ +-----------------+ |
|
+--------------------------------------------------------+--------------------------------------------------------------------------+
Roman commented
Done in https://github.com/tox-rs/tox/