This is a document copied from https://www.tornevalls.se/2019/08/12/the-postfix-maildir-guide/
...
The spamassassin server is separately installed. Actually, spamassassin are running through an AWS (amazon free tier to be exact). The installation looks like this:
Code Block | ||||
---|---|---|---|---|
| ||||
apt-get -y install spamassassin spamc razor pyzor spambayes apt-get install libcrypt-ssleay-perl libio-socket-ssl-perl razor libnet-ident-perl libdbi-perl pyzor libmail-dkim-perl apt-get install opendkim opendkim-tools opendmarc |
As you can see above, the spamassassin server has pyzor and razor as options. This is quite weird part, that mostly actually works but needs initialization first. The packages I used for several years ago stinks, since they was manually installed. Gladly, those were apt-gettable. The initialization was quite simple. As long as your paths are correctly installed, as there are some places to keep in mind that may differ. But first, the initialization:
Code Block | ||||
---|---|---|---|---|
| ||||
razor-admin -home=/etc/spamassassin/.razor -register
razor-admin -home=/etc/spamassassin/.razor -create
razor-admin -home=/etc/spamassassin/.razor -discover |
To keep in mind
- /etc/mail
- /etc/spamassassin
- /etc/mail/spamassassin
During my years with qmail, I'm no longer sure about how those paths are linked together. I have several scripts that makes sure that everything else is set up properly, based on newer and older information (this is very unfortunate). For example /etc/mail/spamassassin is symlinked to /etc/spamassassin, just to be sure that applications finds everything in one place and not bombed all over the place.
Next?
The configuration may be very frustrating from time to time. While installing postfix, courier, etc, you may get warnings from the system about courier users and SSL certificates. When I started this project I chose to ignore it, until I got control over postfix. So how do my postfix configuration look? Because this is a quite important part of everything. There's a lot of things to think of to really make this work out on all levels. This is my level requirement list:
- Postfix should support virtual domains and users
- Postfix should support spamassassin, make use of standard sendmail and spamassassin without weird extra installations. People out there seem to be extremely complex (and stupid) from time to time.
- My networks should be trusted in a very tiny setup; only relays should now about each other.
- The entire world should, primarily, use authentication to be allowed to SEND mail from postfix.
- The rest of the world should be prohibited to relay e-mail via postfix, but STILL deliver mail to the virtual domains.
The above combination is quite interesting, because on the way through this configuration I found out that postfix is not allowing "relaying" unless it is properly configured. By means, doing all this setups should still allow any other useraccount-based email sending. As it seems, many people have huge problems with this combination. Besides, sendmail is - as I can see - the base core of postfix in some "cases", but people also seem to not use this solution. Don't ask me why. Probably it is something like "we cannot make everything work together by using default applications". As I want a standard installation to be extended, I went through with this. So here goes.
Some of the rows below are changed to fit my needs. For example, the standard smtpd_banner is ugly. And it reveals quite a lot of why I run. So this got replaced with my own half static banner, as I still wanted to identify the mailserver by hostname (so I could get use of more, know which I use and to be compliant with other spamcheckers online).
Code Block | ||||
---|---|---|---|---|
| ||||
# myhostname is fetched from /etc/hostname if not set here. Together with mydomain in this configuration # your servername will be quite accurate in it's greeting. smtpd_banner = $myhostname ESMTP $mail_name biff = no # The basic stuff. mydomain = #my-zone-name# myorigin = /etc/mailname mydestination = $myhostname, localhost # appending .domain is the MUA's job. append_dot_mydomain = no readme_directory = no compatibility_level = 2 # TLS parameters smtpd_tls_cert_file=/etc/letsencrypt/live/#my-zone-name#/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/#my-zone-name#/privkey.pem smtpd_use_tls=yes smtpd_tls_session_cache_database = # If you run on focal, you will get a problem with the spambayes candidate. So that will run separately (for example for bionic). # E: Package 'spambayes' has no installation candidate apt-get -y install spambayes apt-get -y install libcrypt-ssleay-perl libio-socket-ssl-perl razor libnet-ident-perl libdbi-perl pyzor libmail-dkim-perl apt-get -y install opendkim opendkim-tools opendmarc |
As you can see above, the spamassassin server has pyzor and razor as options. This is quite weird part, that mostly actually works but needs initialization first. The packages I used for several years ago stinks, since they was manually installed. Gladly, those were apt-gettable. The initialization was quite simple. As long as your paths are correctly installed, as there are some places to keep in mind that may differ. But first, the initialization:
Code Block | ||||
---|---|---|---|---|
| ||||
razor-admin -home=/etc/spamassassin/.razor -register
razor-admin -home=/etc/spamassassin/.razor -create
razor-admin -home=/etc/spamassassin/.razor -discover |
To keep in mind
- /etc/mail
- /etc/spamassassin
- /etc/mail/spamassassin
During my years with qmail, I'm no longer sure about how those paths are linked together. I have several scripts that makes sure that everything else is set up properly, based on newer and older information (this is very unfortunate). For example /etc/mail/spamassassin is symlinked to /etc/spamassassin, just to be sure that applications finds everything in one place and not bombed all over the place.
Next?
The configuration may be very frustrating from time to time. While installing postfix, courier, etc, you may get warnings from the system about courier users and SSL certificates. When I started this project I chose to ignore it, until I got control over postfix. So how do my postfix configuration look? Because this is a quite important part of everything. There's a lot of things to think of to really make this work out on all levels. This is my level requirement list:
- Postfix should support virtual domains and users
- Postfix should support spamassassin, make use of standard sendmail and spamassassin without weird extra installations. People out there seem to be extremely complex (and stupid) from time to time.
- My networks should be trusted in a very tiny setup; only relays should now about each other.
- The entire world should, primarily, use authentication to be allowed to SEND mail from postfix.
- The rest of the world should be prohibited to relay e-mail via postfix, but STILL deliver mail to the virtual domains.
The above combination is quite interesting, because on the way through this configuration I found out that postfix is not allowing "relaying" unless it is properly configured. By means, doing all this setups should still allow any other useraccount-based email sending. As it seems, many people have huge problems with this combination. Besides, sendmail is - as I can see - the base core of postfix in some "cases", but people also seem to not use this solution. Don't ask me why. Probably it is something like "we cannot make everything work together by using default applications". As I want a standard installation to be extended, I went through with this. So here goes.
Some of the rows below are changed to fit my needs. For example, the standard smtpd_banner is ugly. And it reveals quite a lot of why I run. So this got replaced with my own half static banner, as I still wanted to identify the mailserver by hostname (so I could get use of more, know which I use and to be compliant with other spamcheckers online).
Code Block | ||||
---|---|---|---|---|
| ||||
# myhostname is fetched from /etc/hostname if not set here. Together with mydomain in this configuration
# your servername will be quite accurate in it's greeting.
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
# The basic stuff.
mydomain = #my-zone-name#
myorigin = /etc/mailname
mydestination = $myhostname, localhost
# appending .domain is the MUA's job.
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
# TLS parameters
smtpd_tls_cert_file=/etc/letsencrypt/live/#my-zone-name#/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/#my-zone-name#/privkey.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Authentication
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions = permit_mx_backup permit_auth_destination permit_sasl_authenticated permit_mynetworks reject_unauth_destination
smtpd_sasl_path = smtpd
# SMTP Settings
smtpd_tls_loglevel = 3
smtpd_relay_restrictions = permit_mx_backup permit_auth_destination permit_mynetworks permit_sasl_authenticated defer_unauth_destination
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
relayhost = #my-real-relay-server#:#safe-smtp-port#
# NOTE: This should be replaced with trusted addresses
mynetworks = 127.0.0.255
127.0.0.0/8
ip/32
ip-subnet-range/28
[::ffff:127.0.0.0]/104
[::1]/128
[ip-subnet-range]/48
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
# Warning: Run on DigitalOcean? Make sure ipv6 are tunnelled or disabled.
inet_protocols = all
fallback_relay = #my-safe-relay-backup-server#:#safe-smtp-port#
# Do not list major domain in BOTH virtual_alias_domains and relay_domains
# Virtual Aliases, Splitted by zone
virtual_alias_maps =
regexp:/etc/postfix/virtual/virtual_users_regex
hash:/etc/postfix/virtual/virtual_users_#zone-1#
hash:/etc/postfix/virtual/virtual_users_#zone-2#
hash:/etc/postfix/virtual/virtual_users_common
recipient_bcc_maps = hash:/etc/postfix/recipient_bcc_maps
virtual_alias_domains = hash:/etc/postfix/virtual_domains
virtual_mailbox_domains = /etc/postfix/virtual_domains
relay_domains = hash:/etc/postfix/relaydomains
header_checks = regexp:/etc/postfix/header_checks
#smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
relay_recipient_maps = hash:/etc/postfix/relay_recipient_maps
transport_maps = hash:/etc/postfix/transport
# Maildir setup
virtual_mailbox_base = /var/spool/mail
home_mailbox = Maildir/
# Milter Configuration
milter_default_action = accept
milter_protocol = 6
# SMTPD MILTERS - RUNNING TCP INSTEAD OF SOCKETS ETC AS THIS IS WAY TO BUGGY. DO NOT TRUST ANY DOCUMENTS OUT THERE OF HOW
# TO GET THIS FIXED!!
smtpd_milters = inet:#tcpport#
non_smtpd_milters = inet:#tcpport#
mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=$HOME/Maildir/ MAILDIR=$HOME/Maildir
spamassassin_destination_recipient_limit = 1 |
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
mkdir -p /var/spool/postfix#!/bin/bash rl=$(readlink /var/run/saslauthd chgrp sasl /var/spool/postfix/var/) if [ "" != "$rl" ] ; then echo "/var/run/saslauthd adduser postfix sasl is symlinked already." exit fi mkdir -p /var/spool/postfix/var/run/saslauthd chgrp sasl /var/spool/postfix/var/run/saslauthd adduser postfix sasl # Problems with /var/run/saslauthd that should be fixed. If it exists, remove it for instance... rmdir /var/run/saslauthd >/dev/null 2>&1 # Then symlink it away. ln -sv /var/spool/postfix/var/run/saslauthd /var/run # By the way, if saslauthd is not autostarted, it should really be changed. sed -i 's/START=no/START=yes/' /etc/default/saslauthd # Do not forget to restart the daemons. service >/dev/null 2>&1 if [ "$?" != "" ] ; then echo "Obviously something is wrong here." theDate=$(date +'%Y%m%d%H%M') mv -v /var/run/saslauthd /var/run/saslauthd-${theDate} ln -sv /var/spool/postfix/var/run/saslauthd /var/run fi # By the way, if saslauthd is not autostarted, it should really be changed. sed -i 's/START=no/START=yes/' /etc/default/saslauthd # Do not forget to restart the daemons. service postfix restart service saslauthd restart |
...
DKIM is very special as it needs keys to be added into the DNS. The DNS update is not automated in this document (yet). I just generate the keys and then paste them into the DNS.
However, it takes time doing this manually so this is the script that creates what I need – OBSERVE THAT THIS IS ONLY AN EXAMPLE ON HOW WE DO IT:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/bin/bash YYYYMM=$(date +%Y%m) path=/etc/opendkim/keys okey=$(which opendkim-genkey) dkimu=$(grep dkim /etc/group|grep postfix) if [ "" = "$dkimu" ] ; then echo "postfix user must be present in group for dkim" exit fi if [ ! -d /etc/opendkim ] ; then ln -sv /var/tornevall/system/etc/opendkim /etc/opendkim fi rl=$(readlink /etc/opendkim.conf) if [ -f /etc/opendkim.conf ] ; then if [ "" = "$rl" ] ; then mv /etc/opendkim.conf /etc/opendkim.conf.old ln -sv /var/tornevall/system/etc/opendkim.conf /etc/opendkim.conf fi chmod u=rw,go=r /etc/opendkim.conf chmod u=rw,go=r /var/tornevall/system/etc/opendkim.conf else if [ -f /var/tornevall/system/etc/opendkim.conf ] ; then ln -sv /var/tornevall/system/etc/opendkim.conf /etc/opendkim.conf fi fi if [ "" = "$okey" ] ; then echo "opendkim missing, trying to install..." apt-get -y -f install opendkim opendkim-tools >/dev/null 2>&1 okey=$(which opendkim-genkey) if [ "" = "$okey" ] ; then echo "Could not install opendkim ..." exit fi echo "OK, ready!" fi if [ "" = "$2" ] ; then echo "Usage: $0 domain shortname" exit fi domain=$1 short=$2 if [ ! -f /etc/opendkim/signing.table ] ; then touch /etc/opendkim/signing.table fi if [ ! -f /etc/opendkim/key.table ] ; then touch /etc/opendkim/key.table fi echo "$domain - /etc/opendkim/signing.table" dom=$(grep $domain /etc/opendkim/signing.table) if [ "" = "$dom" ] ; then echo "*@${domain} ${short}" >>/etc/opendkim/signing.table echo "Added $domain (short=$short) to /etc/opendkim/signing.table" else echo "Domain already exists in signing.table - please remove it from that table and the key.table to start over." exit fi dom=$(grep $domain /etc/opendkim/key.table) if [ "" = "$dom" ] ; then echo "${short} ${domain}:${YYYYMM}:/etc/opendkim/keys/${short}.private" >>/etc/opendkim/key.table echo "Added $domain (short=$short) to /etc/opendkim/keys/${short}.private" fi echo opendkim-genkey -b 2048 -h rsa-sha256 -r -s ${YYYYMM} -d $domain -v opendkim-genkey -b 2048 -h rsa-sha256 -r -s ${YYYYMM} -d $domain -v rm -vf keys/${short}.private rm -vf ${short}.txt mv -v ${YYYYMM}.private keys/${short}.private mv -v ${YYYYMM}.txt ${short}.txt chown -R opendkim:opendkim /etc/opendkim chmod -R go-rwx /etc/opendkim/keys echo "Fixing SHA-problem by sed ..." sed -i 's/h=rsa-sha256/h=sha256/' ${short}.txt chown opendkim:postfix -Rv /etc/opendkim/ echo "Restarting dkim ..." service opendkim restart |
...
No Format |
---|
# Log to syslog Syslog yes # Required to use local socket with MTAs that access the socket as a non- # privileged user (e.g. Postfix) UMask 007 # OpenDKIM user. Remember to add postfix to group opendkim. UserID opendkim KeyTable /etc/opendkim/key.table SigningTable refile:/etc/opendkim/signing.table # Hosts to ignore when verifying signatures ExternalIgnoreList /etc/opendkim/trusted.hosts InternalHosts /etc/opendkim/trusted.hosts # Commonly-used options; the commented-out versions show the defaults. Canonicalization relaxed/relaxed Mode sv SubDomains no AutoRestart yes AutoRestartRate 10/1M Background yes DNSTimeout 5 SignatureAlgorithm rsa-sha256 Socket inet:#tcpport#@localhost PidFile /var/run/opendkim/opendkim.pid OversignHeaders From TrustAnchorFile /usr/share/dns/root.key |
SpamAssassin
SpamAssassin is very specific configuration. I will not cover the basic setup for SpamAssassin here as it usually works as is. Besides, I run SpamAssassin via mysql-setups and rules, which is a very personal setup. Normally, you won't need think of it here. The important thing with this post is the actual postfix setup.
Clients that does not support SMTP authentication via imap or pop
This text is written in october 2020 after ripping my hair of my head off for a while. What I did not think of, during the first round of installation, was that there will be non standard clients that won't do a pop/smtp-auth before entering the SMTP out. For example, Postfix, straight out of the box - where you want to relay from postfix to postfix via an authenticated user. With the solution above, there might happen things that you do not want. The error message below for example, is quite common but very much unanswered in different kinds of forums. Most of the posts are relating their problems to dovecot, cyrus and different kind of solutions that in the end seem to be database driven. This is not bad, it's just a little bit stupid since you suddenly rely your systems on yet another point of failure: The database. And the more crap you implement, the harder it will be to find the failing point.
No Format |
---|
warning: SASL 5 SignatureAlgorithm rsa-sha256 Socket inet:#tcpport#@localhost PidFile /var/run/opendkim/opendkim.pid OversignHeaders From TrustAnchorFile /usr/share/dns/root.key |
SpamAssassin
SpamAssassin is very specific configuration. I will not cover the basic setup for SpamAssassin here as it usually works as is. Besides, I run SpamAssassin via mysql-setups and rules, which is a very personal setup. Normally, you won't need think of it here. The important thing with this post is the actual postfix setup.
Clients that does not support SMTP authentication via imap or pop
This text is written in october 2020 after ripping my hair of my head off for a while. What I did not think of, during the first round of installation, was that there will be non standard clients that won't do a pop/smtp-auth before entering the SMTP out. For example, Postfix, straight out of the box - where you want to relay from postfix to postfix via an authenticated user. With the solution above, there might happen things that you do not want. The error message below for example, is quite common but very much unanswered in different kinds of forums. Most of the posts are relating their problems to dovecot, cyrus and different kind of solutions that in the end seem to be database driven. This is not bad, it's just a little bit stupid since you suddenly rely your systems on yet another point of failure: The database. And the more crap you implement, the harder it will be to find the failing point.
No Format |
---|
warning: SASL authentication failure: unable to canonify user and get auxprops |
However, the solution may be much simpler than you think in this case. It was first, when I stumbled over theURLs below URLs, I realized that some settings are just misconfigured with the sasl authentication daemon.
As the first step after finding the entire solution, I tried to change the auth mechanism to a shadow based solution as I don't like extra databases to just make authentication work. This however failed, and since the server itself is in a production state I have to stick with the db solution for a while (because I actually don't know if this have effect on other working systems currently in operation).
The solution?
Well, since at least one of the sites are mentioning chrooted files, saslauthd won't read the "real" /etc/sasldb2, since it's not really in /etc - the real file resides in /var/spool/postfix/etc, and requires only one thing: That you create it and put it there and making the sasl user the group owner of the file. This is how it should look.
No Format |
---|
# ls -l /var/spool/postfix/etc/sasldb2
-rw-r----- 1 root sasl 12288 Oct 4 12:00 sasldb2 |
The only backside of this is that you may have another load of users in another location /etc/passwd, that still won't be able to authenticate as long as they are not added to sasldb2.
The documented problem URLs
...
authentication failure: unable to canonify user and get auxprops |
However, the solution may be much simpler than you think in this case. It was first, when I stumbled over theURLs below URLs, I realized that some settings are just misconfigured with the sasl authentication daemon.
As the first step after finding the entire solution, I tried to change the auth mechanism to a shadow based solution as I don't like extra databases to just make authentication work. This however failed, and since the server itself is in a production state I have to stick with the db solution for a while (because I actually don't know if this have effect on other working systems currently in operation).
The solution?
Well, since at least one of the sites are mentioning chrooted files, saslauthd won't read the "real" /etc/sasldb2, since it's not really in /etc - the real file resides in /var/spool/postfix/etc, and requires only one thing - that you create it and put it there and making the sasl user the group owner of the -file. This is how it should look.
No Format |
---|
# ls -l /var/spool/postfix/etc/sasldb2
-rw-r----- 1 root sasl 12288 Oct 4 12:00 sasldb2 |
This file contains the users that can authenticate without the pre-auth system.
The only backside of this is that you may have another load of users in another location /etc/passwd, that still won't be able to authenticate as long as they are not added to sasldb2.
Example of how to create it "properly" first time:
Code Block | ||||
---|---|---|---|---|
| ||||
#> saslpasswd2 -c nisse
Password:
Again (for verification):
#> mv /etc/sasldb2 /var/spool/postfix/etc
#> ln -s /var/spool/postfix/etc/sasldb2 /etc/sasldb2 |
The documented problem URLs
https://serverfault.com/questions/409828/cant-get-sasl-auxprop-sasldb-working-with-postfix-ubuntu-12-04
https://annvix.com/enabling_sasl_in_postfix
Greylisting
Preventing spam can be very exhausting. There is a suggested method on stopping spam by greylisting. You can read a longer description of how to set up greylisting for your system on the link below.
https://www.howtoforge.com/greylisting_postfix_postgrey
Installing
Run: apt install postgrey and service postgrey start
No Format |
---|
apt install postgrey
service postgrey start |
If you have been following the above instructions, your main.cf probably looks like this:
No Format |
---|
smtpd_recipient_restrictions = permit_mx_backup, permit_auth_destination, permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, check_policy_service unix:private/policyd-spf |
Update this row to:
No Format |
---|
smtpd_recipient_restrictions = permit_mx_backup, permit_auth_destination, permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, check_policy_service unix:private/policyd-spf, check_policy_service inet:127.0.0.1:10023 |
Then, reload postfix.
Are we done?
I'm not entirely sure actually. I may have missed something. If someone is actually interested in this post and see that something won't work it may be cause by the fact that I missed that part. I also have a separate configuration (based on this big one) to make sure that relaying actually works out of the box. If you find anything, feel free to contact me and notify me about it...