From 408bd60c56cb42a32201bc5a9352076c7ab15084 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Fri, 5 Jul 2024 09:26:58 +0100 Subject: [PATCH] rfc: known servers, server operators --- rfcs/2024-07-05-server-configuration.md | 20 ++++++++++++++++ src/Simplex/Messaging/Agent/Client.hs | 5 ++++ .../Messaging/Agent/Env/KnownServer.hs | 23 +++++++++++++++++++ src/Simplex/Messaging/Agent/Env/SQLite.hs | 10 ++++++++ 4 files changed, 58 insertions(+) create mode 100644 rfcs/2024-07-05-server-configuration.md create mode 100644 src/Simplex/Messaging/Agent/Env/KnownServer.hs diff --git a/rfcs/2024-07-05-server-configuration.md b/rfcs/2024-07-05-server-configuration.md new file mode 100644 index 000000000..6c6a4ff16 --- /dev/null +++ b/rfcs/2024-07-05-server-configuration.md @@ -0,0 +1,20 @@ +# Server configuration + +## Problem + +Currently SimpleX Chat allows maintaining the list of servers, some of which can be disabled. Only enabled servers are passed to the agent configuration. + +With the recent evolution of SMP protocol and XFTP implementation to protect transport information, additional server taxonomy is required in the agent: + +- Known servers: SMP proxy configuration allows to proxy messages only to unknown servers, and it treats enabled servers as known. It would be better to pass all known servers and use them as known, with the disabled servers not used for any new message queues. +- Server usage: with the different level of trust to SMP servers it may be helpful to differentiate the server roles - to use some only as proxies and some others only to receive messages (with the option proxy to all). +- Server operators: some threat model qualities are based on the assumption that servers do not collude. This would be a stronger guarantee if the servers used together in some communication scope were belonging to different operators (e.g. forward message to destinnation server, we could choose proxy belonging to a different operator from a destination server, also when creating reply queue it could be chosen from a different operator). + +## Solution + +Create KnownServer type in the agent and use it to pass the servers. Server choice will use this process: +- filter the servers with the allowed usage - if no server has allowed usage, operation would fail. It means that the list of servers has to be validated (both in the UI and during the agent initialization), or, possibly it can be enforced on type level with NonEmpty lists - we can pass a separate list for each operation. The types in code have separate lists. +- remove servers of the same operator, then if the list is not empty, randomly pick the server. +- if the list was empty, randomly pick different server. It means that when iterating servers in async commands we should separate the initial server and tried servers. + +All servers operated by SimpleX Chat would be marked as known with some of them randomly chosen to be used during the first start. diff --git a/src/Simplex/Messaging/Agent/Client.hs b/src/Simplex/Messaging/Agent/Client.hs index 0467c31f8..0722ceb56 100644 --- a/src/Simplex/Messaging/Agent/Client.hs +++ b/src/Simplex/Messaging/Agent/Client.hs @@ -290,6 +290,9 @@ data AgentClient = AgentClient subQ :: TBQueue ATransmission, msgQ :: TBQueue (ServerTransmissionBatch SMPVersion ErrorType BrokerMsg), smpServers :: TMap UserId (NonEmpty SMPServerWithAuth), + -- smpServersKnown :: TMap UserId (NonEmpty SMPKnownServer), + -- smpServersProxy :: TMap UserId (NonEmpty SMPKnownServer), + -- smpServersReceive :: TMap UserId (NonEmpty SMPKnownServer), smpClients :: TMap SMPTransportSession SMPClientVar, -- smpProxiedRelays: -- SMPTransportSession defines connection from proxy to relay, @@ -298,6 +301,8 @@ data AgentClient = AgentClient ntfServers :: TVar [NtfServer], ntfClients :: TMap NtfTransportSession NtfClientVar, xftpServers :: TMap UserId (NonEmpty XFTPServerWithAuth), + -- xftpServersKnown :: TMap UserId (NonEmpty XFTPKnownServer), + -- xftpServersEnabled :: TMap UserId (NonEmpty XFTPKnownServer), xftpClients :: TMap XFTPTransportSession XFTPClientVar, useNetworkConfig :: TVar (NetworkConfig, NetworkConfig), -- (slow, fast) networks userNetworkInfo :: TVar UserNetworkInfo, diff --git a/src/Simplex/Messaging/Agent/Env/KnownServer.hs b/src/Simplex/Messaging/Agent/Env/KnownServer.hs new file mode 100644 index 000000000..604bb4580 --- /dev/null +++ b/src/Simplex/Messaging/Agent/Env/KnownServer.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE GADTs #-} + +module Simplex.Messaging.Agent.Env.KnownServer where + +import Data.Int (Int64) +import Data.Text (Text) +import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolType (..)) + +data KnownServer p = KnownServer + { server :: ProtoServerWithAuth p, + operator :: Maybe ServerOperator + } + deriving (Show) + +type SMPKnownServer = KnownServer 'PSMP + +type XFTPKnownServer = KnownServer 'PXFTP + +data ServerOperator = ServerOperator + { operatorId :: Int64, + operatorName :: Text + } diff --git a/src/Simplex/Messaging/Agent/Env/SQLite.hs b/src/Simplex/Messaging/Agent/Env/SQLite.hs index 2ae2ad5c0..be189f60f 100644 --- a/src/Simplex/Messaging/Agent/Env/SQLite.hs +++ b/src/Simplex/Messaging/Agent/Env/SQLite.hs @@ -80,6 +80,16 @@ data InitialAgentServers = InitialAgentServers netCfg :: NetworkConfig } +data InitialAgentServers' = InitialAgentServers' + { smpKnown :: Map UserId (NonEmpty SMPKnownServer), + smpProxy :: Map UserId (NonEmpty SMPKnownServer), + smpReceive :: Map UserId (NonEmpty SMPKnownServer), + xftpKnown :: Map UserId (NonEmpty XFTPKnownServer), + xftpEnabled :: Map UserId (NonEmpty XFTPKnownServer), + ntf :: [NtfServer], + netCfg :: NetworkConfig + } + data AgentConfig = AgentConfig { tcpPort :: Maybe ServiceName, rcvAuthAlg :: C.AuthAlg,