Skip to content

Instantly share code, notes, and snippets.

@therealmik
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save therealmik/4cd07c8025757d0d85e3 to your computer and use it in GitHub Desktop.
Save therealmik/4cd07c8025757d0d85e3 to your computer and use it in GitHub Desktop.
LAFS Mail Server

Tahoe-LAFS Mail Server

Language, APIs

twisted.mail for SMTP server, with LAFS REST API for storage.

Outbound SMTP server much the same - may run on a different box.

Mail Server Configuration variables

Per-user settings

  • emailaddr: Only accept mail for actual users :)
  • inboxcap: RW directory cap containing a list of all received messages. Mail messages are stored here with a universally unique filename.
  • inboxstatuscaps: a list of RO file caps containing the filenames of received messages. Will be checked occasionally, and when all of these files state that they have received the message, the file will be removed from inboxcap.
  • outboxcaps: a list of RO directory caps containing messages to be sent.
  • outboxstatuscaps: a list of RW mutable file caps where we list the status of messages in the accompanying outboxcap

SMTP Mail Server Operation

Listen for SMTP messages. When a message arrives, upload it via LAFS-REST to inboxcap.

Occasionally poll REST API for each inboxstatuscap. Since there are multiple clients, we first ignore entries for files that aren't in inboxcap. Then we check the remaining files, and if all caps list the file we remove it from inboxcap.

Outbound SMTP Relay Operation

Poll each outboxcap for changes. When changed, find new messages and attempt to send via SMTP. Append status information to the relevant outboxstatuscap. Lines in an outboxstatuscap for messages no longer in the accompanying outboxcap should be purged.

Mail Client (Reader) Operation

Poll inboxcap (RO dir cap) for changes. When it changes, collect any new messages and link into a maildir in a separate directory.

Once saved to the the maildir, append the cap to our inboxstatuscap. At this point our inboxstatuscap can have any entries that have been removed from inboxcap removed.

Mail Client (Sending) Operation

Create message as an immutable file, and append cap to our outboxcap.

While appending messages to our outbox, we should scan our outboxstatuscap for messages in outboxcap and purge them.

Multiple Incoming Server Support

To have multiple (receiving) servers, there would need to be one inboxcap per server, with the client performing the dance with all of them. This is possibly too hard for the short term.

Multiple Client Support

Each client would have:

  • A RW mutable inboxstatuscap
  • A RW directory outboxcap
  • A RO mutable file outboxstatuscap
  • A RW file cap listing changes to messages (deletions, moves, status flags)
  • An RO file cap for each other client, which contains the changes for files they have applied.

Each entry in the changes files should contain a unique change ID (probably sequential), the message, and the change to be applied.

Once a client has applied a change from another client, it should append to it's change cap the fact that it has applied the change.

When a client has received acknowledgement of a change from all other clients, it can remove that ID from it's own change cap.

Acknowledgements for changes that no longer exist can be purged.

Note that this is extremely complex - it might be worth implementing single-client support instead with an IMAP frontend. I want to avoid this, as I hope to have multiple mobile clients directly talking to the storage nodes.

Security Model

The mail server is trusted to receive messages via SMTP, which means it must see message content. It puts the messages into LAFS, then loses track of them as soon as the clients have picked them up. If there are idle clients, the SMTP server would easily be able to read those messages. It is probably hard to properly "wipe" the memory of the file caps, so try not to have your SMTP server compromised or stolen if you can help it.

A stealthily compromised mail server would be able to inject arbitrary messages into your inbox, which would avoid the usual anti-spam restrictions and allow custom Received and Delivered-To headers. It may also try to duplicate filenames in order to overwrite messages you've previously received (clients must reject this), or "undeliver" messages by deleting them from the directory before the client picks them up.

Note that SMTP STARTTLS could be attempted, but this should be done in a pre-arranged manner. Common domains (eg. gmail) could have their certificate pinned, as well as custom certificate pinning.

Strict transport security should be implemented, which basically means that if a mail server accepted TLS before, then it is required for all future transactions.

Certificate checking is required, which either requires a certificate hash for pinning, or having a certificate from a trusted CA with the CN/SAN having either the recipient domain or a subdomain of it.

Enforcing STARTTLS from other mail servers is pointless, as if the other mail server is willing to send at all via non-TLS or doesn't check certificates (both of which are basically always true), the connection can be subverted. For some domains, you could require STARTTLS and a client certificate, but otherwise just take what you can get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment