Add support for sender rewriting using postsrsd
With SRS we support forwarding of mails without (fully) breaking SPF alignment.
This commit is contained in:
@@ -57,6 +57,8 @@ SNM branch corresponding to your NixOS version.
|
|||||||
* User Aliases
|
* User Aliases
|
||||||
* [x] Regular aliases
|
* [x] Regular aliases
|
||||||
* [x] Catch all aliases
|
* [x] Catch all aliases
|
||||||
|
* Improve the Forwarding Experience
|
||||||
|
* [x] [Sender Rewriting Scheme](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme)
|
||||||
|
|
||||||
### In the future
|
### In the future
|
||||||
|
|
||||||
@@ -69,7 +71,6 @@ SNM branch corresponding to your NixOS version.
|
|||||||
* [ ] Allow passing DKIM signing keys
|
* [ ] Allow passing DKIM signing keys
|
||||||
* Improve the Forwarding Experience
|
* Improve the Forwarding Experience
|
||||||
* [ ] Support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) signing with [Rspamd](https://rspamd.com/doc/modules/arc.html)
|
* [ ] Support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) signing with [Rspamd](https://rspamd.com/doc/modules/arc.html)
|
||||||
* [ ] Support [SRS](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme) with [postsrsd](https://github.com/roehling/postsrsd)
|
|
||||||
* User management
|
* User management
|
||||||
* [ ] Allow local and LDAP user to coexist
|
* [ ] Allow local and LDAP user to coexist
|
||||||
* OpenID Connect
|
* OpenID Connect
|
||||||
|
|||||||
22
default.nix
22
default.nix
@@ -1101,6 +1101,28 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
srs = {
|
||||||
|
enable = mkEnableOption "Sender Rewrite Scheme";
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = config.mailserver.systemDomain;
|
||||||
|
defaultText = literalExpression "config.mailserver.systemDomain";
|
||||||
|
example = "srs.example.com";
|
||||||
|
description = ''
|
||||||
|
Mail domain used for ephemeral SRS envelope addresses.
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
This domain can only support relaxed SPF alignment.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::{important}
|
||||||
|
For privacy reasons you should use a dedicated domain when serving multiple unrelated domains.
|
||||||
|
:::
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
redis = {
|
redis = {
|
||||||
configureLocally = mkOption {
|
configureLocally = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
|||||||
@@ -23,16 +23,22 @@ Welcome to NixOS Mailserver's documentation!
|
|||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
:caption: Features
|
||||||
|
|
||||||
|
fts
|
||||||
|
ldap
|
||||||
|
srs
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 0
|
||||||
:caption: How-to
|
:caption: How-to
|
||||||
|
|
||||||
backup-guide
|
backup-guide
|
||||||
add-radicale
|
add-radicale
|
||||||
add-roundcube
|
add-roundcube
|
||||||
rspamd-tuning
|
rspamd-tuning
|
||||||
fts
|
|
||||||
flakes
|
flakes
|
||||||
autodiscovery
|
autodiscovery
|
||||||
ldap
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ NixOS 25.11
|
|||||||
- The ``systemName`` and ``systemDomain`` options have been introduced to have
|
- The ``systemName`` and ``systemDomain`` options have been introduced to have
|
||||||
reusable configurations for automated reports (DMARC, TLSRPT). They come with
|
reusable configurations for automated reports (DMARC, TLSRPT). They come with
|
||||||
reasonable defaults, but it is suggested to check and change them as needed.
|
reasonable defaults, but it is suggested to check and change them as needed.
|
||||||
|
- Support for the `Sender Rewriting Scheme`_ has been added, which allows
|
||||||
|
forwarding mail without breaking SPF by rewriting the envelope address.
|
||||||
- The default key length for new DKIM RSA keys was increased to 2048 bits as
|
- The default key length for new DKIM RSA keys was increased to 2048 bits as
|
||||||
recommended in `RFC 8301 3.2`_.
|
recommended in `RFC 8301 3.2`_.
|
||||||
We recommend rotating existing keys, as the RFC advises that signatures from
|
We recommend rotating existing keys, as the RFC advises that signatures from
|
||||||
@@ -29,6 +31,7 @@ NixOS 25.11
|
|||||||
`tlsrpt-reporter`_. They can be enabled with the ``mailserver.tlsrpt.enable``
|
`tlsrpt-reporter`_. They can be enabled with the ``mailserver.tlsrpt.enable``
|
||||||
option.
|
option.
|
||||||
|
|
||||||
|
.. _Sender Rewriting Scheme: srs.html
|
||||||
.. _RFC 8301 3.2: https://www.rfc-editor.org/rfc/rfc8301#section-3.2
|
.. _RFC 8301 3.2: https://www.rfc-editor.org/rfc/rfc8301#section-3.2
|
||||||
.. _RFC 8314 3.3: https://www.rfc-editor.org/rfc/rfc8314#section-3.3
|
.. _RFC 8314 3.3: https://www.rfc-editor.org/rfc/rfc8314#section-3.3
|
||||||
.. _RFC 8314 4.1: https://www.rfc-editor.org/rfc/rfc8314#section-4.1
|
.. _RFC 8314 4.1: https://www.rfc-editor.org/rfc/rfc8314#section-4.1
|
||||||
|
|||||||
102
docs/srs.rst
Normal file
102
docs/srs.rst
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
Sender Rewriting Scheme
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The Sender Rewriting Scheme (SRS) allows mail servers to forward emails without
|
||||||
|
breaking SPF checks. By rewriting the envelope sender to an address within the
|
||||||
|
forwarder’s domain, SRS ensures that forwarded messages pass SPF validation,
|
||||||
|
preventing them from being rejected as spoofed or unauthorized.
|
||||||
|
|
||||||
|
How SRS works in practice
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
1. ``alice@foo.example`` receives an E-Mail from ``bob@bar.example``. Both the
|
||||||
|
envelope sender as well as the ``From`` header show ``bob@bar.example``. This
|
||||||
|
results in strict SPF alignment, because ``bar.example`` is the domain used in
|
||||||
|
both the ``Return-Path`` and ``FROM`` headers.
|
||||||
|
|
||||||
|
2. ``alice@foo.example`` forwards the mail to ``charlie@moo.example`` and
|
||||||
|
uses SRS to rewrite the envelope sender to originate from the local SRS domain
|
||||||
|
(e.g. `SRS0=HHH=TT=bar.example=alice@foo.example`). The ``FROM`` header remains
|
||||||
|
unchanged. This ensures that the forwarded mail succeeds SPF checks.
|
||||||
|
|
||||||
|
3. The email reaches ``charlie@moo.example``. SPF passes because the sender
|
||||||
|
domain in the envelope has been rewritten. The mismatch between envelope sender
|
||||||
|
domain and ``FROM`` domain does however break strict SPF alignment.
|
||||||
|
|
||||||
|
Enabling SRS
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In a simple setup just enabling SRS will use your ``mailserver.systemDomain``
|
||||||
|
when rewriting the envelope sender domain.
|
||||||
|
|
||||||
|
.. code:: nix
|
||||||
|
|
||||||
|
{
|
||||||
|
mailserver = {
|
||||||
|
srs = {
|
||||||
|
enable = true;
|
||||||
|
#domain = "srs.example.com";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
..
|
||||||
|
|
||||||
|
While you can reuse an existing email domain for SRS, it is recommended to
|
||||||
|
configure a dedicated SRS domain. This is particularly important under the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
* Multiple unrelated mail domains are hosted on the mailserver
|
||||||
|
* The mail domain requires strict SPF alignment in its DMARC policy
|
||||||
|
|
||||||
|
Required DNS changes
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In the following example we assume that you want to set up a dedicated SRS
|
||||||
|
domain. If that is not the case you already have SPF and DKIM set up for the
|
||||||
|
system domain. If you have a DMARC record on the system domain, make sure it
|
||||||
|
uses a relaxed SPF alignment policy (``aspf=r``).
|
||||||
|
|
||||||
|
First we set up an MX record. This is so that we can receive and route bounces
|
||||||
|
that can result from forwards.
|
||||||
|
|
||||||
|
======================== ===== ==== ======== =====================
|
||||||
|
Name (Subdomain) TTL Type Priority Value
|
||||||
|
======================== ===== ==== ======== =====================
|
||||||
|
srs.example.com 10800 MX 10 ``mail.example.com``
|
||||||
|
======================== ===== ==== ==============================
|
||||||
|
|
||||||
|
Next up is the SPF record on the SRS domain to allow SPF authentication.
|
||||||
|
|
||||||
|
======================== ===== ==== ===================
|
||||||
|
Name (Subdomain) TTL Type Value
|
||||||
|
======================== ===== ==== ===================
|
||||||
|
srs.example.com 10800 TXT ``v=spf1 mx -all``
|
||||||
|
======================== ===== ==== ===================
|
||||||
|
|
||||||
|
Then we deploy the DKIM record with the `p=<value>` taken from
|
||||||
|
``/var/dkim/srs.example.com.mail.txt``, that appears after deploying with SRS
|
||||||
|
enabled.
|
||||||
|
|
||||||
|
=============================== ===== ==== ========================================
|
||||||
|
Name (Subdomain) TTL Type Value
|
||||||
|
=============================== ===== ==== ========================================
|
||||||
|
mail._domainkey.srs.example.com 10800 TXT ``v=DKIM1; k=rsa; p=<really-long-key>``
|
||||||
|
=============================== ===== ==== ========================================
|
||||||
|
|
||||||
|
Finally we can tie this together in the DMARC record to require receivers to
|
||||||
|
verify the requested SPF/DKIM alignment.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The SRS domain can only support relaxed SPF alignment due to the envelope
|
||||||
|
sender and ``FROM`` header mismatch.
|
||||||
|
|
||||||
|
======================== ===== ==== =========================================
|
||||||
|
Name (Subdomain) TTL Type Value
|
||||||
|
======================== ===== ==== =========================================
|
||||||
|
_dmarc.srs.example.com 10800 TXT ``v=DMARC1; p=reject; aspf=r; adkim=s;``
|
||||||
|
======================== ===== ==== =========================================
|
||||||
|
|
||||||
|
We can safely configure a ``reject`` policy on the SRS domain, to enforce the
|
||||||
|
SPF and DKIM alignment as configured above.
|
||||||
@@ -84,6 +84,7 @@
|
|||||||
_module.check = false;
|
_module.check = false;
|
||||||
mailserver = {
|
mailserver = {
|
||||||
fqdn = "mx.example.com";
|
fqdn = "mx.example.com";
|
||||||
|
systemDomain = "example.com";
|
||||||
domains = [
|
domains = [
|
||||||
"example.com"
|
"example.com"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -261,6 +261,24 @@ in
|
|||||||
configurePostfix = true;
|
configurePostfix = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Sender Rewriting Scheme (https://www.libsrs2.net/srs/srs.pdf)
|
||||||
|
services.postsrsd = {
|
||||||
|
inherit (cfg.srs) enable;
|
||||||
|
configurePostfix = true;
|
||||||
|
settings = {
|
||||||
|
domains = lib.unique (
|
||||||
|
[
|
||||||
|
cfg.fqdn
|
||||||
|
cfg.sendingFqdn
|
||||||
|
cfg.systemDomain
|
||||||
|
]
|
||||||
|
++ cfg.domains
|
||||||
|
);
|
||||||
|
separator = "=";
|
||||||
|
srs-domain = cfg.srs.domain;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.postfix-setup = lib.mkIf cfg.ldap.enable {
|
systemd.services.postfix-setup = lib.mkIf cfg.ldap.enable {
|
||||||
preStart = ''
|
preStart = ''
|
||||||
${appendPwdInVirtualMailboxMap}
|
${appendPwdInVirtualMailboxMap}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ let
|
|||||||
echo "Generated key for domain ${domain} and selector ${cfg.dkimSelector}"
|
echo "Generated key for domain ${domain} and selector ${cfg.dkimSelector}"
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
dkimDomains = lib.unique (cfg.domains ++ (lib.optionals cfg.srs.enable [ cfg.srs.domain ]));
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
@@ -201,7 +203,7 @@ in
|
|||||||
SupplementaryGroups = [ config.services.redis.servers.rspamd.group ];
|
SupplementaryGroups = [ config.services.redis.servers.rspamd.group ];
|
||||||
}
|
}
|
||||||
(lib.optionalAttrs cfg.dkimSigning {
|
(lib.optionalAttrs cfg.dkimSigning {
|
||||||
ExecStartPre = map createDkimKeypair cfg.domains;
|
ExecStartPre = map createDkimKeypair dkimDomains;
|
||||||
ReadWritePaths = [ cfg.dkimKeyDirectory ];
|
ReadWritePaths = [ cfg.dkimKeyDirectory ];
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ groups = [
|
|||||||
"mailserver.loginAccounts",
|
"mailserver.loginAccounts",
|
||||||
"mailserver.certificate",
|
"mailserver.certificate",
|
||||||
"mailserver.dkim",
|
"mailserver.dkim",
|
||||||
|
"mailserver.srs",
|
||||||
"mailserver.dmarcReporting",
|
"mailserver.dmarcReporting",
|
||||||
"mailserver.fullTextSearch",
|
"mailserver.fullTextSearch",
|
||||||
"mailserver.redis",
|
"mailserver.redis",
|
||||||
|
|||||||
Reference in New Issue
Block a user