Complete Virtual Mail Server/Postfix additions

From Gentoo Wiki
Jump to:navigation Jump to:search
This page contains changes which are not marked for translation.
Other languages:
Note
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.

Submission

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.

Configuration

The submission port is enabled in Postfix's master.cf. It is commented by default including its options:

FILE /etc/postfix/master.cfMail submission by postfix
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:

root #/etc/init.d/postfix restart
Note
Additional options can be set and overridden if so desired.

Testing

Testing should be done by a mail client, and using port 587 for the smtp server port.

Redundancy

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.

Configuring backup-mx

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:

FILE /etc/postfix/pgsql/relay_domains.cfSetup relay domains
# 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:

FILE /etc/postfix/main.cfModify postfix for relay domains
# 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_domains:

FILE /etc/postfix/pgsql/relay_recipient_maps.cfSetup relay recipients
# 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:

FILE /etc/postfix/main.cfModify postfix for relay recipients
# 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.

Warning
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

Introduction

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.

Configuration

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:

FILE /etc/postfix/pgsql/virtual_mailbox_limit_maps.cfQuery the database for quotas
# 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.

FILE /etc/postfix/main.cfSetup postfix to use quotas
# 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
Warning
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.

FILE /etc/postfix/main.cfChange allowed message size limit
# Disable postfix mailbox size check
mailbox_size_limit = 0

Testing

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 testuser@example.com would create this file in the users maildir.

user $sendmail testuser@example.com
Subject: Testmail to create quota file.
No content!
.
Note
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.

HELO Restrictions

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.

smtpd_helo_restrictions Description
reject_invalid_hostname REJECT if HELO greeting is not a DN or an IP
reject_non_fqdn_hostname REJECT if HELO greeting is not a FQDN or an IP
reject_unknown_hostname REJECT if HELO host has no A or MX in DNS
permit_naked_ip_address 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.

bogus example example.com 192.0.23.58
reject_invalid_hostname X O O O
reject_non_fqdn_hostname X X O O
reject_unknown_hostname X X ? X
Note
Notice that reject_unknown_hostname not only rejects fake FQDNs, but it also rejects IP addresses. By prepending the restriction list with permit_nakid_ip_address it will allow just IP addresses.

On a properly configured network the following will be tight and should work:

FILE /etc/postfix/main.cfHELO Restrictions
# HELO Restrictions
smtpd_helo_restrictions = permit_sasl_authenticated, reject_invalid_hostname, reject_unknown_hostname, reject_non_fqdn_hostname
smtpd_helo_required = yes
Warning
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 mynetworks bringing the restriction to smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, reject_unknown_hostname, reject_non_fqdn_hostname and then either extending mynetworks with 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:

FILE /etc/postfix/main.cfDisable verify
# 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.

SMTPD Banner

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:

FILE /etc/postfix/main.cfChange the SMTPD Banner
# SHOW SOFTWARE VERSION OR NOT
smtpd_banner = $myhostname ESMTP NO UCE
Note
NO UCE is technically a comment, ESMTP needs to be the before any comments.

Message size

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:

FILE /etc/postfix/main.cfChange allowed message size limit
# Increase maximum message size
message_size_limit = 20971520

Postfix Performance

Biff

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:

FILE /etc/postfix/main.cfDisable biff
# Disable biff notifications
biff = no

Processes

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:

FILE /etc/postfix/main.cfIncrease postfix processes
# Increase number of allowed processes
default_process_limit = 75
Warning
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.

DNS Lookup

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.

Mail Storage

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.