apt install postfix postfix-ldap certbot
Wählen Sie hier Internet Site
System mail name: domain.tld - das ist im Normalfall der Wert für myorigin
Das setzt /etc/mailname auf diesen Wert und macht sonst gar nix an der Postfix-Grundkonfiguration. myorigin ist der Wert der für alle Mails ohne Domain angehängt wird. https://wiki.debian.org/EtcMailName viel mehr macht der mailname auch nicht.
Zwingend 🗝️ LetsEncrypt-Zertifikat.
main.cf
myhostname = mx.domain.tld
# domain.tld
myorigin = /etc/mailname
mydestination = localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
mail_spool_directory = /var/vmail
home_mailbox = Maildir/
compatibility_level = 3.9
### SSL
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.domain.tld/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.domain.tld/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_protocols = >=TLSv1.3
tls_preempt_cipherlist = yes
tls_disable_workarounds = 0xFFFFFFFFFFFFFFFF
smtpd_tls_mandatory_ciphers = high
smtp_tls_security_level = encrypt
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_loglevel = $smtpd_tls_loglevel
smtp_tls_mandatory_protocols = $smtpd_tls_mandatory_protocols
smtp_tls_mandatory_ciphers = $smtpd_tls_mandatory_ciphers
smtp_tls_exclude_ciphers = $smtpd_tls_exclude_ciphers
### /SSL
### Alias
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
### Virtual Mailbox
virtual_mailbox_domains = domain.tld mail.domain.tld
### Transport
virtual_transport = lmtp:inet:[127.0.0.1]:24
### SMTPD
smtpd_sasl_type = dovecot
smtpd_sasl_path = inet:127.0.0.1:26
smtpd_sasl_auth_enable = yes
##### SMTPD Security
smtpd_sender_login_maps = ldap:/etc/postfix/ldap_lookups/smtpd_sender_login_maps
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
### Default Transport
relayhost = mx.domain.tld
#default_transport = smtp # Das ist so Standard
### SMTP
smtp_sasl_auth_enable = yes
smtp_sasl_tls_security_level = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/relay_password
https://www.spamhaus.com/data-access/free-data-query-service/ registrieren
https://docs.spamhaus.com/datasets/docs/source/40-real-world-usage/MTAs/020-Postfix.html lesen :)
$ apt install postfix-policyd-spf-python
https://manpages.debian.org/testing/postfix-policyd-spf-python/policyd-spf.conf.5.en.html
policyd-spf.conf
# For a fully commented sample config file see policyd-spf.conf.commented
# https://manpages.debian.org/testing/postfix-policyd-spf-python/policyd-spf.conf.5.en.html#LOGGING
debugLevel = 2
# nur loggen aber alle mails pass
TestOnly = 1
HELO_reject = Fail
Mail_From_reject = Fail
PermError_reject = False
TempError_Defer = False
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1
# Requirement for DMARC Reports
Header_Type = AR
Authserv_Id = mx.domain.tld
wenn alles geht Testonly = 0
master.cf
policy-spf unix - n n - - spawn
user=nobody argv=/usr/bin/policyd-spf
main.cf
policy-spf_time_limit = 3600s
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_policy_service unix:private/policy-spf,
reject_rbl_client query_key.zen.dq.spamhaus.net=127.0.0.[2..11]
reject_rhsbl_sender query_key.dbl.dq.spamhaus.net=127.0.1.[2..99]
reject_rhsbl_helo query_key.dbl.dq.spamhaus.net=127.0.1.[2..99]
reject_rhsbl_reverse_client query_key.dbl.dq.spamhaus.net=127.0.1.[2..99]
reject_rhsbl_sender query_key.zrd.dq.spamhaus.net=127.0.2.[2..24]
reject_rhsbl_helo query_key.zrd.dq.spamhaus.net=127.0.2.[2..24]
reject_rhsbl_reverse_client query_key.zrd.dq.spamhaus.net=127.0.2.[2..24]
# reject_rhsbl_helo dbl.spamhaus.org,
# reject_rhsbl_reverse_client dbl.spamhaus.org,
# reject_rhsbl_sender dbl.spamhaus.org,
# permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3],
# permit_dnswl_client swl.spamhaus.org,
# reject_rbl_client zen.spamhaus.org
rbl_reply_maps = hash:/etc/postfix/dnsbl-reply-map
dnsbl-reply-map
query_key.zen.dq.spamhaus.net=127.0.0.[2..11] 554 $rbl_class $rbl_what blocked using ZEN - see https://www.spamhaus.org/query/ip/$client_address for details
query_key.dbl.dq.spamhaus.net=127.0.1.[2..99] 554 $rbl_class $rbl_what blocked using DBL - see $rbl_txt for details
query_key.zrd.dq.spamhaus.net=127.0.2.[2..24] 554 $rbl_class $rbl_what blocked using ZRD - domain too young
query_key.zen.dq.spamhaus.net 554 $rbl_class $rbl_what blocked using ZEN - see https://www.spamhaus.org/query/ip/$client_address for details
query_key.dbl.dq.spamhaus.net 554 $rbl_class $rbl_what blocked using DBL - see $rbl_txt for details
query_key.zrd.dq.spamhaus.net 554 $rbl_class $rbl_what blocked using ZRD - domain too young
$ postmap dnsbl-reply-map
http://www.opendkim.org/docs.html
(ambigious syntax in signing.table, arch is better)
https://wiki.archlinux.org/title/OpenDKIM
$ apt install opendkim
Build socket
mkdir /var/spool/postfix/opendkim
chown -R opendkim:opendkim /var/spool/postfix/opendkim
chmod -R 750 /var/spool/postfix/opendkim
Add postfix uid to opendkim gid
usermod -aG opendkim postfix
/etc/opendkim.conf
# Defaults to MTA name so myhostname in postfix
#AuthservID mx.domain.tld
Syslog yes
SyslogSuccess yes
LogWhy yes
Canonicalization relaxed/relaxed
Mode sv
# needed if you send from subdomains, i recommend
SubDomains yes
OversignHeaders From
UserID opendkim
UMask 007
Socket local:/var/spool/postfix/opendkim/opendkim.sock
PidFile /run/opendkim/opendkim.pid
TrustAnchorFile /usr/share/dns/root.key
# Auto restart on failures, max 10/minute
AutoRestart true
AutoRestartRate 10/1M
# forks, default
Background yes
# default
DNSTimeout 5
SignatureAlgorithm rsa-sha256
# not required if a SigningTable is in use; in that case, the list of signed domains is implied by the lines in that file.
#Domain domain.tld
KeyTable refile:/etc/opendkim/key.table
SigningTable refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
$ mkdir /etc/opendkim
$ mkdir /etc/opendkim/keys
/etc/opendkim/trusted.hosts
127.0.0.1
::1
localhost
# needed?
10.lan.your.mailserver
.domain.tld
.deutschebahn.com
.bahn.de
build keys
/etc/opendkim/# opendkim-genkey -d domain.tld -b 2048 -r -s 20261224
move keys
mv 20261224.private keys/domain.tld.private
mv 20261224.txt keys/domain.tld.txt
/etc/opendkim/signing.table
@domain.tld 20261224._domainkey.domain.tld
/etc/opendkim/key.table
20260908._domainkey.domain.tld domain.tld:20260908:/etc/opendkim/keys/domain.tld.private
chown all
chown -R opendkim:opendkim /etc/opendkim
start
systemctl enable opendkim && systemctl start opendkim
liegen in der .txt bekommste hin
check
opendkim-testkey -d domain.tld -s 20261224 -vvv
http://www.trusteddomain.org/opendmarc/opendmarc.conf.5.html
$ apt install opendmarc
Ja brauch mysql ... db common errort erstmal einfach retry dann selbsterklärend
build socket
mkdir /var/spool/postfix/opendmarc
chown -R opendmarc:opendmarc /var/spool/postfix/opendmarc
chmod -R 750 /var/spool/postfix/opendmarc
usermod -aG opendmarc postfix
/etc/opendmarc.conf
# Defaults to /etc/mailname (?) - needs to match opendkim
AuthservID mx.domain.tld
# this just means we will not milter away already checked by opendkim mails
TrustedAuthservIDs mx.domain.tld
# set to true when all works
RejectFailures false
# technicallo not needed when IgnoreHosts is correct
IgnoreMailFrom domain.tld
IgnoreHosts /etc/opendmarc/ignore.hosts
IgnoreAuthenticatedClients false
# Auto restart on failures, max 10/minute
AutoRestart true
AutoRestartRate 10/1M
Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
PublicSuffixList /etc/opendmarc/public_suffix_list.dat
# Reports
# needed for aggregate reports to work, see script /etc/cron.hourly/opendmarc-reporting.sh
HistoryFile /var/run/opendmarc/opendmarc.dat
# Forensic Reports, not aggregate. DSGVO beachten.
FailureReports true
FailureReportsSentBy no-reply.dmarc.failurereports@domain.tld
# Debian defaults
PidFile /run/opendmarc/opendmarc.pid
PublicSuffixList /usr/share/publicsuffix/public_suffix_list.dat
#Socket local:/run/opendmarc/opendmarc.sock
Syslog true
UMask 0002
UserID opendmarc
eigene Server ignorieren:
mkdir /etc/opendmarc
touch /etc/opendmarc/ignore.hosts
127.0.0.1
::1
localhost
Public Suffixes in Debian evtl veraltet
wget --no-check-certificate -q -N -P /etc/opendmarc https://publicsuffix.org/list/public_suffix_list.dat
Alles chownen
chown -R opendmarc:opendmarc /etc/opendmarc
Starten
systemctl enable opendmarc && systemctl start opendmarc
forensic reports werden sofort versandt.
für aggregate reports:
opendmarc writes a report .dat file we can use to populate the mysql database and send out reports, then purge it again.
Deshalb muss man die dann aber auch wieder neu mit denselben Rechten erstellen.
touch /etc/cron.hourly/opendmarc-reporting.sh
chmod +x /etc/cron.hourly/opendmarc-reporting.sh
apt install zip
/etc/cron.hourly/opendmarc-reporting.sh
# Database Connection
DBHOST='localhost'
DBUSER='opendmarc'
DBPASS='StarkesPasswortVerwenden'
DBNAME='opendmarc'
# History-File
HISTDIR='/var/run/opendmarc'
HISTFILE='opendmarc'
# Report-Settings
REPORT_INTERVAL='86400'
REPORT_SENDER='no-reply.dmarc.reports@domain.tld'
REPORT_ORG='domain.tld'
REPORT_EXPIRE='90'
# Define a clean temp file
TMPFILE="/tmp/${HISTFILE}.$$"
# Delete the temp file automatically when the script exits (even on error)
trap 'rm -f "$TMPFILE"' EXIT
# Check history file exists
touch ${HISTDIR}/${HISTFILE}.dat
chown opendmarc:opendmarc ${HISTDIR}/${HISTFILE}.dat
# Move history file to Temp-Dir for processing
mv ${HISTDIR}/${HISTFILE}.dat "$TMPFILE"
# Import Temp history file data to MySQL DB and send reports
/usr/sbin/opendmarc-import -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} < "$TMPFILE"
/usr/sbin/opendmarc-reports -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} --interval=$REPORT_INTERVAL --report-email=$REPORT_SENDER --report-org=$REPORT_ORG
/usr/sbin/opendmarc-expire -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} --expire=$REPORT_EXPIRE
# (No manual rm line needed, trap handles it cleanly)
wer dafür bccs bekommen will:
/etc/postfix/bcc_map
no-reply.dmarc.reports@domain.tld bcc.dmarc.reports@domain.tld
/etc/postfix/main.cf
sender_bcc_maps = hash:/etc/postfix/bcc_map
/etc/postfix# postmap bcc_map
/etc/postfix/main.cf
## Milters
# The default action when a Milter (mail filter) response is unavailable
milter_default_action = accept
# default
milter_protocol = 6
smtpd_milters =
local:opendkim/opendkim.sock,
local:opendmarc/opendmarc.sock
# local, rarely used here
non_smtpd_milters =
${smtpd_milters}
apt install rsyslog
defaults are fine, but add
/etc/rsyslog.conf
...
mail.* -/var/log/mail.log
mail.err /var/log/mail.err
...
/etc/postfix/main.cf
header_checks = regexp:/etc/postfix/header_checks
/etc/postfix/header_checks
# Strip internal hop from authenticated clients
/^Received:.*with ESMTPSA/ IGNORE
/^Received:.*with ESMTPA/ IGNORE
# Optional: strip client fingerprinting headers
/^User-Agent:/ IGNORE
/^X-Mailer:/ IGNORE
/^X-Originating-IP:/ IGNORE
# RFC 8601 - strip any incoming forged Authentication-Results headers
# This makes sure we never get spoofed headers
/^Authentication-Results:.*mx\.domain\.tld/ IGNORE
header_checks runs in cleanup
/etc/opendmarc.conf
https://manpages.debian.org/unstable/opendmarc/opendmarc.conf.5.en.html
add these to harden SPF checks
SPFIgnoreResults true
SPFSelfValidate true
postscreen