Complete Virtual Mail Server/Postfix additions
This article is part of the Complete Virtual Mail Server series, and may require previous parts to have been read or followed.
At this point, Postfix should be running well and users through mailclients and webmail should have no problem sending and receiving e-mails securely. Tweaking the postfix installation can give a little more performance, make it a bit more secure and having a bit more redundancy never hurts either.
Introduction to submission
Mail submission is often incorrectly done on port 25 of the Mail Transfer Agent (MTA). Mail should actually be submitted on port 587 to the Mail Submission Agent (MSA). Postfix is both an MTA and MSA. There are numerous advantages to having mail delivered to the MSA by the client as can be seen on Wikipedia. The most important however, is that nomadic users can send e-mail even when port 25 is being blocked by a firewall, as port 587 tends to be more open. Also when only letting authenticated users send e-mail, they could even bypass the spam filter for their outgoing messages.
The submission port is enabled in Postfix's master.cf. It is commented by default including its options:
submission inet n - n - - smtpd -o smtpd_tls_security_level=may -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject
After restarting Postfix, this lets the client know that there is STARTTLS availability, but it is not required (set this to
smtpd_tls_security_level=encrypt to enforce encryption) and rejects all mail, except for authenticated users:
Additional options can be set and overridden if so desired.
Testing should be done by a mail client, and using port 587 for the smtp server port.
Introduction to backup-mx
For redundancy, postfix offers the feature of backup mx. Backup mx allows another mailhost to catch e-mail for a domain when the main mailserver is for whatever reason not responding. A backup mx server will try to deliver the mail to the original mailserver. This all sounds just perfect, however backup mx is dead. Spam killed it. The problem with backup mx nowadays is, due to spam, mail can end up bouncing the wrong way and the backup mx server may thus end up on a spam block list. This kind of mail is called Backscatter mail. If a secondary mailserver is setup, it needs to know all of the users from the primary domain so that it can bounce unknown users. A simple way to do this, is having the entire database synchronized between primary and secondary mailserver. Caveat being however the
backupmx flag in the domain table. This would need to be inverted on the secondary mailserver.
The database already knows about backup domains. If a domain has a backup mail server, the
backupmx field is set to "1" in the domain table. Connecting postfix to the database requires a file with connection information:
# relay_domains.cf user = postfix password = $password dbname = postfix #hosts = localhost query = SELECT description FROM domain WHERE domain='%s' AND backupmx='1' AND active='1';
This then needs to be configured into postfix:
# The relay_domains parameter restricts what destinations this system will # relay mail to. See the smtpd_recipient_restrictions description in # postconf(5) for detailed information. relay_domains = pgsql:/etc/postfix/pgsql/relay_domains.cf
To make proper use of
# relay_recipient_maps.cf user = postfix password = $password dbname = postfix #hosts = localhost query = SELECT goto FROM alias WHERE address='%s' AND active='1';
Also this needs to be configured into postfix:
# REJECTING UNKNOWN RELAY USERS # # The relay_recipient_maps parameter specifies optional lookup tables # with all addresses in the domains that match $relay_domains. relay_recipient_maps = pgsql:/etc/postfix/pgsql/relay_recipient_maps.cf
After restarting postfix, the mail server is now a less-open relay, relaying mail to only approved domains and approved users.
Do not use
permit_mx_backup. It is dead. Letting others relay the 'backup domains' through the mail server, to the list of known users, is the proper way of doing it, but only if they are administered by the same user(s). Use even more caution when accepting entire domains, unless the other domain has a catch-all mailbox, Backscatter mail will be a problem and the mail server will most likely be blacklisted.
Quotas are a tool to help a user monitor their mailbox. They are very easily abused and should not be relied on. That said, they can work well enough most of the time and give the user feedback on the status of his usage pattern. IMAP supports quota reporting and thus the mail-client can even report this the user. Thunderbird does this via an extension, roundcube shows this per default.
The database supports mail quotas however postfix requires a patch to support these mail quotas. The
vda USE flag enables this patch for postfix and allows the use of quotas.
First, the data needs to be obtained from the database:
# virtual_alias_maps.cf user = postfix password = $password dbname = postfix #hosts = localhost query = SELECT quota FROM mailbox WHERE local_part='%u' AND domain='%d' AND active='1';
There are a few things that need to be configured in postfix, next to the database query. The Trash folder for example should not be counted when automatically deleting Trash after a fixed amount of time. This can (and has to) be done in courier-imap.
# Support for Postfix VDA quotas virtual_mailbox_limit_maps = pgsql:/etc/postfix/pgsql/virtual_mailbox_limit_maps.cf virtual_mailbox_limit_inbox = no virtual_mailbox_limit_override = yes virtual_maildir_extended = yes virtual_overquota_bounce = no # virtual_maildir_limit_message_maps = hash:/etc/postifx/limit_messages virtual_maildir_limit_message = "Sorry, the recipients mailbox is currently full. Please try again later." virtual_trash_count = no virtual_trash_name = ".Trash" virtual_maildir_filter = no
According to the postgresql manual, the maximum value of a bigint (the quota) would be 9223372036854775807. However only 9223372036854774784 can be successfully used. If for some reason however 8 Exabytes is required as the quota, it is probably wiser to just turn it off by setting the quota to 0 bytes.
With VDA quota's in place, it's recommended to disable the postfix internal mailbox size limit.
# Disable postfix mailbox size check mailbox_size_limit = 0
Roundcube displays diskusage per default and hovering over it displays detailed information. Thunderbird has an extension, Display quota. For both and others to actually work a maildirsize file is required. This file will be created and updated whenever postfix delivers a message or when courier-imap makes changes. The file is located in each virtual users root mail dir, which would be /var/vmail/example.com/testuser/maildirsize in the case of testuser on example.com. Thus sending a message to firstname.lastname@example.org would create this file in the users maildir.
Subject: Testmail to create quota file. No content! .
Generally, there is no need to manually broadcast an e-mail message to generate the maildirsize file, plenty of mail should be delivered and thus create the file, including the Welcome mail postfixadmin creates. Nevertheless, postfixadmin does have the ability to broadcast a message, that can be used for this purpose.
Hackers, spammers and everybody else can obtain information from the mail server by using the HELO and EHLO commands. Spammers usually put fake information in the HELO greeting and thus restricting and rejecting connections from servers that do not properly identify themselves can only be good. Postfix offers the
smtpd_helo_restrictions variable to tune how to respond to connections. Restrictions here have to be thought over carefully however. Locking down the server too tight may make it so messages are rejected because the other server is just poorly configured. A quick overview of the available options.
||REJECT if HELO greeting is not a DN or an IP|
||REJECT if HELO greeting is not a FQDN or an IP|
||REJECT if HELO host has no A or MX in DNS|
||PERMIT if HELO greeting is an IP|
The following table should give an idea how mail will get rejected from the various restrictions. An X means the message will be rejected, an ? means it depends on the proper DNS record setup for that domain and O means the message will be delivered normally.
reject_unknown_hostnamenot only rejects fake FQDNs, but it also rejects IP addresses. By prepending the restriction list with
permit_nakid_ip_addressit will allow just IP addresses.
On a properly configured network the following will be tight and should work:
# HELO Restrictions smtpd_helo_restrictions = permit_sasl_authenticated, reject_invalid_hostname, reject_unknown_hostname, reject_non_fqdn_hostname smtpd_helo_required = yes
Internal servers or internal mail clients may have trouble sending messages as they do not have a valid hostname setup and so local hostnames need to be configured properly in the internal DNS servers and thus become valid hostnames. If internal servers or clients do not have proper hostnames, a safe restriction list would be
smtpd_helo_restrictions = permit_naked_ip_address, reject_invalid_hostname. If tight control is required and setting up of proper internal hostnames is not possible, another option would be to permit
mynetworksbringing the restriction to
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, reject_unknown_hostname, reject_non_fqdn_hostnameand then either extending
mynetworkswith the internal systems or internal network.
Deny local username farming
Normally postfix, or general MTAs allow to verify whether a mailbox exists or not. This command may have been useful in the early days of mail, but is almost exclusively used by people who maintain bulk mailing lists and search if accounts are still valid. This command can be disabled by postfix:
# Do not respond to the VRFY command disable_vrfy_command = yes
After a restart of postfix, telnet to port 25 will no longer show 250-VRFY.
Another often abused feature is the SMTP header. Also some countries require senders to honor the "NO UCE" greeting message (No Unsolicited Commercial E-mail). Also it is wise not to tell any outsiders what MTA is being used or what version thereof. Postfix allows for changing the SMTP header quite easily. Find the
smtpd_banner section in main.cf:
# SHOW SOFTWARE VERSION OR NOT smtpd_banner = $myhostname ESMTP NO UCE
NO UCE is technically a comment, ESMTP needs to be the before any comments.
For years the default message size amongst MTA's has been 10MiB. Google raised the bar with their gmail service to 20MiB per message. If bandwidth isn't an issue this, can easily be accomplished with postfix:
# Increase maximum message size message_size_limit = 20971520
For compatibility reasons, postfix's local mail notification is enabled by default. With many users this can be a performance drain and since there are no local users to use the biff command anyway this can safely be disabled:
# Disable biff notifications biff = no
The amount of concurrent processes of any of postfix's applications is limited to 50. The first bump in high load environments can be very quickly be the amount of active daemons. Smaller setups should not need to worry about this setting:
# Increase number of allowed processes default_process_limit = 75
Before increasing the amount of processes it needs to be carefully examined if the server can handle the additional load. The ps aux and top commands can be of great help here. The percentage of memory used by each process should be inspected. If for example the memory usage per postfix process nears 2% on a process limit of 50, increasing the limit to 100 would mean that double the memory would be required. After all, 2% * 50 processes would be 100% of the available memory. If the server would also have other processes running consuming memory, the amount of memory used by postfix would have to be less. The same can be said about CPU usage. If CPU utilization is nearing 70% doing mostly mail delivery and postfix is the only service on the server, a faster CPU or clustered setup should be considered. If there are other services running on the server using larger amounts of CPU time, they could be relocated to other, less busy servers.
A common throughput limiter is the use of DNS lookups. These can be slow and can be an issue far before processes, CPU or memory are the issue. One lookup per message is required at the very least per message, a server MX record needs to be found. A local caching DNS server could help enormously here and packages such as net-dns/dnsmasq or even a full net-dns/bind setup should be used.
Postfix maintains a number of queue directories in /var/spool/postfix. Various postfix applications pass messages around each other using these queues. Placing these directories on a separate disk, raid array or an SSD can significantly improve overall throughput. Also making sure that the partition in question is marked with the
noatime option helps a lot on disk access. Postfix does not use access timestamps.
Multiple mail servers
If one server is not enough, multiple mail-servers can spread the load. Also having multiple mail-servers offers redundancy so it is something worth considering. spreading the load over several mail-servers can be done effectively using DNS round-robin. Two options are available here, either assign multiple A entries to the mail-server, or cleaner, have multiple MX entries which allow prioritization.