Postfix Hardening Guide for Security and Privacy
Postfix is a common software component on servers for receiving or sending email. It has a lot of configuration options available, including those to improve your Postfix security. This Postfix security and privacy guide will help with hardening your Postfix configuration.
After you are finished, your system will have improved defenses against spam, abuse, and leaking sensitive data.
Why Postfix hardening?
Every service that is connected to the internet is sooner or later to be abused by automated scripts. For example, an incorrectly Postfix might send messages to everyone, instead of just your network systems. This type of configuration is called an open relay. It will get your system ending up on multiple blacklists. If it is just a test system, then you are lucky. If your customers are depending on it, then you have something to explain.
Another reason for Postfix hardening is the increasing need for privacy. Most of the legacy protocols, SMTP included, did not have security or privacy high on the priority list. These protocols may share data with other systems without any form of protection. This may result in unauthorized people snooping on data, from your local IT administrator to possibly the CIA or NSA.
Preparation
Time to get technical and get the configuration tested. Many hardening guides and blogs forget an important part of system hardening: the preparation. So let’s start with that, before making any changes.
Test the existing Postfix configuration
Your current configuration may have errors without you even knowing. So let’s first test for that using the postconf command.
postconf 1> /dev/null
The postconf command can be used to display the Postfix configuration, or make changes. In this case, we redirect all normal output (stdout) to the digital trash bin (/dev/null). If your configuration has any errors or warnings, they will show up. Guess what, one of our systems had actually a warning. This was discovered when we implemented a related test in our own auditing tool Lynis.
If you get any output, then it is wise to solve these first and restart your Postfix service to see if the error or warning is gone.
Backup your Postfix configuration
It goes without saying, but too often this step is skipped. If you do system hardening, make a backup first. The first backup is to create a copy of the /etc/postfix directory.
tar czf /root/postfix-$(date "+%F").tar.gz /etc/postfix
For later troubleshooting or comparing configurations, it is also wise to use postconf to store a copy. This one we can easily use together with the diff command.
postconf > /root/postconf-$(date "+%F")
Find your Postfix version
postconf mail_version | awk -F" = " '{print $2}'
An alternative is to use your package manager to find the version of the ‘postfix’ package. For Debian and Ubuntu users, this can be achieved with the dpkg command.
dpkg -l postfix
Postfix hardening steps
With all the preparations taken, it is time to start with the Postfix hardening steps. Each of the steps will change a particular area within Postfix. Some are to prevent information disclosure, others to enhance stability or increase the privacy of the content being sent.
Basic hardening
Disable VRFY (verify)
The VRFY command is short for ‘verify’. It can be used to see if an email address is valid on the mail server. While this is great for troubleshooting, it also allows others to make educated guesses if an account exists and deliver possibly spam. The VRFY command is not normally not needed for delivery between two mail servers
postconf -e disable_vrfy_command=yes
Note: after changing each item, restart or reload Postfix and monitor Postfix for errors. One way to do this is by keeping a watch on the log file.
Network interfaces (inet_interfaces)
The first setting to check is the interfaces Postfix is listening to. This setting is called inet_interfaces and by default configured with all. If you just want to relay messages to other systems, like sending outgoing emails, then there is no needed to listen on all network interfaces. Configure Postfix to listen only on the local interface. This can be achieved by setting inet_interface to loopback-only.
postconf -e inet_interfaces=loopback-only
Test your configuration after restarting Postfix. In this case, we can use the output from netstat or ss.
Important notes:
- Some changes need a restart of Postfix
- A reload is not enough when changing the inet_interfaces setting.
- If you are configuring a system that relays for other systems, then most likely you want to listen on all network interfaces, or just on localhost and the primary network interface where requests come from.
Prevent unwanted email relaying
The first rule when putting a mail server up is to avoid being an open relay system. An open relay is a system that accepts email from all systems and forwards them. Spammers use these open relays to send out their messages.
Networks
Relaying is configured with several parameters. The first one is the mynetworks setting, which typically only includes the network addresses of the local network interface (lo).
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
If you want to extend this list, simply add network segments or individual systems. Specify the related network mask, which is /32 for a single IPv4 address, or /128 for IPv6.
Due to the spaces in this setting, add quotes when using the postconf command.
postconf -e mynetworks="127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
Domains
The second layer to define what emails to accept. This is called relaying and one of the options is by looking at the destination domain. The related setting for this is relay_domains, which specifies for which domains to accept email in the first place.
Test Postfix relaying
You can test if your configuration is correctly set up by setting up a connection to the other system. Telnet to the other system, and run the following commands
- helo yourdomain.com
- mail from:<your.alias@yourdomain.com>
- rcpt to:<your.personal.mailbox@gmail-or-hostmail.com>
- data
- Type a test line and press CTRL+D twice
- quit
Replace the addresses and see if you can relay a message to an address outside your own domain. For example, you could use a Gmail or Hotmail address as the receiver.
If things are properly configured to avoid an open relay, you should be getting a relay access denied message.
Relay access denied (in reply to RCPT TO command)
Incoming email configuration
Configuration items starting with smtpd refer to the SMTP daemon. This is the daemon that deals with incoming requests.
Enable HELO
People usually greet each other by saying ‘hello’ or something similar. Mail servers do this with a HELO command, or EHLO, the extended version. Servers that are not using this are typically not properly configured, or simply sending spam.
postconf -e smtpd_helo_required=yes
Outgoing email configuration
Typically only a few machines will accept incoming email and all other servers need to send out emails. This might be a system notification from the daily cronjobs. Another typical example is a web application that needs to send emails for account activation or password resets.
Configure authenticated relaying with a smarthost
The first step is to define which system will accept the email. This system is the so-called smarthost, or relayhost in Postfix terms. Use the postconf command to set these settings from the command line, or edit main.cf directly.
relayhost = [hostname.example.org]:587
Use the brackets around the hostname or IP address, to prevent MX lookups. The port number can be changed, depending on the required configuration. Some providers use an alternative SMTP port.
Next step is to enable SASL authentication.
# Enable SASL authentication
smtp_sasl_auth_enable = yes
# Disallow any methods that do allow anonymous authentication
smtp_sasl_security_options = noanonymous
# Define the sasl_passwd file location
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
Now we will edit the /etc/postfix/sasl/sasl_passwd file.
[mail.example.org]:587 username:password
This file can be parsed by postmap to created an optimized version, which is used as the database for lookups.
postmap /etc/postfix/sasl/sasl_passwd
The last part is configuring encryption. To enable this, we have to configure this separately.
# Enable STARTTLS encryption
smtp_use_tls = yes
# Location of CA certificates
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
Now restart Postfix, and send a test email.
echo "test" | mail -s "test" me@example.org
Related and useful commands
Flush mail queue and retry delivering all emails with the postqueue command:
postqueue -f
Cryptography, encryption, and privacy
Enable TLS logging
To see the details from TLS, increase the level of Postfix logging. Set smtp_tls_loglevel (outgoing) or smtpd_tls_loglevel (incoming) to the value one (1).
postconf -e smtp_tls_loglevel=1
Testing keys
You can easily test your SMTP configuration and related ciphers with OpenSSL. One of the areas to test is the strength of the initial connection handshake. This is typically done with the Diffie Hellman (DH) algorithm, that exchanges the cryptographic keys.
echo | openssl s_client -starttls smtp -connect localhost:25 -cipher "EDH" 2>/dev/null | grep -i -e "Server .* key"
Note: you need at least version 1.02 of OpenSSL, otherwise not all details are displayed. Use openssl version to double check that you are on a recent version.
This command should give you two lines of output. The first line is the temporary key and should be at least 1024 bits when using DH, to prevent the Logjam attack .
Server Temp Key: DH, 2048 bits
The second line is the public key size. This will typically be a 2048 bit key (or higher) on modern systems.
Server public key is 2048 bit
Did you find this guide useful? Share it, link to it! If you have any questions, let it know!