Postes, télégraphes et téléphones, next steps
+As you know from our article on Robur's +finances, we've just received +funding for our email project. This project +started when I was doing my internship in Cambridge and it's great to see that +it's been able to evolve over time and remain functional. This article will +introduce you to the latest changes to our PTT +project and how far we've got towards providing +an OCaml mailing list service.
+A Git repository or a simple block device as a database?
+One issue that came up quickly in our latest experiments with our SMTP stack was +the database of users with an email address. Since we had decided to ‘break +down’ the various stages of an email submission to offer simple unikernels, we +ended up having to deploy 4 unikernels to have a service that worked.
+-
+
- a unikernel for authentication +
- a unikernel DKIM-signing the incoming email +
- one unikernel as primary DNS server +
- one unikernel sending the signed email to its real destination +
And we're only talking here about the submission of an email, the reception +concerns another ‘pipe’.
+The problem with such an architecture is that some unikernels need to have the +same data: the users. In this case, the first unikernel needs to know the user's +password in order to verify authentication. The final unikernel needs to know +the real destinations of the users.
+Let's take the example of two users: foo@robur.coop and bar@robur.coop. The +first points to hannes@foo.org and the second to reynir@example.com.
+If Hannes wants to send a message to bar@robur.coop under the identity of +foo@robur.coop, he will need to authenticate himself to our first unikernel. +This first unikernel must therefore:
+-
+
- check that the user
foo
exists
+ - the hashed password used by Hannes is the same as the one in the database +
Next, the email will be signed by our second unikernel. It will then forward the +email to the last unikernel, which will do the actual translation of the +recipients and DNS resolution. In other words:
+-
+
- it will see that one (the only) recipient is bar@robur.coop +
- check that bar@robur.coop exists and obtain its real address +
- it will obtain reynir@example.com and perform DNS resolution on
+
example.com
to find out the email server for this domain
+ - finally send the email signed by foo@robur.coop to reynir@example.com! +
So the first and last unikernels need to have the same information about our +users. One for the passwords, the second for the real email addresses.
+But as you know, we're talking about unikernels that exist independently of each +other. What's more, they can't share files and the possibility of them sharing +block-devices remains an open question (and a complex one where parallel access +may be involved). In short, the only way to ‘synchronise’ these unikernels in +relation to common data is with a Git repository.
+Git has the advantage of being widely used for our unikernels +(primary-git, pasteur, unipi and +contruno). The advantage is that you can track changes, modify +files and notify the unikernel to update itself (using nsupdate, a simple ping +or an http request to the unikernel).
+The problem is that this requires certain skills. Even if it's ‘simple’ to set +up a Git server and then deploy our unikernels, we can restructure our +architecture and simplify the deployment of an SMTP stack!
+Elit and OneFFS
+We have therefore decided to merge the email exchange service and email +submission into a unikernel so that this is the only user information requester.
+So we decided to use OneFFS as the file system for our database, +which will be a plain JSON file. This is perhaps one of the advantages of +MirageOS, which is that you can decide exactly what you need to implement +specific objectives.
+In this case, those with experience of Postfix, LDAP or MariaDB could confirm +that configuring an email service should be ‘simpler’ than implementing a +multitude of pipes between different applications and authentication methods.
+The JSON file is therefore very simple and so is the creation of an OneFFS +image:
+$ cat >database.json<<EOF
+> [ { "name": "din"
+> , "password": "xxxxxx"
+> , "mailboxes": [ "romain.calascibetta@gmail.com" ] } ]
+> EOF
+$ opam install oneffs
+$ oneffs create -i database.json -o database.img
+
+All you have to do is register this image as a block with albatross and launch +our Elit unikernel with this block-device.
+$ albatross-client create-block --data=database.img database 1024
+$ albatross-client create --net=service:br0 --block=database:database \
+ elit elit.hvt \
+ --arg=...
+
+At this stage, and if we add our unikernel signing incoming emails, we have more +or less the same thing as what I've described in my previous articles on +deploying an email service.
+Multiplex receiving & sending emails
+The PTT project is a toolkit for implementing SMTP servers. It gives developers +the choice of implementing their logic as they see fit:
+-
+
- sign an email +
- resolve destinations according to a database +
- check SPF information +
- annotate the email as spam or not +
- etc. +
Previously, PTT was split into 2 parts:
+-
+
- management of incoming clients/emails +
- the logic to be applied to incoming emails and their delivery +
The second point was becoming increasingly complex, however, and errors in +sending emails are legion (DMARC non-alignment, the email is too big for the +destination, the destination doesn't exist, etc.). All the more so since, up to +now, PTT could only report these errors via the logs...
+Hannes immediately mentioned the possibility of separating the logic of the +unikernel from the delivery. This will allow us to deal with temporary failures +(greylisting) as well. So a fundamental change was made:
+-
+
- improve the sendmail and
sendmail-lwt
packages (as well as proposing +sendmail-miou
!) when sending or submitting an email
+ - improve PTT so that there are now 3 distinct jobs: receiving, what to do with +incoming emails and sending emails +
This finally allows us to describe a clearer error management policy that is
+independent of what we want to do with incoming emails. At this stage, we can
+look for the Return-Path
in emails that we haven't managed to send and notify
+the senders!
All this is still in the experimental stage and practical cases are needed to +observe how we should handle errors and how others do.
+Insights & Next goals
+We're already starting to have a bit of fun with email and we can start sending +and receiving emails right away.
+We're also already seeing hacking attempts on our unikernel:
+-
+
- people trying to authenticate themselves without
STARTTLS
(or with it, +depending on how clever the bot is)
+ - people trying to send emails as non-existent users in our database +
- we're also seeing content that has nothing to do with SMTP +
Above all, this shows that, very early on, bots try to usurp the identity linked +to your server (in our case, osau.re) in order to send spam, authenticate +themselves or simply send ‘stuff’ and observe what happens. In this case, for +all the cases mentioned, Elit (and PTT) reacts well: in other words, it simply +cuts off the connection.
+We were also able to observe how services such as gmail work. In addition, for +the purposes of a mailing list, email forwarding distorts DMARC verification +(specifically, SPF verification). The case is very simple:
+foo@gmail.com tries to reply to robur@osau.re. robur@osau.re is a mailing list
+to several addresses (one of them is bar@gmail.com). The unikernel will receive
+the email and send it to bar@gmail.com. The problem is the alignment between
+the From
field (which corresponds to foo@gmail.com) and our osau.re server.
+From gmail.com's point of view, there is a misalignment between these two
+pieces of information and it therefore refuses to receive the email.
This is where our next objectives come in:
+-
+
- finish our DMARC implementation +
- implement ARC so that our server notifies us that, on our side, the DMARC +check went well and that gmail.com should trust us on this. +
There is another way of solving the problem, perhaps a little more problematic,
+modify the incoming email and in particular the From
field. Although this
+could be done quite simply with mrmime, it's better to concentrate on
+DMARC and ARC so that we can send our emails as they are and never alter them
+(especially as this will invalidate previous DKIM signatures!).
Conclusion
+It's always satisfying to see your projects working ‘more or less’ correctly. +This article will surely be the start of a series on the intricacies of email +and the difficulty of deploying such a service at home.
+We hope that this NLnet-funded work will enable us to replace our current email +system with unikernels. We're already past the stage where we can, more or less +(without DMARC checking), send emails to each other, which is a big step!
+So follow our work on our blog and if you like what we're producing (which +involves a whole bunch of protocols and formats - much more than just SMTP), you +can make a donation here!
+ +