/Main_Page

::You must have ninja focus to complete your mission::NinjaFocus::

Email Server/Postfix

Views:

Part of the Email Server documentation

Contents

Introduction

This page describes installing and configuring postfix as virtual domain, virtual user email server, with all account information stored in a database.

This includes configuring postfix to work a with Amavisd-new, an email content filter, and Postgrey, a postfix policy daemon.

Dependancies

There are a lot of (inter-)dependancies for setting up postfix.

You need to prepare the database

Maildrop is needed as the postfix delivery agent

saslauthd and pam_mysql are required for authentication.

Postgrey and Amavisd-new can be used for spam and virus protection.

Installation

We don't need anything too special for postfix, only that it has MySQL support. Are there any server distros that don't package up postfix? Who knows but if it doesn't include MySQL support then you'll need to install from source.

Note: Maildrop will handle quotas, so there is no need to compile postfix with the VDA patch, really. Postfix doesn't need to touch the user's maildir, Maildrop will use Courier Authlib to to discover the quota when it is delivering the mail.

On CentOS 5 you can get Postfix with Mysql support from the "centosplus" repository.

Remove any existing copy of postfix

# yum remove postfix

then enable "centosplus" in /etc/yum.repos.d/CentOS-Base.repo by setting the "enabled" setting to 1.

To make sure we don't get lots of random packages showing up from centosplus, and to make sure that postfix from base and postfix from centosplus don't interfere, we need to add some rules to the config file.

For the "base", "updates" and "updates-released" repositories, set

exclude=postfix-*

For the "centosplus" repository, set

includepkgs=postfix-*

Once yum is prepared:

# yum install postfix

Configuration

main.cf

main.cf is the main place to configure how postfix will operate

/etc/postfix/main.cf

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mail_owner = postfix
myhostname = hostname.example.com

mydomain = example.com
myorigin = example.com
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost
local_recipient_maps = unix:passwd.byname $alias_maps
unknown_local_recipient_reject_code = 550
mynetworks_style = host
mynetworks = 127.0.0.1/32
relay_domains = $mydestination
append_at_myorigin = no
append_dot_mydomain = no
in_flow_delay = 1s
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mail_spool_directory = /var/mail

#####################################################################

#####################################################################
#
# VIRTUAL DOMAINS
#
#####################################################################
maildrop_recipient_limit=1
virtual_mailbox_domains=proxy:mysql:/etc/postfix/virtual_mailbox_domains
virtual_mailbox_maps=proxy:mysql:/etc/postfix/virtual_mailbox_maps
virtual_alias_maps=proxy:mysql:/etc/postfix/virtual_alias_maps
virtual_alias_domains=
virtual_mailbox_base=/var/mail/virtualdomains
virtual_transport=maildrop

#####################################################################
#
# AUTHENTICATION
#
#####################################################################
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
smtpd_sasl_authenticated_header = yes

smtpd_pw_server_security_options = noanonymous

smtpd_tls_cert_file = /etc/postfix/server-cert.pem
smtpd_tls_key_file = /etc/postfix/server-key.pem
smtpd_tls_received_header = yes
smtpd_tls_security_level = may

#####################################################################
#
# JUNK MAIL CONTROLS
#
#####################################################################
disable_vrfy_command = yes
# The smtpd_helo_required paramter is used to block poorly written software
# that doesn't bother to helo <hostname> when we send a 220. Basically, a
# genuine email sever will say helo to us, but a lot of spam tools don't 
# bother (KJW)
smtpd_helo_required = yes
smtpd_banner = $myhostname ESMTP - NO UCE
smtpd_helo_restrictions = 
    permit_mynetworks,
    check_helo_access hash:/etc/postfix/helo_restrictions,
    permit
# Non-compliant envelopes are used by lots of otherwise very good servers. Thanks sendmail.
strict_rfc821_envelopes = no

##############
# CAUTION!!! #
##############
# DO NOT EDIT "smtpd_data_restrictions" unless you know exactly what you are doing, 
# you know the devil doesn't own your soul and that your karma levels are good.
#
##############
# CAUTION!!! #
##############
# DO NOT EDIT "check_client_access" unless you know exactly what you are doing, 
# you know the devil doesn't own your soul and that your karma levels are good.
#
# This regexp sets content_filter = smtp-amavis:[127.0.0.1]:10024
# The content_filter parameter is used to specify an external tool for
# filtering mail. 
# Hopefully some of the smtpd*restrictions below will have blocked obvious spam, 
# but now it's time to let the master get to work ;-) (KJW)
# reject_anauth_pipelining - Don't allow clients to start pipelining before 
# they've asked if its ok - Surely a sign of dodgy spam software!?
# (KJW)
smtpd_data_restrictions = 
    reject_unauth_pipelining,
    permit_sasl_authenticated,
    check_client_access regexp:/etc/postfix/filter-catchall.regexp

# smtpd_recipient_restriction Allows us to be very picky about what we let in to the
# system in the first place and helps to block some very obvious spam and errors 
# permit_mynetworks - trust everything from our public servers
# reject_invalid_hostname - any hostnames must be written correctly - blocks too many friendly but poorly configured servers
# reject_non_fqdn_hostname - hostnames must be fully qulified ie varndean.ac.uk - blocks too many friendly but poorly configured servers
# reject_non_fqdn_sender - sender must provide a proper domain name ie @example.com
# reject_non_fqdn_recipient - recipient must have a proper domain name
# reject_unknown_sender_domain - if we can't find your domain in dns then we ain't interested!
# reject_unknown_recipient_domain - recipient domain must be available in dns
# reject_unauth_destination - local mail and relay recipients only!
# check_unath_destination - check email addrs to block anything silly, really just to help crappy open relay testers, postfix isn't stoopid
# check_sender_access - see comments in access file
# reject_rbl_client - realtime block lists, not certain about using these here - they block some false positives. Spamassassin accounts for FPs
# check_policy_service - pass off to something like postgrey
# permit - incase anything manages to pass through all the above rules
# (KJW)
smtpd_recipient_restrictions = 
    reject_non_fqdn_sender,
    reject_non_fqdn_recipient,
    reject_unknown_sender_domain,
    reject_unknown_recipient_domain,
    check_sender_access hash:/etc/postfix/access,
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    check_recipient_access pcre:/etc/postfix/recipient.pcre,
    reject_rbl_client zen.spamhaus.org,
    reject_rhsbl_sender bogusmx.rfc-ignorant.org,
    reject_rhsbl_sender nomail.rhsbl.sorbs.net,
    check_policy_service inet:127.0.0.1:60000,
    permit

###############
# CAUTION!!!! #
###############
# DO NOT EDIT "content_filter" unless you know exactly what you are doing, you know the devil
# doesn't own your soul and that your karma levels are good.
#
# The content_filter parameter is used to specify an external tool for
# filtering mail. There must be a matching entry in master.cf 
# Hopefully some of the smtpd*restrictions above will have blocked obvious spam, 
# but now it's time to let the master get to work ;-) (KJW)
# smtp-amavis:[127.0.0.1]:10026 - this is for sasl authenticated users, who bypass amavis checks
# we are using it for antivirus scanning. Non-authenticated users should be sent to 
# smtp-amavis[127.0.0.1]:10024 for full filtering via the check_client_access rule in the the 
# smtpd_data_restristrictions setting (above)
content_filter = smtp-amavis:[127.0.0.1]:10026
# smtp-amavis:[127.0.0.1]:10024 - is for incoming mail from non-sasl autenticated smtp sessions
#content_filter = smtp-amavis:[127.0.0.1]:10024
#####################################################################
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix*
setgid_group = courier
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.3.3/samples
readme_directory = /usr/share/doc/postfix-2.3.3/README_FILES
masquerade_exceptions = root
masquerade_classes = envelope_sender, header_sender, header_recipient
smtpd_soft_error_limit = 3
smtpd_error_sleep_time = 4s

# 20MB limit on message size.
message_size_limit = 20480000

proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $smtpd_sender_login_maps

master.cf

master.cf defines protocols used by different postfix components for different purposes.

It's in here that we define the return path for email which has been filtered in Amavisd-new, alternative ports for email submission, mail delivery through Courier Maildrop

/etc/postfix/master.cf

smtp       inet  n       -       n       -       -       smtpd
smtpalt    inet  n       -       n       -       -       smtpd
            -o smtpd_data_restrictions=permit_sasl_authenticated,reject
submission inet  n       -       n       -       -       smtpd
            -o smtpd_data_restrictions=permit_sasl_authenticated,reject
smtps     inet  n       -       n       -       -       smtpd
            -o smtpd_tls_wrappermode=yes
            -o smtpd_sasl_auth_enable=yes
            -o smtpd_client_restrictions=permit_sasl_authenticated,reject
pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
smtp      unix  -       -       n       -       -       smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay     unix  -       -       n       -       -       smtp
	-o fallback_relay=
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache	  unix	-	-	n	-	1	scache
maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=courier:courier argv=/usr/local/bin/maildrop_primer -a -w 90 -d ${recipient} ${user} ${nexthop} ${sender} ${recipient}
smtp-amavis unix -	-	n	-	4  smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
127.0.0.1:10025 inet n	-	n	-	-  smtpd
    -o content_filter=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o mynetworks=127.0.0.1/32
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o smtpd_milters=
    -o local_header_rewrite_clients=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

filter_catchall.regexp

/etc/postfix/filter_catchall.regexp

/^/ FILTER smtp-amavis:[127.0.0.1]:10024

helo_restrictions

You'll want to list all the names that your server goes by in this file.

/etc/postfix/helo_restrictions

127.0.0.1 554 Service unavailable. You are not 127.0.0.1 to me, I am
localhost 554 Service unavailable. You are not localhost to me, I am
localhost.localdomain 554 Service unavailable. You are not localhost.localdomain to me, I am
hostname.example.com 554 Service unavilable. You are not hostname.example.com
aliasname.example.com 554 Service unavilable. You are not aliasname.example.com

precipient.pcre

/etc/postfix/recipient.pcre

/^\@/              550 Invalid address format.
/[!%\@].*\@/       550 This server disallows weird address syntax.
/^postmaster\@/    OK
/^abuse\@/         OK

virtual_alias_maps

You just need a mysql user with read access to the alias_maps view in the database

/etc/postfix/virtual_alias_maps

user = <DATABASE USER>
password = <PASSWORD>
hosts = localhost
dbname = <DATABASE>
#query = SELECT  alias, username FROM alias_maps
table = alias_maps
select_field = username
where_field = alias

virtual_mailbox_domains

You just need a mysql user with read access to the active_domains view in the database

/etc/postfix/virtual_mailbox_domains

user = <DATABASE USER>
password = <PASSWORD>
hosts = localhost
dbname = <DATABASE>
query = SELECT 1 FROM active_domains WHERE domain = '%s'

virtual_mailbox_maps

You just need a mysql user with read access to the active_domains view in the database

/etc/postfix/virtual_mailbox_maps

user = <DATABASE USER>
password = <PASSWORD>
hosts = localhost
dbname = <DATABASE>

query = SELECT CONCAT(home, '/Maildir/') FROM account_auth WHERE username = '%s'

Main Menu

Personal tools

Toolbox