nyarlathotep: cleanup after deployment #55
|
@ -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
|
||||
nerf marked this conversation as resolved
Outdated
|
||||
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
|
||||
};
|
||||
};
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
the diff is very confusing here, this line should be compared to 182 in green the diff is very confusing here, this line should be compared to 182 in green
|
||||
|
||||
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
|
||||
nerf
commented
Is there still something left in the database that we could move here? Is there still something left in the database that we could move here?
Gonne
commented
The list of domains served by stalwart and the existence of catch-all accounts remains in the database, but I have not found out how do set them from config. The list of domains served by stalwart and the existence of catch-all accounts remains in the database, but I have not found out how do set them from config.
nerf
commented
I think we should move it to the config file, or do we need to dynamically change these? I think we should move it to the config file, or do we need to dynamically change these?
Gonne
commented
Yes, at least while we don't provide mail boxes. But I don't know how. Yes, at least while we don't provide mail boxes. But I don't know how.
nerf
commented
That mailboxes need some state attached to them is clear to me (not necessarily, which mail boxes but user generated sieve scripts for example). Maybe I should open another question in the stalwart discussion thing. That mailboxes need some state attached to them is clear to me (not necessarily, which mail boxes but user generated sieve scripts for example). Maybe I should open another question in the stalwart discussion thing.
|
||||
# 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
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
maybe we should move this file from maybe we should move this file from `/tmp` into the `/run` directory as this usually has proper
file access rights set up.
Gonne
commented
There is also Reading https://lwn.net/Articles/436012/ I have no idea whether There is also `JoinsNamespaceOf` for `PrivateTmp` of systemd service units (https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html) but I didn't succeed setting it.
Reading https://lwn.net/Articles/436012/ I have no idea whether `/run` is a better place.
nerf
commented
We don't care about the early boot discussion. So the question is, is it runtime date or temporary data, wherever the boundary between these two is. Putting things in If we already follow Lennart's advice then we also should use So after reading all of this maybe the cleanest option is to get the We don't care about the early boot discussion. So the question is, is it runtime date or temporary data, wherever the boundary between these two is. Putting things in `/tmp` is often a buggy mess as this directory is usually somewhat of a global dumpster fire, where there are no guarantees that this file does not already exist with some important information for some other process (though unlikely). `PrivateTmp` would save us here, but even the documentation says that one should not rely on this (and we would need to get it to work).
If we already follow Lennart's advice then we also should use `mkstemp` to generate files in `/tmp` which will
be very painful in a nix setting (as paths and filenames will only be available at runtime). Lennart also seems to think that `/run` is primarily for communication primitives (is this one?).
See [his blogpost](https://0pointer.net/blog/projects/tmp.html).
So after reading all of this maybe the cleanest option is to get the `JoinNamespaceOf` option to work?
Gonne
commented
I got the private I got the private `/tmp` with `JoinsNamespaceOf` working.
|
||||
from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM.
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
the the `trusted` part is to much, also see the comment at `from-name` below
|
||||
from-name = "sender";
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
I couldn't figure out what I couldn't figure out what `from-name` or `from-addr` actually do. Reading the documentation I believe combined they
set the default value for the `From:` header of a generated mail. But I couldn't verify this in tests.
Maybe it does something different that has to do with the `MAIL FROM:` see comment below
nerf marked this conversation as resolved
nerf
commented
where did the where did the `/tmp` folder discussion disappeared to?
nerf
commented
ahh it got marked outdated ahh it got marked outdated
|
||||
return-path = "sender";
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
This seems to do what we want, even though the documentation reads like it sets the This seems to do what we want, even though the documentation reads like it sets the `Return-Path:` header. But it seems to set the reverse path (which is the argument to the `MAIL FROM:` smtp command). Maybe it does both?
nerf
commented
This parameter seems to control the This parameter seems to control the `MAIL FROM:` and with this all the headers we want to set.
The documentation reads to me as if it sets the `Return-Path:` header. I'm unsure if it actually does it.
|
||||
# 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
|
||||
|
|
But Mailman shouldn't sign its mail, right? how do we solve that?
Possibly by moving all submission from our other vms to a separate listener.
I open an issue for later