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'
