Edges and two premises
Taking mail for a domain whose mailboxes are elsewhere, a backup MX, an edge in front of another server, and one domain with mailboxes in two places.
A Nixt Server node does not have to hold every mailbox of the domains it takes mail for. It can stand in front of another server, whether that is another Nixt Server, Exchange or Postfix, and it can share one domain with another set of mailboxes while people move across a few at a time.
| You want | Set up |
|---|---|
| A backup MX that holds mail while the main server is away | A relay domain with no route of its own. |
| An edge in the cloud that filters mail for a server on your premises | A relay domain with a route to your server; optionally the server sending out through the edge. |
| Your server to trust the edge’s checks | [edge] on the server that holds the mailboxes. |
| Mailboxes of one domain in two places | Other premises, and where each person’s mailbox is. |
| The certificates for any of these without running an authority of your own | A link between the two sides, made with a one-time code. |
Taking mail for a domain whose mailboxes are elsewhere
Name the domain, and whom to take mail for:
[[relay_domains]]
domain = "branch.example.com"
recipients = ["@branch.example.com"]
recipients lists whole addresses, or @ and the domain for every address at it. The node cannot ask the other server during the conversation whether an address exists, so with @ an unknown address is taken here and bounced once the other server refuses it. Listing the addresses one by one refuses unknown ones at once. versealx-server explain says which of the two each relay domain does.
Where the mail goes next is the ordinary routing:
- With an
[outbound.transport]entry for the domain, it goes to that next hop — your own server, over TLS. - Without one, it goes to the domain’s MX hosts. A backup MX passes mail only to the hosts that outrank it, so it never hands mail back to itself.
The destination’s MTA-STS policy and DANE records hold on that hop as on any other. Mail waiting for the destination stays in the queue, retried as any other.
An edge and the server that holds the mailboxes
An edge that takes a domain’s mail in can also be the way the domain’s own server sends out: the server keeps the mailboxes, and the edge sends from addresses with a good reputation. The edge knows the server by the certificate it shows over TLS, rather than by a password. The certificate is issued for the server’s host name by an authority of your own, which the edge trusts for this server and nothing else.
On the edge:
[[relay_domains]]
domain = "partner.example"
recipients = ["@partner.example"]
[relay_domains.mailboxes]
name = "store.partner.example" # the name its certificate carries
authority = "/etc/versealx/partner-links-ca.pem" # who issued it
On the server that holds the mailboxes, the relay it sends through presents the certificate:
[outbound.relay]
host = "edge.example.net"
port = 25
tls = "required"
certificate = "/etc/versealx/store.pem" # its certificate, then any intermediates
key = "/etc/versealx/store.key"
Once a mailboxes server is named, the edge’s port 25 asks every client for a certificate. A server delivering inbound mail shows none and is served as before. A certificate the named authority did not issue for the named server makes the client a stranger like any other.
The server the edge knows may send to anyone, from an envelope sender at its own domains, at a name below one, or empty, as its bounces are, so whatever bounces from the edge goes back to it. Its mail passes through the edge’s outbound filter, and the message trace names it. The edge does not sign its mail: its DKIM keys are with its mailboxes, so the server signs its own. Several relay domains may name the same server.
The certificate carries the server’s name among its subject alternative names and allows client authentication. check reads the authority and the certificate, and refuses a key that is not the certificate’s.
Trusting the edge in front of you
In the other direction, the edge passes the domain’s mail on through its transport, presenting its own certificate from that transport’s certificate and key. The server that holds the mailboxes names the edge in front of it:
[edge]
names = ["edge.example.net"] # each edge server's certificate name
authority = "/etc/versealx/partner-links-ca.pem" # who issued them
The edge writes what it found above its Received: line on everything it passes on for a relay domain: its Authentication-Results, and its decision in X-Versealx-Disposition — deliver, file as junk, or quarantine with its reason. Mail from a client presenting an edge’s certificate keeps that verdict. It is filed into the inbox, into Junk or into the person’s quarantine as the edge decided, rather than checked again here, where SPF could only see the edge’s address.
Anybody else’s mail is checked as always. Every node removes from what it accepts on port 25 any Authentication-Results in its own name or its edge’s, and any X-Versealx-Disposition, so the only such lines a message holds are the ones the node that wrote them put there. A server behind the edge that is not Nixt Server receives the same headers and can act on them with its own rules.
One domain, mailboxes in two places
An organisation moving its mailboxes a few at a time has people on both sides for a while, and both sides host the domain: each side’s directory lists everybody, and each person’s mailbox is on one side. Name the other side’s MX as premises, with the certificate this node presents to it:
[outbound.premises.onprem]
host = "mail.onprem.example"
port = 25
tls = "required"
certificate = "/etc/versealx/cloud.pem"
key = "/etc/versealx/cloud.key"
Premises names are letters, digits and hyphens. Then say whose mailbox is there:
vsx admin mailbox move ada@example.com onprem
vsx admin mailbox show ada@example.com
vsx admin mailbox return ada@example.com
Mail for someone whose mailbox is on the other premises is taken here like anybody’s and sent there, whether it was written to them, to an alias of theirs or to a group they belong to, with this node’s findings written above it. The other side keeps them when it names this node in its [edge]. Nothing else about the person changes: addresses, groups and the address book stay as they were, which is why a mailbox moves by changing one setting. mailbox return brings it back.
Port 25 takes one side’s recipients per message and asks for the rest in another, which sending servers do on their own. When no route to the premises is configured, the mail waits in the queue and says what to add, rather than being filed here.
Over the API, where a mailbox is is GET, PUT and DELETE /api/v1/tenants/{tenant}/accounts/{id}/location, the PUT with premises. Administrators and domain administrators move mailboxes; helpdesks and auditors can see where they are. The console shows it on each person’s page.
Linking the two sides by code
The certificates and authorities above can be made for you. On one side, invite the other:
versealx-server link invite --name onprem --address https://mail.example.com
This prints a code that works once, within an hour. Hand it to the other side’s operator as you would a password. On the other side, accept it:
versealx-server link accept vsxlink1.… --name head-office --address https://store.onprem.example.com
--name is what each side calls the other. --address is where this side answers, and --names lists the host names its certificate carries, which is its host name unless you say otherwise.
Each side makes an authority of its own for this link, and a certificate from it. The code carries the inviting side’s authority fingerprint, and the accepting side checks the authority it receives against it. Both sides print both fingerprints: read them to each other and check they match.
Then, on each side, write the files the configuration uses:
versealx-server link files head-office --dir /etc/versealx/links/head-office
This writes this side’s certificate and key, and the other side’s authority, to that directory. It also prints the [edge], [relay_domains.mailboxes] and certificate and key lines that name them, ready to paste into the sections above. The authorities’ private keys stay in the store, encrypted.
Each side’s link certificate lasts a year and renews itself a month before it runs out; the other side needs nothing, because it trusts the link’s authority rather than the certificate. Set dir under [links] and the server rewrites each link’s files in a folder of that name when it renews, and shows the new certificate from its next connection to the other side; nothing needs restarting. If a renewed file is damaged, the server keeps using the certificate that worked and records an error. versealx-server link renew <name> --dir <directory> renews one by hand. The server’s certificate alert tells the operator when a link certificate has two weeks left, and again at three days.
With [links] dir set, you can name the link instead of its files. The server then uses the files in that link’s folder, which renewal keeps current:
[edge]
names = ["store.onprem.example.com"]
link = "onprem"
[outbound.premises.onprem]
host = "mx.onprem.example.com"
port = 25
link = "onprem"
link takes the place of authority in [edge] and [relay_domains.mailboxes], and of certificate and key in an outbound relay; a table has one or the other.
versealx-server link list shows each link and whether it is waiting to be accepted or linked. The operator sees the same at GET /api/v1/links. versealx-server link remove <name> ends a link on this side; end it on the other side too, and take its files out of the configuration.
Something unclear or out of date on this page? Tell us.