Using Postfix for Secure SMTP Gateways

Improve your site's e-mail hygiene and make life difficult for spammers and hackers.
Keeping out Unsolicited Commercial E-mail

Junk mail is one of the most common and annoying types of e-mail abuse. Postfix offers protection against UCE (Unsolicited Commercial E-mail) via a couple of settings in Some caution is in order, however: there's a fine line between spam and legitimate dissemination, and it's entirely possible that even modest UCE controls will cause some legitimate (i.e., desired) mail to be dropped.

Having said that, for most sites this is an acceptable risk (avoidable, too, through end-user education), and we recommend that at a minimum, you set the following in

  • smtpd_recipient_limit. This setting indicates how many recipients may be addressed in the header of a single message. Normally, such a number should not exceed something like 500. It would be extreme to receive an e-mail that has 500 recipients and was not being sent to a mailing list.

  • smtpd_recipient_restricitons. Not every e-mail that arrives at your server should be accepted. This parameter instructs postfix to check each message's recipient-address base on one or more criteria. One of the easiest to maintain is the access database. This file lists domains, hosts, networks and users who are allowed to receive mail from your server. To enable it: (1) set check_recipient_access = hash:access; (2) create /etc/postfix/access (do a man 5 access for format/syntax); and (3) run postmap hash:/etc/postfix/access to convert the file into a database. Repeat step (3) each time you edit /etc/postfix/access.

  • smtpd_sender_restrictions. By default postfix will accept SMTP connections from everybody, potentially exposing your server to SMTP relaying, a method often used for UCE perpetrators who wish to hide their identities by “bouncing” their messages off unsuspecting SMTP relayers. If this occurs, it's possible and even likely that other servers will reject e-mail from your domain(s). Other protection mechanisms lie in the fact that it is always wise to check the sender against DNS. Although this costs some performance, it makes it harder to send the information from a faulty sender e-mail address. See the file /etc/postfix/ for a list of possible list options for this parameter. Note that hash:access is one of them; the access database can be used not only to allow/disallow particular recipients, but senders as well. For a complete list of anti-UCE parameters and their exact syntax see /etc/postfix/

Hiding Internal E-mail Addresses by Masquerading

In order to prevent giving out information that serves no purpose to legitimate external parties, it is wise to set in the file the parameter masquerade_domains = $mydomain (remember, “$mydomain” refers to a variable). If you wish to make an exception for mail sent by “root” (probably a good idea), you can set the parameter masquerade_exceptions = root. This will cause internal host names to be stripped from FQDSes in “From” addresses of outbound messages.

Running Postfix in a chroot Jail

Now we come to one of the groovier things we can do to secure postfix: running it in a “chroot jail”. chroot is a UNIX command that confines the “chrooted” process to a specified directory; that directory becomes “/” for that process. This usually requires you to first create copies of things needed by the process but normally kept elsewhere. For example, if the process looks for “/etc/mydaemon.conf” upon startup but is being chrooted to “/var/mydaemon”, the process will actually look for “/var/mydaemon/etc/mydaemon.conf”.

The advantage to chrooting should be obvious: should a chrooted-postfix process become hijacked somehow, the attacker will find himself in a “padded cell” from which (hopefully) no sensitive or important system files or data can be accessed. This isn't a panacea, but it significantly. increases the difficulty of exploiting postfix.

Happily, the preparations required to chroot postfix are provided in a subdirectory of the postfix documentation called “examples”. These files aren't really shell scripts: they're suggested sequences of commands.

Better still, some binary distributions of postfix have installation scripts that automatically make these preparations for you after installing postfix. In SuSE, for example, the postfix RPM package runs a script that creates a complete directory tree for postfix to use when chrooted (etc, usr, lib, and so forth) in /var/spool/postfix, with the appropriate ownerships and permissions.

In addition to “provisioning” postfix's chroot jail, you need to edit /etc/postfix/ to toggle the postfix dæmons you wish to run chrooted (i.e., put a “y” in the “chroot” column of each dæmon to be chrooted). Do not, however, do this for dæmons whose “command” column indicates that they are of type “pipe” or “local”. Some binary-package distributions toggle the appropriate dæmons to chroot automatically during postfix installation (again, SuSE does).

After configuring the chroot jail and editing, all you need to do is start postfix the way you normally would: postfix start. Postfix's master process handles the actual chroot-ing.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

how to local smtp

Anonymous's picture

Hello and thank you for the guide.

I changed inet_interfaces = localhost but it didnt worked.
I can receive but i can not send eimail
I quote the cf in order to have a look.

# See /usr/share/postfix/ for a commented, more complete version

# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $myhostname, localhost.$mydomain, $mydomain
relayhost =
mynetworks = [::ffff:]/104 [::1]/128,

mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = localhost
default_transport = error
relay_transport = error
inet_protocols = ipv4

Did i missed something?

Sending from localhost only

Robsteranium's picture

Apparently setting the following in will ensure that only localhost can send emails:

inet_interfaces = localhost