This howto will use Solaris 8 install with Core System Support component and the latest Postfix release 1.1.0 release.
Solaris uses the old dbm UNIX database for lookup table. dbm is old and can run into problems if the lookup table contains lots of information. Berkeley DB is a modern version and standard on all 4.4BSD and Linux systems. Sleepycat distributes free for non-commercial use here. Please read the license before proceeding.
Download Berkeley DB and unpack it into a directory.
Change to the Berkeley DB unpack directory, build and install it:
$ cd build_unix $ ../dist/configure $ make # make installDownload Postfix and unpack it into a directory.
Change to the Postfix unpack directory and build it with Berkeley DB:
$ make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB.3.3/include" \
AUXLIBS="-L/usr/local/BerkeleyDB.3.3/lib -ldb"
$ make
Once the sources are built and ready to install, a postfix user,
group and a postdrop group need to be pre-created.
Add user/group postfix and group maildrop:
# echo "postfix:x:11:11:Postfix pseudo-user:/:" >> /etc/passwd # echo "postfix:NP:6445::::::" >> /etc/shadow # echo "postfix::11:" >> /etc/group # echo "postdrop::13:" >> /etc/groupYou also need to add postfix alias to root:
# echo "postfix: root" >> /etc/aliasesOn a single user system, use maildrop for submission mechanism. On multi user, use set-gid privileges on a small ``maildrop'' command. We will use set-gid privileges
# make installChoose default settings except for ``setgid'' question where you need to put ``maildrop'' for set-gid privileges.
install_root: [/] tempdir: [/tmp/snapshot-20011008] config_directory: [/etc/postfix] daemon_directory: [/usr/libexec/postfix] command_directory: [/usr/sbin] queue_directory: [/var/spool/postfix] sendmail_path: [/usr/lib/sendmail] newaliases_path: [/usr/bin/newaliases] mailq_path: [/usr/bin/mailq] mail_owner: [postfix] setgid_group: [postdrop] manpages: [/usr/local/man] sample_directory: [/etc/postfix] readme_directory: [no]2. Update /etc/syslog.conf to log mail to /var/log/maillog
# echo "mail.info /var/log/maillog" >> /etc/syslog.conf # touch /var/log/maillog # /etc/init.d/syslog stop # /etc/init.d/syslog start3. Enable Postfix on startup:
# vi /etc/init.d/postfix
#!/sbin/sh
#
LD_LIBRARY_PATH=/usr/local/BerkeleyDB.3.3/lib; export LD_LIBRARY_PATH
case "$1" in
'start')
if [ -x /usr/sbin/postfix ]; then
/usr/sbin/postfix start > /dev/console 2>&1
fi
;;
'stop')
/usr/sbin/postfix stop
;;
*)
echo "Usage: $0 { start | stop }"
exit 1
;;
esac
exit 0
Turn on executable bit:
# chmod 744 /etc/init.d/postfixStart Postfix in init level 2 and make sure it does not run on other levels:
# cp /etc/init.d/postfix /etc/rcS.d/K89postfix # cp /etc/init.d/postfix /etc/rc0.d/K89postfix # cp /etc/init.d/postfix /etc/rc1.d/K89postfix # cp /etc/init.d/postfix /etc/rc2.d/S89postfixPostfix out of the box has pretty much everything configured for a mail system. In order to start Postfix, you only need to change one parameter in the main configuration file /etc/postfix/main.cf.
# vi /etc/postfix/main.cf myhostname = mailgateway.example.comPopulate the mail aliases:
# /usr/bin/newaliasesStart Postfix:
# postfix startThis is the minimum change to get postfix up and running.
Purpose of the mail gateway:
Mail gateway hostname: mailgateway Domain name: example.com Client network: 192.168.1.0/24 example.com backup MX host for: other.com other.com IP address: 10.0.0.1Since Postfix is already started, stop it and start the fun.
# postfix stopPostfix out of the box relay policy:
myhostname = mailgateway.example.comIdentify the mail gateway domain name. This value is used for many other parameters:
mydomain = example.comOutgoing emails will appear as @example.com:
myorigin = $mydomainAccept incoming emails and delivery to local mail boxes for the mailgateway and smtp clients in example.com domain:
mydestination = $myhostname, localhost.$mydomain, $mydomainPostfix default to relay for clients on the same subnet. In the case of public DSL/cable network, it is not desired to relay for those clients. Therefore, explicitly identify the trusted clients IP address range. SMTP clients whose IP address belonging in these ranges will be permitted to relay emails.
mynetworks = 192.168.1.0/24, 127.0.0.0/8Add my friend mail server other.com domain as trusted smtp client and allow it to relay emails through this mail server:
relay_domains = $mydestination, other.comIf an email destine to an unknown user, Postfix will default to accept, queue and bounce later once it found out that user is non-existent. Force Postfix to query for valid user and bounce if non-existent user instead:
local_recipient_maps = $alias_maps, unix:passwd.bynameLog and report everything to postmaster:
notify_classes = bounce, delay, policy, protocol, resource, softwareMasquerade smtp client hostnames behind the mail gateway for outbound emails. e.g. me@host.example.com will appear as me@example.com:
masquerade_domains = $mydomainNote:
At this point, the mail server is not an open relay host and will only relay emails for its trusted network clients and its friend other.com domain. Going further is not necessary for a very basic mail gateway.
If you don't use NIS, disable NIS client code in Postfix local delivery agent:
alias_maps = $alias_databaseOtherwise, you will find similar entries in /var/log/maillog:
NIS domain name not set - NIS lookups disabled
disable_vrfy_command = yesPeople have no business in knowing what email software and its version. Under a US proposed federal law, unsolicited commercial email cannot be sent through a server that includes the string NO UCE in the 220 greeting line. More information from DJB's technical information on SMTP Greeting:
smtpd_banner = $myhostname NO UCE ESMTPDisable notify local users of the arrival of new mail. This feature makes use of the comsat network service, which is turned off on many UNIX systems for performance and/or security reasons.
biff = noPostfix default to 10M per message size. Reduce it to 2M as a prevention for possible mail abuse:
message_size_limit = 2048000
Transcript of session follows. 1 Out: 220 mailgateway.example.com ESMTP 2 In: EHLO imbad.spammer.com 3 Out: 250-mailgateway.example.com 4 Out: 250-PIPELINING 5 Out: 250-SIZE 2048000 6 Out: 250-ETRN 7 Out: 250-XVERP 8 Out: 250 8BITMIME 9 In: MAIL FROM:<jackass@spammer.com> SIZE=1897 10 Out: 250 Ok 11 In: RCPT TO:<niceguy@example.com> 12 Out: 450 <imbad.spammer.com>: Helo command rejected: Host not found 13 In: QUIT 14 Out: 221 Bye No message was collected successfully.Detail description of each parameter in action:
0. $smtpd_client_restrictions
1. $smtpd_banner
2. $smtpd_helo_required = yes; $smtpd_helo_restrictions
3. Our mail server introduces itself 4-8. Our mail server
advertises its settings
9. $smtpd_sender_restrictions
10. Our mail server responses with Ok
11. $smtpd_recipient_restrictions
12. imbad.spammer.com got reject with ``Host not found'' during
$smtpd_helo_restrictions. Otherwise, the smtp client will start
sending its DATA and $header_checks and $body_checks the last 2
remaining restriction to defend us from spammer will apply. If
these 2 stages are passes, the mail will be accepted and
niceguy@example.com will receive the email.
13. Remote mail server disconnects
14. Our mail server disconnects
Why reject an EHLO ``Host not found'' after $smtpd_recipient_restrictions stage? Why not reject at once after $smtpd_helo_restrictions stage where we know the spammer didn't have the reverse PTR record? The answer is the default setting $smtpd_delay_reject = yes. The reason to have this parameter enable is because some windows smtp client will simple ignore and continue until the RCPT TO: stage.
Once smtpd_delay_reject = no, the mail gateway will reject the spammer after $smtp_helo_restrictions as below:
Transcript of session follows. Out: 220 redsand.muine.org ESMTP In: EHLO imbad.spammer.com Out: 450 <imbad.spammer.com>: Helo command rejected: Host not found In: HELO imbad.spammer.com Out: 450 <imbad.spammer.com>: Helo command rejected: Host not found Session aborted, reason: lost connectionHere is the summary of how Postfix apply its UCE restrictions:
<smtpd_client_restrictions> <smtpd_banner> <smtpd_helo_required = yes> <smtpd_helo_restrictions> <smtpd_etrn_restrictions> [smtp server advertises its settings] MAIL FROM: <smtpd_sender_restrictions> RCPT TO: <smtpd_recipient_restrictions> [Got rejected? If yes, skip header and body checks below. Otherwise, apply them.] DATA <header_checks> <body_checks>Now, with UCE knowledge, lets put the restrictions to use.
Reject immediately. Do not delay until RCPT TO: to reject the email:
smtpd_delay_reject = noRequire HELO command at the beginning of smtp session. Requiring this will stop bulk mail programs:
smtpd_helo_required = yesRequire strict RFC 821 envelopes. This will stop unwanted emails:
strict_rfc821_envelopes = yesIdentify our friends DNS blacklist hostnames to query when using $reject_maps_rbl restriction:
maps_rbl_domains =
relays.ordb.org,
inputs.orbz.org
Client Restrictions
Example of using client restrictions:
smtpd_client_restrictions =
check_client_access hash:/etc/postfix/client_access,
reject_unauth_pipelining,
reject_unknown_client,
reject_maps_rbl
client_access should contain the client hostname, parent domains,
client IP address, or networks obtained by stripping least
significant octets.
Sometimes, it is necessary to permit a friend mail server with offending ``unknown client'' to pass through. The solution is to put that IP in the client_access with OK action.
client_access: 10.0.0.1 OK
Then generate the client access lookup table:
# postmap client_accessehlo/helo Restrictions
Example of using ehlo/helo restrictions:
smtpd_helo_restrictions =
check_helo_access regexp:/etc/postfix/helo_access,
reject_invalid_hostname,
reject_unknown_hostname,
reject_non_fqdn_hostname
helo_access should contain the HELO hostname or parent domains in
the specified table.
Sometimes, it is necessary to permit a friend mail server with offending ``unknown hostname'' to pass through. The solution is to put that hostname in the helo_access with OK action.
helo_access: /^smtp\.goodfriend\.com$/ OKThen generate the helo access lookup table:
# postmap helo_accessETRN Restrictions
Example of using etrn restrictions:
smtpd_etrn_restrictions =
check_etrn_access hash:/etc/postfix/etrn_access
etrn_access should contain the the domain specified in the ETRN
command, or its parent domains.
Permit our friend at other.com to issue ETRN:
etrn_access: other.com OK
Then generate the etrn access lookup table:
# postmap etrn_accessSender Restrictions
Example of using sender restrictions:
smtpd_sender_restrictions =
check_sender_access hash:/etc/postfix/sender_access,
reject_unknown_sender_domain,
reject_non_fqdn_sender
sender_access should contain the sender mail address, parent
domain, or localpart@.
Then generate the sender access lookup table:
# postmap sender_accessRecipient Restrictions
Example of using recipient restrictions:
smtpd_recipient_restrictions =
check_recipient_access hash:/etc/postfix/recipient_access,
reject_unknown_recipient_domain,
reject_non_fqdn_recipient,
check_relay_domains
recipient_access should contain the resolved destination address,
parent domain, or localpart@.
Then generate the recipient access lookup table:
# postmap recipient_accessHeader Restrictions
Example of using header checks:
header_checks = regexp:/etc/postfix/header_checks: /^From:(.*)@spammer\.com$/ REJECT /^From:(.*)@babbabbad\.com$/ IGNORE /^From:(.*)@sex\.com$/ REJECT Geeks have no time for this /^From:(.*)@goodfriend\.com$/ OK /^Subject: hot hot hot$/ WARN
Reload Postfix to pickup new header change:
# postfix reloadBody Restrictions
Example of using body checks:
body_checks = pcre:/etc/postfix/body_checks: /^(.*)name\=\"(.*)\.(zip|gz|Z|bz)\"$/ REJECT /^(.*)name\=\"(.*)\.(hta|vb[esx]|ws[fh]|js[e]|bat|cmd)\"$/ IGNORE /^(.*)name\=\"(.*)\.(com|exe)\"$/ REJECT Please no executable /^(.*)name\=\"(.*)\.(doc)\"$/ OK /^hot deal$/ WARN
Reload Postfix to pickup new header change:
# postfix reloadCustom UCE Restriction
Postfix SMTP server allows you to define custom UCE restrictions on the right-hand side of lookup tables. The benefit of it is to allow easy-to-remember names to groups of UCE restrictions.
smtpd_helo_restrictions =
regexp:/etc/postfix/helo_friends,
reject_invalid_hostname,
reject_unknown_hostname,
reject_non_fqdn_hostname
Define a restriction class name friends_only:
smtpd_restriction_classes = friends_only friends_only = check_helo_access regexp:/etc/postfix/friendsUse friends_only UCE restriction on the right hand side of a lookup table:
helo_friends: /^smtp\.goodfriend\.com$/ friends_onlyFinally, create the lookup table friends:
friends: /^smtp\.goodfriend\.com$/ OKDon't forget to reload postfix to pick up new change.
# egrep '(reject|warning|error|fatal|panic):' /var/log/maillogAlternatively, you can use a nicer Postfix log summary like pflogsumm to output useful statistics.
# postconf mail_versionShow Postfix default settings:
# postconf -dShow Postfix non-default settings:
# postconf -nDelete one message with the named queue ID from default queues: incoming, active and deferred
# postsuper -d queue-idDelete all messages from the queues:
# postsuper -d ALLFlush the mail queue:
# postfix flush
SMTP Protocol http://www.muine.org/rfc/rfc821.txt New SMTP Protocol http://www.muine.org/rfc/rfc2821.txt The Postfix Home Page http://www.postfix.org/ SMTP: Simple Mail Transfer Protocol http://cr.yp.to/smtp.html Postfix Configuration - UCE Controls http://www.muine.org/postfix/uce.html postfix-uce-guide http://www.mengwong.com/misc/postfix-uce-guide.txt Requirements for Internet Hosts -- Application and Support http://www.muine.org/rfc/rfc1123.txt