2023-04-20 09:43:39 +00:00
|
|
|
# postfix config options: <https://www.postfix.org/postconf.5.html>
|
|
|
|
|
2023-04-20 14:25:59 +00:00
|
|
|
{ lib, pkgs, ... }:
|
2022-04-27 08:48:40 +00:00
|
|
|
|
2022-05-07 04:39:54 +00:00
|
|
|
let
|
|
|
|
submissionOptions = {
|
2022-05-11 06:41:34 +00:00
|
|
|
smtpd_tls_security_level = "encrypt";
|
|
|
|
smtpd_sasl_auth_enable = "yes";
|
|
|
|
smtpd_sasl_type = "dovecot";
|
|
|
|
smtpd_sasl_path = "/run/dovecot2/auth";
|
|
|
|
smtpd_sasl_security_options = "noanonymous";
|
|
|
|
smtpd_sasl_local_domain = "uninsane.org";
|
|
|
|
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
|
|
|
|
# reuse the virtual map so that sender mapping matches recipient mapping
|
|
|
|
smtpd_sender_login_maps = "hash:/var/lib/postfix/conf/virtual";
|
|
|
|
smtpd_sender_restrictions = "reject_sender_login_mismatch";
|
|
|
|
smtpd_recipient_restrictions = "reject_non_fqdn_recipient,permit_sasl_authenticated,reject";
|
2022-05-07 04:39:54 +00:00
|
|
|
};
|
|
|
|
in
|
2022-04-27 08:48:40 +00:00
|
|
|
{
|
2023-01-06 11:29:13 +00:00
|
|
|
sane.persist.sys.plaintext = [
|
2022-07-11 00:58:16 +00:00
|
|
|
# TODO: mode? could be more granular
|
2023-07-08 00:56:20 +00:00
|
|
|
{ user = "opendkim"; group = "opendkim"; path = "/var/lib/opendkim"; }
|
|
|
|
{ user = "root"; group = "root"; path = "/var/lib/postfix"; }
|
|
|
|
{ user = "root"; group = "root"; path = "/var/spool/mail"; }
|
2022-10-22 14:00:56 +00:00
|
|
|
# *probably* don't need these dirs:
|
|
|
|
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
|
|
|
|
# "/var/lib/dovecot"
|
2022-07-11 00:58:16 +00:00
|
|
|
];
|
2022-12-11 16:12:23 +00:00
|
|
|
|
2023-05-31 04:25:39 +00:00
|
|
|
sane.ports.ports."25" = {
|
|
|
|
protocol = [ "tcp" ];
|
|
|
|
visibleTo.ovpn = true;
|
|
|
|
description = "colin-smtp-mx.uninsane.org";
|
|
|
|
};
|
|
|
|
sane.ports.ports."465" = {
|
|
|
|
protocol = [ "tcp" ];
|
|
|
|
visibleTo.ovpn = true;
|
|
|
|
description = "colin-smtps-mx.uninsane.org";
|
|
|
|
};
|
|
|
|
sane.ports.ports."587" = {
|
|
|
|
protocol = [ "tcp" ];
|
|
|
|
visibleTo.ovpn = true;
|
|
|
|
description = "colin-smtps-submission-mx.uninsane.org";
|
|
|
|
};
|
2022-12-11 16:12:23 +00:00
|
|
|
|
2022-12-17 00:52:48 +00:00
|
|
|
# exists only to manage certs for Postfix
|
|
|
|
services.nginx.virtualHosts."mx.uninsane.org" = {
|
|
|
|
enableACME = true;
|
|
|
|
};
|
|
|
|
|
2022-12-17 01:29:12 +00:00
|
|
|
|
2023-06-07 23:34:00 +00:00
|
|
|
sane.dns.zones."uninsane.org".inet = {
|
2023-01-02 13:23:52 +00:00
|
|
|
MX."@" = "10 mx.uninsane.org.";
|
2022-12-19 04:38:41 +00:00
|
|
|
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
2023-01-02 13:23:52 +00:00
|
|
|
A."mx" = "185.157.162.178";
|
2022-12-17 01:29:12 +00:00
|
|
|
|
2022-12-19 04:38:41 +00:00
|
|
|
# Sender Policy Framework:
|
|
|
|
# +mx => mail passes if it originated from the MX
|
|
|
|
# +a => mail passes if it originated from the A address of this domain
|
|
|
|
# +ip4:.. => mail passes if it originated from this IP
|
|
|
|
# -all => mail fails if none of these conditions were met
|
2023-01-02 13:23:52 +00:00
|
|
|
TXT."@" = "v=spf1 a mx -all";
|
2022-12-17 01:29:12 +00:00
|
|
|
|
2022-12-19 04:38:41 +00:00
|
|
|
# DKIM public key:
|
2023-01-02 13:23:52 +00:00
|
|
|
TXT."mx._domainkey" =
|
2023-03-14 11:35:34 +00:00
|
|
|
"v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
2023-01-02 13:23:52 +00:00
|
|
|
;
|
2022-12-17 01:29:12 +00:00
|
|
|
|
2022-12-19 04:38:41 +00:00
|
|
|
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
|
|
|
|
# p=none|quarantine|reject: what to do with failures
|
|
|
|
# sp = p but for subdomains
|
|
|
|
# rua = where to send aggregrate reports
|
|
|
|
# ruf = where to send individual failure reports
|
|
|
|
# fo=0|1|d|s controls WHEN to send failure reports
|
|
|
|
# (1=on bad alignment; d=on DKIM failure; s=on SPF failure);
|
|
|
|
# Additionally:
|
|
|
|
# adkim=r|s (is DKIM relaxed [default] or strict)
|
|
|
|
# aspf=r|s (is SPF relaxed [default] or strict)
|
|
|
|
# pct = sampling ratio for punishing failures (default 100 for 100%)
|
|
|
|
# rf = report format
|
|
|
|
# ri = report interval
|
2023-01-02 13:23:52 +00:00
|
|
|
TXT."_dmarc" =
|
2022-12-19 04:38:41 +00:00
|
|
|
"v=DMARC1;p=quarantine;sp=reject;rua=mailto:admin+mail@uninsane.org;ruf=mailto:admin+mail@uninsane.org;fo=1:d:s"
|
2023-01-02 13:23:52 +00:00
|
|
|
;
|
2022-12-19 04:38:41 +00:00
|
|
|
};
|
2022-12-17 01:29:12 +00:00
|
|
|
|
2022-04-28 07:22:03 +00:00
|
|
|
services.postfix.enable = true;
|
2022-04-27 08:48:40 +00:00
|
|
|
services.postfix.hostname = "mx.uninsane.org";
|
2022-04-28 07:22:03 +00:00
|
|
|
services.postfix.origin = "uninsane.org";
|
2022-05-07 04:39:54 +00:00
|
|
|
services.postfix.destination = [ "localhost" "uninsane.org" ];
|
|
|
|
services.postfix.sslCert = "/var/lib/acme/mx.uninsane.org/fullchain.pem";
|
|
|
|
services.postfix.sslKey = "/var/lib/acme/mx.uninsane.org/key.pem";
|
2022-04-28 07:22:03 +00:00
|
|
|
|
|
|
|
services.postfix.virtual = ''
|
2022-05-11 06:41:34 +00:00
|
|
|
notify.matrix@uninsane.org matrix-synapse
|
2022-04-28 07:22:03 +00:00
|
|
|
@uninsane.org colin
|
|
|
|
'';
|
|
|
|
|
2023-04-20 14:25:59 +00:00
|
|
|
services.postfix.config = {
|
2022-04-28 07:22:03 +00:00
|
|
|
# smtpd_milters = local:/run/opendkim/opendkim.sock
|
2022-05-06 11:43:17 +00:00
|
|
|
# milter docs: http://www.postfix.org/MILTER_README.html
|
2023-04-20 14:25:59 +00:00
|
|
|
# mail filters for receiving email and from authorized SMTP clients (i.e. via submission)
|
2022-05-06 11:43:17 +00:00
|
|
|
# smtpd_milters = inet:185.157.162.190:8891
|
2023-04-20 14:25:59 +00:00
|
|
|
# opendkim.sock will add a Authentication-Results header, with `dkim=pass|fail|...` value to received messages
|
|
|
|
smtpd_milters = "unix:/run/opendkim/opendkim.sock";
|
2022-05-06 11:43:17 +00:00
|
|
|
# mail filters for sendmail
|
2023-04-20 14:25:59 +00:00
|
|
|
non_smtpd_milters = "$smtpd_milters";
|
|
|
|
|
|
|
|
# what to do when a milter exits unexpectedly:
|
|
|
|
milter_default_action = "accept";
|
|
|
|
|
|
|
|
inet_protocols = "ipv4";
|
|
|
|
smtp_tls_security_level = "may";
|
|
|
|
|
|
|
|
# hand received mail over to dovecot so that it can run sieves & such
|
|
|
|
mailbox_command = ''${pkgs.dovecot}/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"'';
|
|
|
|
|
|
|
|
# hand received mail over to dovecot
|
|
|
|
# virtual_alias_maps = [
|
|
|
|
# "hash:/etc/postfix/virtual"
|
|
|
|
# ];
|
|
|
|
# mydestination = "";
|
|
|
|
# virtual_mailbox_domains = [ "localhost" "uninsane.org" ];
|
|
|
|
# # virtual_mailbox_maps = "hash:/etc/postfix/virtual";
|
|
|
|
# virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
2023-04-20 09:17:25 +00:00
|
|
|
|
|
|
|
# anti-spam options: <https://www.postfix.org/SMTPD_ACCESS_README.html>
|
|
|
|
# reject_unknown_sender_domain: causes postfix to `dig <sender> MX` and make sure that exists.
|
|
|
|
# but may cause problems receiving mail from google & others who load-balance?
|
|
|
|
# - <https://unix.stackexchange.com/questions/592131/how-to-reject-email-from-unknown-domains-with-postfix-on-centos>
|
|
|
|
# smtpd_sender_restrictions = reject_unknown_sender_domain
|
2023-04-20 14:25:59 +00:00
|
|
|
};
|
2022-04-28 07:22:03 +00:00
|
|
|
|
2022-05-07 04:39:54 +00:00
|
|
|
services.postfix.enableSubmission = true;
|
|
|
|
services.postfix.submissionOptions = submissionOptions;
|
|
|
|
services.postfix.enableSubmissions = true;
|
|
|
|
services.postfix.submissionsOptions = submissionOptions;
|
|
|
|
|
2023-01-19 07:45:14 +00:00
|
|
|
systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ];
|
|
|
|
systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ];
|
2022-05-06 11:43:17 +00:00
|
|
|
systemd.services.postfix.serviceConfig = {
|
|
|
|
# run this behind the OVPN static VPN
|
|
|
|
NetworkNamespacePath = "/run/netns/ovpns";
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-04-20 14:25:59 +00:00
|
|
|
#### OPENDKIM
|
|
|
|
|
2022-04-28 07:22:03 +00:00
|
|
|
services.opendkim.enable = true;
|
2022-05-06 11:43:17 +00:00
|
|
|
# services.opendkim.domains = "csl:uninsane.org";
|
|
|
|
services.opendkim.domains = "uninsane.org";
|
2022-04-28 07:22:03 +00:00
|
|
|
|
|
|
|
# we use a custom (inet) socket, because the default perms
|
2022-05-06 11:43:17 +00:00
|
|
|
# of the unix socket don't allow postfix to connect.
|
|
|
|
# this sits on the machine-local 10.0.1 interface because it's the closest
|
|
|
|
# thing to a loopback interface shared by postfix and opendkim netns.
|
|
|
|
# services.opendkim.socket = "inet:8891@185.157.162.190";
|
|
|
|
# services.opendkim.socket = "local:/run/opendkim.sock";
|
2022-04-28 07:22:03 +00:00
|
|
|
# selectors can be used to disambiguate sender machines.
|
|
|
|
# keeping this the same as the hostname seems simplest
|
|
|
|
services.opendkim.selector = "mx";
|
2022-05-03 00:44:15 +00:00
|
|
|
|
2023-01-19 07:45:14 +00:00
|
|
|
systemd.services.opendkim.after = [ "wireguard-wg-ovpns.service" ];
|
|
|
|
systemd.services.opendkim.partOf = [ "wireguard-wg-ovpns.service" ];
|
2022-05-06 11:43:17 +00:00
|
|
|
systemd.services.opendkim.serviceConfig = {
|
2022-05-03 00:44:15 +00:00
|
|
|
# run this behind the OVPN static VPN
|
|
|
|
NetworkNamespacePath = "/run/netns/ovpns";
|
2022-05-06 11:43:17 +00:00
|
|
|
# /run/opendkim/opendkim.sock needs to be rw by postfix
|
|
|
|
UMask = lib.mkForce "0011";
|
2022-05-03 00:44:15 +00:00
|
|
|
};
|
2022-05-07 02:25:18 +00:00
|
|
|
|
2022-05-10 23:15:01 +00:00
|
|
|
|
|
|
|
#### OUTGOING MESSAGE REWRITING:
|
|
|
|
services.postfix.enableHeaderChecks = true;
|
|
|
|
services.postfix.headerChecks = [
|
|
|
|
# intercept gitea registration confirmations and manually screen them
|
|
|
|
{
|
|
|
|
# headerChecks are somehow ignorant of alias rules: have to redirect to a real user
|
|
|
|
action = "REDIRECT colin@uninsane.org";
|
|
|
|
pattern = "/^Subject: Please activate your account/";
|
|
|
|
}
|
2022-05-11 06:41:34 +00:00
|
|
|
# intercept Matrix registration confirmations
|
|
|
|
{
|
|
|
|
action = "REDIRECT colin@uninsane.org";
|
|
|
|
pattern = "/^Subject:.*Validate your email/";
|
|
|
|
}
|
2022-05-10 23:15:01 +00:00
|
|
|
# XXX postfix only supports performing ONE action per header.
|
|
|
|
# {
|
|
|
|
# action = "REPLACE Subject: git application: Please activate your account";
|
|
|
|
# pattern = "/^Subject:.*activate your account/";
|
|
|
|
# }
|
|
|
|
];
|
2022-04-27 08:48:40 +00:00
|
|
|
}
|