From f086234f51b92c54bc744602eb08f1bb5eeca047 Mon Sep 17 00:00:00 2001 From: Gonne Date: Fri, 28 Feb 2025 11:11:58 +0100 Subject: [PATCH 01/13] Delete directive proxy_interface This directive is supposed to prevent mail delivery loops that would be caused by portforwarding to itself. Behind this ip address, however, there is our general mail vm and not immediately the mailinglist setup. --- nixos/modules/mailman.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/nixos/modules/mailman.nix b/nixos/modules/mailman.nix index f4ecd0e..1c8eaba 100644 --- a/nixos/modules/mailman.nix +++ b/nixos/modules/mailman.nix @@ -32,7 +32,6 @@ in { config = { transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"]; local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"]; - proxy_interfaces = "130.83.2.184"; smtputf8_enable = "no"; # HRZ does not know SMTPUTF8 }; relayHost = "mathebau.de"; # Relay to mail vm which relays to HRZ (see https://www.hrz.tu-darmstadt.de/services/it_services/email_infrastruktur/index.de.jsp) From 22b15d0eef31d9662bfd8310769683da13011e8e Mon Sep 17 00:00:00 2001 From: Gonne Date: Fri, 28 Feb 2025 11:13:59 +0100 Subject: [PATCH 02/13] Allow unpacking stalwart's webadmin interface --- nixos/modules/mail.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 4d7f950..76eadb1 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -148,6 +148,7 @@ in { # In order to accept mail that we only forward # without having to generate an account. # Invalid addresses are filtered by DFN beforehand. + # See also https://stalw.art/docs/smtp/inbound/rcpt/#catch-all-addresses catch-all = true; relay = [ { @@ -267,6 +268,7 @@ in { "stalwart-mail" = { restartTriggers = lib.attrsets.mapAttrsToList (_: aliaslist: aliaslist.sopsFile) config.sops.secrets; # restart if secrets, especially alias files, have changed. serviceConfig.PrivateTmp = lib.mkForce false; # enable access to generated Sieve script + serviceConfig.ProtectSystem = lib.mkForce "full"; # "strict" does not allow writing to /tmp which we need for unpacking the webadmin interface. "full" is less strict. }; "virt-aliases-generator" = { description = "Virtual Aliases Generator: Generate a sieve script from the virtual alias file"; From 0cc1a1fb85b704137f8945b04e08b190adddea02 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:33:22 +0100 Subject: [PATCH 03/13] Disable matheball.de forwards and submission to mail allowlist until we actually handle it --- nixos/machines/nyarlathotep/configuration.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/machines/nyarlathotep/configuration.nix b/nixos/machines/nyarlathotep/configuration.nix index 6cbfd19..286307d 100644 --- a/nixos/machines/nyarlathotep/configuration.nix +++ b/nixos/machines/nyarlathotep/configuration.nix @@ -15,10 +15,12 @@ stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg"; domains = [ # lists.mathebau.de is forwarded to another VM and does not need to be listed here. - { + /* + { domain = "matheball.de"; allowlistPass = config.sops.secrets."allowlistPass/matheball".path; } + */ { domain = "mathebau.de"; allowlistPass = config.sops.secrets."allowlistPass/mathebau".path; From 2dda6094647783eea4bf05cd1e5011507774b182 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:34:54 +0100 Subject: [PATCH 04/13] Rename config option after update beyond version 0.11.2 --- nixos/modules/mail.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 76eadb1..07326d0 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -65,7 +65,7 @@ in { openFirewall = true; settings = { server = { - lookup.default.hostname = "fb04184.mathematik.tu-darmstadt.de"; # Because the DNS PTR of 130.83.2.184 is this and this should be used in SMTP EHLO. + hostname = "fb04184.mathematik.tu-darmstadt.de"; # Because the DNS PTR of 130.83.2.184 is this and this should be used in SMTP EHLO. listener = { "smtp" = { bind = ["[::]:25"]; From bdd88e748b1b2ad021d37167c0fb0e9d27f58d57 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:36:33 +0100 Subject: [PATCH 05/13] Add mathebau.de to certificate --- nixos/modules/mail.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 07326d0..94cfae6 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -82,7 +82,7 @@ in { tls.implicit = true; }; "management" = { - # Cthulhu forwards requests for http://fb04184.mathematik.tu-darmstadt.de/.well-known/acme-challenge/ http://imap.mathebau.de/.well-known/acme-challenge/ and http://smtp.mathebau.de/.well-known/acme-challenge/ + # Cthulhu forwards requests for http://fb04184.mathematik.tu-darmstadt.de/.well-known/acme-challenge/ http://imap.mathebau.de/.well-known/acme-challenge/ and http://smtp.mathebau.de/.well-known/acme-challenge/ and http://mathebau.de/.well-known/acme-challenge/ # for TLS certificate challenge validation # whereas the rest of the management interface is not available publically. # It can be reached via SSH and portforwarding. @@ -95,7 +95,7 @@ in { directory = "https://acme-v02.api.letsencrypt.org/directory"; # This setting is necessary for this block to be activated challenge = "http-01"; contact = ["root@mathebau.de"]; - domains = ["fb04184.mathematik.tu-darmstadt.de" "imap.mathebau.de" "smtp.mathebau.de"]; + domains = ["fb04184.mathematik.tu-darmstadt.de" "imap.mathebau.de" "smtp.mathebau.de" "mathebau.de"]; default = true; }; # Reevaluate after DKIM and DMARC deployment From b2c89091d81667c85c28d26ee15707ba8d8209ae Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:37:40 +0100 Subject: [PATCH 06/13] Accept mail from our badly configured VMs --- nixos/modules/mail.nix | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 94cfae6..62fe93a 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -159,6 +159,21 @@ in { ]; }; + session.ehlo.require = [ + { + "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly + "then" = false; + } + {"else" = true;} + ]; + session.ehlo.reject-non-fqdn = [ + { + "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly + "then" = false; + } + {"else" = true;} + ]; + # Stalwart gets its configuration from two places: A TOML configuration file that we control in this module # and from a database that can be configured from web management interface or via Rest API. # We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" to the default ones From 74e5df98b171736876b6e8e1ea3c0a841ad3e088 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:40:47 +0100 Subject: [PATCH 07/13] Set sender and increase redirect limit for our alias file --- nixos/modules/mail.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 62fe93a..1019ffc 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -197,8 +197,15 @@ in { "lookup.default.hostname" "certificate.*" ] # the default ones - ++ ["sieve.trusted.scripts.*"]; #for macros to be able to include our redirection script + ++ ["sieve.trusted.*"]; #for macros to be able to include our redirection script sieve.trusted.scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script + sieve.trusted.from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM. + sieve.trusted.from-name = "sender"; + sieve.trusted.return-path = "sender"; + sieve.trusted.limits = { + redirects = 50; + out-messages = 50; + }; session.data.script = "'redirects'"; authentication.fallback-admin = { From a486d42e1c5e443239d2bb8c1d1e4722b2a3a0ff Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 08:41:07 +0100 Subject: [PATCH 08/13] Filter out catch-all addresses of the form "@domain.tld" from the allowlist that are not intended for HRZ --- nixos/modules/mail.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 1019ffc..2791b74 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -252,7 +252,8 @@ in { echo "process ${domain}" # This line gets the available mailboxes from stalwart's Rest API, searches for their addresses and collects them to a file for submission. # The regex searches for alphanumerics combined with some special characters as local paths and the right domain. - ${pkgs.curl}/bin/curl -s --header "authorization: Basic $(<${cfg.stalwartAdmin})" http://localhost/api/principal | ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" | tee /tmp/addresses + # Exclude @domain.tld which is not a valid mail address but used for catch-all accounts. + ${pkgs.curl}/bin/curl -s --header "authorization: Basic $(<${cfg.stalwartAdmin})" http://localhost/api/principal | ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" | grep -v "@${domain}" | tee /tmp/addresses # This line searches for available redirects and adds them to the submission file. ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" /tmp/virt_aliases >> /tmp/addresses # This doesn't catch all RFC conform local parts. Improve if you need. # Post local-parts to HRZ, see https://www-cgi.hrz.tu-darmstadt.de/mail/index.php?bereich=whitelist_upload From 654922c40a7bf8963be3b0ff477f6335418dba08 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 11:44:08 +0100 Subject: [PATCH 09/13] Enable DKIM signing --- nixos/machines/nyarlathotep/configuration.nix | 12 +++++ nixos/machines/nyarlathotep/dkim.keys.yaml | 40 +++++++++++++++ nixos/modules/mail.nix | 50 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 nixos/machines/nyarlathotep/dkim.keys.yaml diff --git a/nixos/machines/nyarlathotep/configuration.nix b/nixos/machines/nyarlathotep/configuration.nix index 286307d..1989736 100644 --- a/nixos/machines/nyarlathotep/configuration.nix +++ b/nixos/machines/nyarlathotep/configuration.nix @@ -75,6 +75,18 @@ group = "stalwart-mail"; mode = "0440"; }; + "dkim_rsa" = { + sopsFile = ./dkim.keys.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0440"; + }; + "dkim_ed25519" = { + sopsFile = ./dkim.keys.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0440"; + }; # password for https://stalw.art/docs/auth/authorization/administrator/#fallback-administrator encoded to be supplied in the basic auth header stalwartAdmin = { sopsFile = ./stalwartAdmin.yaml; diff --git a/nixos/machines/nyarlathotep/dkim.keys.yaml b/nixos/machines/nyarlathotep/dkim.keys.yaml new file mode 100644 index 0000000..a923ce2 --- /dev/null +++ b/nixos/machines/nyarlathotep/dkim.keys.yaml @@ -0,0 +1,40 @@ +dkim_rsa: ENC[AES256_GCM,data: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,iv:QbZVXp5FQhmYZvXxXNxWKrNm5GqM+2P3a5pPk499mlc=,tag:F+KNoPRnoLLhOpEj6Czj6Q==,type:str] +dkim_ed25519: ENC[AES256_GCM,data:cZHm7bVpQ/VhYLt2CnNk9364k+J5ybgSLrR7Vm1GsCU6JcAvHl8Y5R7mqwgS+gTnHX7K02GuIGXa8909/aEotE0ZMY5irKJ25SGJqTaqQafbiMOz65CRQh5trtcMBF4s4wRYOkDGgz09KkELbkDHyQZFcrGqvgM=,iv:p9ROj/epqR3xtrimXF1onJJHH9JUqNG9z1MxKVu9uPg=,tag:m53rXkcu+ernS5JX+k8YcA==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6VnhvWHdsZWNHemlueFo4 + L0xCTGp4NlRuU3YwRWJiSHFBbmtURTNMQkVRCnlSbFc0Q2xINjRvU2tQeStQc1U5 + VElxcTVuNm9MUm01RkpGYytrYWg0czgKLS0tIHZqUWhkMGRNNjJvUTQrOHBpZXVS + NlpjeDQxbVZIRHFCcmNtT1JSVHp1K2sKSNcC0fcOar/KKzs1twaozB8wfdFT9OdB + 4quV/ycNpJpfs6+2r0RTLBxYFyusybu1swosAni+PJsRXS82+PTXHQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsUTUzYzZuMkYvcTlrUmRK + aStnak5IWitFUSt0eVBQOHIzcTlrMFRFTjA4CmlYUTdobXFUK2tYMWtFekNqNnhp + R2RRRFdHc1p6bFVjYU9lbTRBeEM3Y2sKLS0tIHdsRW1wR25pVkZIYU1yMm9sQXpr + NFhiN0pyaHVWT1h5eVFXMWZDb0sxUGMKIVkYYheD8F9aaAyCA+m9ZGlV8vKbAW4r + H6FUe+ats30abxoYfHZfMJv17BxJtpodksSxWjnPYm0dfRf/EF/vSQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvU3NzY0Uxc0NhY2xJZyti + TCtTS1crV3hzMXZNV3k4cm0zUFNuY2tBL0dNCnNpYytoaUI1eERhdG1PUlZ2eE5C + R2UrVlBwcXR2L1VNR3RJL1lEQmlTSDgKLS0tIFJyLzhZeG5zejFmL2VkYy8xVEM1 + U3QwOXlRdU8yd3ozL2hUVzRXNGE0bDQKT7SLAqICsbFmRUF+3s2avpBt0dLUbHLX + AgQzx5v6GpMMNwCkCrOnpFX6al7zkRSYHe7hbn03BBORz9mPHek5ew== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-03-02T07:58:00Z" + mac: ENC[AES256_GCM,data:OvERjDFfHTJbTfwq9BmXBQy6pjeyIhao6zP4we0KeYL3skbw4+aaMixjUFzjauby0C7nJjEPBSk6pwK3lN+rScS5g7J8tTNtmhfEDQbfsS5zNDKzIQjYxbUbDr2cTPWwCA73gRGMwLbyNvdfuEp46jNV8OJ8km/y2nyG9lDcBb4=,iv:0RSU2MdZWiYEapwXGzevP9/vc/Sk1MS6a0MnCRQyIs8=,tag:vvngXS2IRzH999yzo4JyFQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.4 diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 2791b74..391778f 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -108,6 +108,15 @@ in { iprev.verify = "relaxed"; spf.verify.ehlo = "relaxed"; spf.verify.mail-from = "relaxed"; + + # Sign *our* outgoing mails with the configured signatures. + dkim.sign = [ + { + "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; + "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; + } + {"else" = false;} + ]; }; # Forward outgoing mail to HRZ or mail VMs. @@ -202,12 +211,53 @@ in { sieve.trusted.from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM. sieve.trusted.from-name = "sender"; sieve.trusted.return-path = "sender"; + # If we are the sender, we sign the message with DKIM. Else we leave it alone. + sieve.trusted.sign = [ + { + "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; + "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; + } + {"else" = false;} + ]; sieve.trusted.limits = { redirects = 50; out-messages = 50; }; session.data.script = "'redirects'"; + # See https://stalw.art/docs/smtp/authentication/dkim/sign + # We need two blocks per domain because the domain setting in the blocks does not accept variables like `sender_domain`. + signature = let + signatureTemplate = domain: { + "rsa-${domain}" = { + private-key = "%{file:/run/secrets/dkim_rsa}%"; + domain = "${domain}"; + selector = "rsa-default"; + headers = ["From" "To" "Cc" "Date" "Subject" "Message-ID" "Organization" "MIME-Version" "Content-Type" "In-Reply-To" "References" "List-Id" "User-Agent" "Thread-Topic" "Thread-Index"]; + algorithm = "rsa-sha256"; + canonicalization = "relaxed/relaxed"; + }; + "ed25519-${domain}" = { + private-key = "%{file:/run/secrets/dkim_ed25519}%"; + domain = "${domain}"; + selector = "ed-default"; + headers = ["From" "To" "Cc" "Date" "Subject" "Message-ID" "Organization" "MIME-Version" "Content-Type" "In-Reply-To" "References" "List-Id" "User-Agent" "Thread-Topic" "Thread-Index"]; + algorithm = "ed25519-sha256"; + canonicalization = "relaxed/relaxed"; + }; + }; + in + map signatureTemplate (["lists.mathebau.de"] ++ (map ({domain, ...}: domain) cfg.domains)); + + # Sign *our* outgoing mails with the configured signatures. + auth.dkim.sign = [ + { + "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; + "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; + } + {"else" = false;} + ]; + authentication.fallback-admin = { user = "admin"; # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH From c5849b8695ed74dc415fe7f67546e4b987dee361 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 2 Mar 2025 11:57:05 +0100 Subject: [PATCH 10/13] Group config parameters --- nixos/modules/mail.nix | 124 ++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 391778f..720df68 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -101,7 +101,7 @@ in { # Reevaluate after DKIM and DMARC deployment spam.header.is-spam = "Dummyheader"; # disable moving to spam which would conflict with forwarding auth = { - # TODO check if HRZ conforms to these standards and we can validate them strictly + # TODO check if HRZ and our own VMs conform to these standards and we can validate them strictly dkim.verify = "relaxed"; arc.verify = "relaxed"; dmarc.verify = "relaxed"; @@ -140,52 +140,57 @@ in { starttls = "optional"; # e.g. Lobon does not offer starttls }; }; - remote."hrz" = { - address = "mailout.hrz.tu-darmstadt.de"; - port = 25; - protocol = "smtp"; - tls.implicit = false; # Don't assume TLS on this port but use STARTTLS - }; - remote."mailman" = { - address = "lobon.mathebau.de"; # must be created in DNS as a MX record because this field does not accept ip addresses. - port = 25; - protocol = "smtp"; - tls.implicit = false; # Don't assume TLS on this port but use STARTTLS + remote = { + "hrz" = { + address = "mailout.hrz.tu-darmstadt.de"; + port = 25; + protocol = "smtp"; + tls.implicit = false; # Don't assume TLS on this port but use STARTTLS + }; + "mailman" = { + address = "lobon.mathebau.de"; # must be created in DNS as a MX record because this field does not accept ip addresses. + port = 25; + protocol = "smtp"; + tls.implicit = false; # Don't assume TLS on this port but use STARTTLS + }; }; - session.rcpt = { - # In order to accept mail that we only forward - # without having to generate an account. - # Invalid addresses are filtered by DFN beforehand. - # See also https://stalw.art/docs/smtp/inbound/rcpt/#catch-all-addresses - catch-all = true; - relay = [ + session = { + ehlo.require = [ { - "if" = "!is_empty(authenticated_as) || rcpt_domain == 'lists.mathebau.de' || starts_with(remote_ip, '192.168.0.')"; #TODO restrict trust by IP - "then" = true; + "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly + "then" = false; } - {"else" = false;} + {"else" = true;} + ]; + ehlo.reject-non-fqdn = [ + { + "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly + "then" = false; + } + {"else" = true;} ]; - }; - session.ehlo.require = [ - { - "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly - "then" = false; - } - {"else" = true;} - ]; - session.ehlo.reject-non-fqdn = [ - { - "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly - "then" = false; - } - {"else" = true;} - ]; + rcpt = { + # In order to accept mail that we only forward + # without having to generate an account. + # Invalid addresses are filtered by DFN beforehand. + # See also https://stalw.art/docs/smtp/inbound/rcpt/#catch-all-addresses + catch-all = true; + relay = [ + { + "if" = "!is_empty(authenticated_as) || rcpt_domain == 'lists.mathebau.de' || starts_with(remote_ip, '192.168.0.')"; #TODO restrict trust by IP + "then" = true; + } + {"else" = false;} + ]; + }; + data.script = "'redirects'"; + }; # Stalwart gets its configuration from two places: A TOML configuration file that we control in this module # and from a database that can be configured from web management interface or via Rest API. - # We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" to the default ones + # We here define what comes from the TOML-file and especially add "sieve.trusted.*" to the default ones # because only TOML-based keys may use macros to load files from disk. # We want this to be able to load our sieve-script for mail forwarding. # See https://stalw.art/docs/configuration/overview/#local-and-database-settings for more details. @@ -207,24 +212,24 @@ in { "certificate.*" ] # the default ones ++ ["sieve.trusted.*"]; #for macros to be able to include our redirection script - sieve.trusted.scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script - sieve.trusted.from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM. - sieve.trusted.from-name = "sender"; - sieve.trusted.return-path = "sender"; - # If we are the sender, we sign the message with DKIM. Else we leave it alone. - sieve.trusted.sign = [ - { - "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; - "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; - } - {"else" = false;} - ]; - sieve.trusted.limits = { - redirects = 50; - out-messages = 50; + sieve.trusted = { + scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script + from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM. + from-name = "sender"; + return-path = "sender"; + # If we are the sender, we sign the message with DKIM. Else we leave it alone. + sign = [ + { + "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; + "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; + } + {"else" = false;} + ]; + limits = { + redirects = 50; + out-messages = 50; + }; }; - session.data.script = "'redirects'"; - # See https://stalw.art/docs/smtp/authentication/dkim/sign # We need two blocks per domain because the domain setting in the blocks does not accept variables like `sender_domain`. signature = let @@ -249,15 +254,6 @@ in { in map signatureTemplate (["lists.mathebau.de"] ++ (map ({domain, ...}: domain) cfg.domains)); - # Sign *our* outgoing mails with the configured signatures. - auth.dkim.sign = [ - { - "if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'"; - "then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]"; - } - {"else" = false;} - ]; - authentication.fallback-admin = { user = "admin"; # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH From b3a0936e30510578710fea39ede341c0fdd008aa Mon Sep 17 00:00:00 2001 From: Gonne Date: Mon, 3 Mar 2025 12:58:49 +0100 Subject: [PATCH 11/13] Alias file update --- nixos/machines/nyarlathotep/mathebau.aliases.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nixos/machines/nyarlathotep/mathebau.aliases.yaml b/nixos/machines/nyarlathotep/mathebau.aliases.yaml index a4d15fa..f808f69 100644 --- a/nixos/machines/nyarlathotep/mathebau.aliases.yaml +++ b/nixos/machines/nyarlathotep/mathebau.aliases.yaml @@ -1,4 +1,4 @@ -mathebau.aliases: ENC[AES256_GCM,data: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,iv:2jIbgMhGa8GWlDQeQNuAOrxiC03V7sdfy8EorUcjP5M=,tag:8/owPwtrW4khSqCraE+PDQ==,type:str] +mathebau.aliases: ENC[AES256_GCM,data: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,iv:Bxtv/WP4akeJGDECL9QTkBpGsc/u82uPQ131wOnFOY4=,tag:/4iI+VhtzpafIiuBkgpjIg==,type:str] sops: kms: [] gcp_kms: [] @@ -41,8 +41,8 @@ sops: Y21YcmlWTkJDRUh3czJEUWVGaG44cXMKoibsYSOYv329WNzktBVJ18aGAMXCxz3B c9938x3U7BCsSatnNch/cTbxPFYt8GhgAXXZb8/vsT9URH+9/K2iuA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-02-25T17:40:56Z" - mac: ENC[AES256_GCM,data:5jtuwMlqF+0FFo/QWnogC+Gm4ADUrhZLFJ9qoLMxDfrY8c8AHPDV+rNk9e/zO+tmqWcNmktWsVrK8xhmCTD8cszTMHdGRxjtqvjVatd+xjAziBik5SFR4pWO7doVx25iD6DOItARW8yxRLk+yMhTgWpe6ozxFhnGH+YdEH/rVNQ=,iv:f3xIO/MSBVfIeAfGtMUzqhY9/U10we/fftRe3/88uCA=,tag:nBSRI/FpOIqrknmlos9Vvg==,type:str] + lastmodified: "2025-03-03T11:58:32Z" + mac: ENC[AES256_GCM,data:0IAwyE28bwU1PHKsLvgaOSdrsiNO7Uyxw+FRxEknddLBDzgH8oKNHc5HOJ1qLsIBrJcUbo0hIOf1c6HQTSN82G+69TuhUsrENN6w86EVcUkL4GZRFbn48mQrQAjowz7JAGIdjwykJWOE2Mdacvk+5Hhvh3yW80QZ5OkxTCewkVg=,iv:kzwY5jDvEAx3I7czURxoeBE/DjFqXo5OfqqOuksKQiI=,tag:/K9gmH2roTZ7B436PIxZbA==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.4 From 67d81326060a5210b889e4ed4c462475a312f10e Mon Sep 17 00:00:00 2001 From: Gonne Date: Mon, 3 Mar 2025 14:49:42 +0100 Subject: [PATCH 12/13] Only set original sender for MAIL FROM --- nixos/modules/mail.nix | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 720df68..24d144c 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -214,9 +214,8 @@ in { ++ ["sieve.trusted.*"]; #for macros to be able to include our redirection script sieve.trusted = { scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script - from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM. - from-name = "sender"; - return-path = "sender"; + return-path = "sender"; # set the outgoing MAIL FROM to the original sender as specified in the incoming MAIL FROM. + # If we are the sender, we sign the message with DKIM. Else we leave it alone. sign = [ { From c24757321ef4ce2d1a775a095dce3bdea362ca43 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 4 Mar 2025 07:39:36 +0100 Subject: [PATCH 13/13] Hack around sieve execution for multiple recipients. --- nixos/modules/mail.nix | 4 ++++ nixos/modules/mailman.nix | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 24d144c..88bc59e 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -184,6 +184,10 @@ in { } {"else" = false;} ]; + # The sieve script only handles the last RCPT TO command (https://stalw.art/docs/sieve/variables). + # Since we want it to run for every recipient, we need to accept them one at a time. :-( + # This setting throws a temporary error for the second RCPT TO command after which the HRZ retries in a new connection. + max-recipients = 1; }; data.script = "'redirects'"; }; diff --git a/nixos/modules/mailman.nix b/nixos/modules/mailman.nix index 1c8eaba..b090ef0 100644 --- a/nixos/modules/mailman.nix +++ b/nixos/modules/mailman.nix @@ -43,7 +43,11 @@ in { webHosts = [cfg.hostName]; serve.enable = true; # # Don't include confirmation tokens in reply addresses, because we would need to send them to HRZ otherwise. - settings.mta.verp_confirmations = "no"; + settings.mta = { + verp_confirmations = "no"; + max_recipients = "1"; # We can only send to one recipient at a time due to how forwarding currently works. See also the mail module. + max_sessions_per_connection = "1"; + }; }; };