mail us  |  mail this page

products  |  company  |  support  |  training  |  contact us

Tech Stuff - Postfix Survival Guide

This is a survival guide to Postfix. A popular Open source SMTP Agent that needs a corresponding Mail Agent (a.k.a POP3 or IMAP server) such as Dovecot or Courier-IMAP to provide a complete mail solution. We happen to use Dovecot at this time.

Mostly this survival guide is about FreeBSD[bsd] but we note Linux - Fedora Core[fc] locations, commands and other trivia where available, or relevant, or when we can remember. The postfix configuration principles are the same for all platforms - paths and some port numbers may change. Postfix installation is not covered - if you need this level of advice this guide is not for you.

Updated for Postfix 2.8.x on FreeBSD 8.x. At some point the Postfix install options were enhanced to include the option INST_BASE which changes the default script/application locations from /usr/local/sbin and /usr/local/libexec to /usr/sbin and /usr/libexec respectively, and the configuration files from /usr/local/etc/postfix to /etc/postfix. In all cases below the default paths assume this option has NOT been specified. One assumes the justification for this option is to allow the installation of test versions as non-base (modifying any config files without disturbing the base versions) and trivially reverting to the current base version if anything goes wrong during testing then, when completely happy, to reinstall the test version as the base version (using 'make config FORCE_PKG_REGISTER=yes install clean' or 'portupgrade -f package-name'). Note also, the port in installed as postfix-version or postfix-base-version package names.

Contents

Postfix Virtual Domain Terminology

Postfix can use some confusing, IOHO, terminology. We try and explain some of it here so that the, otherwise excellent, documentation can make perfect sense.

local mail This term refers to local, unix style mail accounts whose name is that of a user account and that typically do not have any associated domain name, for example, 'root' mail account is sent mail output from many host scripts. In unix style, mail is read by logged on users. Local mailboxes, however, are not required since local account names, such as 'root', can be mapped using the alias_maps parameter of main.cf to virtual domain mailboxes.
virtual alias domain Defined by the virtual_alias_domains = parameter of main.cf are source domains where address manipulations (carried out through the virtual_alias_maps definitions) will NOT result in any address for that domain. Or to phrase in the negative form - all address manipulations will result in a mail address for another domain which can be locally hosted or be relayed to some other mail server. For example, assume that the address info@example.com was to be sent to my-name@gmail.com then example.com would be defined as a virtual alias domain and the actual transformation defined in virtual_alias_maps. Virtual_alias_domains do not use the virtual_mailbox_maps parameter.
virtual mailbox domain Defined using the virtual_mailbox_domains = parameter of main.cf are hosted domains that have local mailboxes/Maildirs on this server or in a filesystem visible to this server. These differ from local mail in that they have a domain suffix (for example info@example.com). Typically the mail will be read using a Mail Agent (POP3 or IMAP) server which may also be hosted on this server in smaller configurations. Virtual_mailbox_domains require virtual_mailbox_maps which define where, for a given incoming mail account, the mail will be stored and in what format. Mail addresses for virtual_alias_domains may be transformed by using a virtual_alias_maps parameter into destinations for virtual_mailbox_domains since this transform occurs prior to lookup in the virtual_mailbox_maps.
virtual_alias_maps The term virtual_alias_maps suggests that they are only related to virtual_alias_domains which is not the case. Instead the information in the virtual_alias_map is used to manipulate mail addresses globally and will allow such forms as:
  1. forwarding - account@example.com sent to me@example.net
  2. multiple destinations - sales@example.com -> joe@example.com and bill@example.net
If the result of mail address manipulation (trivial-rewrite) by this file only results in maail for another domain (locally hosted or remote) the domain should be defined as a virtual_alias_domain and if it results in locally stored mail it should be defined as a virtual_mailbox_domain.

GO UP Image

Postfix Relaying

Relaying of mail, sending incoming mail to another location, is an essential process which if incorrectly configured can result in the MTA being OPEN, that is it will send mail from ANY incoming source to another location. Postfix goes to some considerable trouble to make sure that it is as difficult as possible to configure an OPEN relay. In general Postfix relaying is tied to its acceptance of incoming mail (and thus relay domains are defined in smtpd_recipient_restrictions). Mail will be relayed if:

  1. Unauthenticated (untrusted) users from hosts in the mynetworks parameter
  2. Unauthenticated (untrusted) users where the end destination is defined in relay_domains and permit_auth_destination is defined in smtpd_recipient_restrictions.
  3. Unauthenticated (untrusted) users where permit_mx_backup is defined in smtpd_recipient_restrictions and the end destination is defined in permit_mx_backup_networks (and/or relay_domains)
  4. Authenticated (trusted) users if permit_sasl_authenticated is defined in smtpd_recipient_restrictions

GO UP Image

Postfix control commands

The following commands control the operation of postfix.

# start/stop/restart postfix
# preferred method uses postfix tools
postfix [stop | start | reload]

# OR
[fc]/etc/rc.d/init.d/postfix [stop | start | restart]
[fc]service postfix [stop | start | restart]
[bsd]/usr/local/etc/rc.d/postfix [start | stop | restart]

# OR stop using long manual method 
more /var/spool/postfix/pid/master.pid [gives xxx = pid]
# then 
kill xxx

# OR another manual method
ps ax|grep postfix [gives xxx= pid]
# then 
kill xxx

# OR nice and quick for bsd
[bsd]killall postfix

# display configurations
postconf [all parameters]
postconf -n [only user supplied parameters]
postconf -d [display all default values]
postcong -m [display database types supported]
postconf mail_version [displays version number]

# start at boot
# [bsd] add to /etc/rc.conf
postfix_enable="YES"

# BSD only: completely disable sendmail
# in /etc/rc.conf
sendmail_enable="NO"
sendmail_outbound_enable="NO"
sendmail_submit_enable="NO"
sendmail_msp_queue_enable="NO"

# linux[fc] place KXXpostfix and SXXpostfix link in rcY.d directory
# XX is arbitrary and Y is run level 
ln /etc/rc.d/init.d/postfix /etc/rc.d/rc5.d/K69postfix
ln /etc/rc.d/init.d/postfix /etc/rc.d/rc5.d/S69postfix

GO UP Image

Postfix locations

Defines the default locations for binaries, scripts and config files with normal postfix distributions and packages.

Application Directory

[fc]/usr/sbin [scripts e.g. sendmail]
[fc]/usr/libexec/postfix [daemons]
[bsd]/usr/local/sbin [scripts]
[bsd]/usr/local/libexec/postfix [daemons]

Note: The installation option INST_BASE in FreeBSD changes the paths above to /usr/sbin and /usr/libexec respectively.

Documentation Directory

[fc]/usr/share/docs/postfix-xxx/html [where xxx is release]
[bsd]/usr/local/share/doc/postfix/index.html

Log File

Postfix uses syslogd for logging which, depending on the /etc/syslog.conf file, will typically stream to /var/log/maillog. Read with either:

# read last entries
vi + /var/log/maillog

# OR
tail [-n 20] /var/log/maillog
# where -n optionally defines the number of lines at
# the end of the file to be displayed. default is 10

# find specific mail-address log entries
cat /var/log/maillog|grep mail-address

Mail Queues Directories

/var/spool/postfix
/var/spool/postfix/maildrop [sendmail output location]

Mailboxes/Maildir Directories

Used to store mail for virtual domains hosted on this server and may be in mailbox (mbox) or Maildir format. Base directory is user defined in main.cf using virtual_mailbox_base = path parameter. We use the following directory structure as an example only:

# generic mail directory structure
/var/email/domains/domain-name/mailbox-name
# e.g. mail for info@example.com in mailbox (mbox) format
/var/email/domains/example.com/info

# Maildir format
/var/email/domains/domain-name/mailbox-name/Maildir/
# Maildir format uses three sub directories tmp, new, cur

# virtual_mailbox_base = /var/email/domains for all above examples

Configuration Files

# primary configuration file
[fc]/etc/postfix/main.cf
[bsd]/usr/local/etc/postfix/main.cf

# defines ports and various services used by postfix
[fc]/etc/postfix/master.cf
[bsd]/usr/local/etc/postfix/master.cf

# local mail alias file - used by mail originating from server
# defined in main.cf using alias_maps = db:path/to/file 
[fc]/etc/postfix/aliases 
[bsd]/usr/local/etc/postfix/aliases

# virtual domain configuration files 
# N.B. use any name you want for these files - just a suggestion

# virtual_mailbox_domains maps
# user defined in main.cf using virtual_mailbox_maps = db:path/to/file
# defines mailbox name to location 
# e.g. virtual_mailbox_maps = hash:/etc/postfix/virtual_mboxes
[fc]/etc/postfix/virtual_mboxes
[bsd]/usr/local/etc/postfix/virtual_mboxes

# virtual_alias_domains maps
# user defined in main.cf using virtual_alias_maps = db:path/to/file
# defines incoming to outgoing mailbox aliasing
# e.g. virtual_alias_maps = hash:/etc/postfix/virtual_aliases
[fc]/etc/postfix/virtual_aliases
[bsd]/usr/local/etc/postfix/virtual_aliases

Note: The installation option INST_BASE in FreeBSD changes the paths of all configuration files from/usr/local/etc/postix to /etc/postfix.

GO UP Image

Postfix Basic Configuration

There are many parameters controlling the behavior of postfix - this ends up being both a strength and a weakness. Adding to the confusion is that, like PERL, there is usually more than one way to do anything. The following files show the minimum parameters required to get postfix running with one or more virtual domains as a CLOSED MTA (does not allow relaying of external mail). The sample distribution file is big and well documented but can be a bit daunting. The following is the minimum required:

Word of Caution: Get a basic configuration running and deliverying email before you attempt anything else.

Minimal main.cf

# main.cf - minimal file
# you can always read the values of all postfix parameters 
# including defaults by using
# postconf [all values]
# postconf -n [only those defined by user]

# only change the next two lines if the default username (nobody) does 
# not exist. On many systems installation creates a unique postfix 
# account and group which should be used instead
default_privs = nobody
mail_owner = nobody

# next two lines can be omitted since they will default to 
# servers name and domain name
myhostname = hostname.example.com
mydomain = example.com

# added to unqualified mailbox addresses - used by local mail service
# can be ommitted if a valid aliases file exists since this does the
# same thing
myorigin = $mydomain

# local aliases normal default value - aliases file MUST be edited
alias_maps = hash:/usr/local/etc/postfix/aliases
# same thing again
alias_database = hash:/usr/local/etc/postfix/aliases

# next line is the default so could be omitted
inet_interfaces = all

# defines local network which is permitted by default to relay mail
# hereafter the key word mynetworks refers to this IP or IPs
mynetworks = 192.168.2.0/28, 10.5.0.0/16

# controls email sent to postmaster
# default is shown below - omit if this is OK
notify_classes = resource,software
# can also include - bounce, 2bounce, delay, policy, protocol

#
# VIRTUAL DOMAIN Definitions
#
# VIRTUAL ALIAS DOMAINS
# if no address manipulation required omit this section
# continue on new line if required but MUST start with a space
virtual_alias_domains = example.com

# next line defines the aliasing for each mailbox address
virtual_alias_maps = hash:/etc/postfix/virtual_aliases

# VIRTUAL MAILBOX DOMAINS
# for all domains that have mailboxes on this server/filesystem
# continue on new line if required but MUST start with a space
virtual_mailbox_domains = example.org example.net

# base for delivery to virtual_mailbox_domains
virtual_mailbox_base = /var/email/domains

# defines the location of each mailbox
virtual_mailbox_maps = hash:/etc/postfix/virtual_mboxes

GO UP Image

aliases file

The aliases files is used to define how local mail (without a domain suffix) is mapped or aliased to either other local mail accounts or domain based mail accounts. Local mail is typically generated by server scripts, daemons and other stuff. The name of the aliases file is defined by the alias_maps parameter of main.cf.

# User defines how this file is organized from the version supplied with
# postfix. It is used ONLY for mail originating on the server (normally 
# from applications and scripts) using unix (no domain name part) mail 
# accounts such as root, bin or postmaster
# In a typical virtual domain configuration, local names are mapped to
# useful domain based addresses such as security@example.com

# We use the following trivial policy:
# postmaster mail is mapped to mail-ops@example.com mailbox
# which leaves postmaster@example.com for external mail only
# root is mapped to server-ops@example.com for operational mail 
# such as weekly/daily/monthly reports and other such related stuff

# NOTE: short extract from distribution version for illustration
# of principles only

# this maps all postmaster stuff to an external mailbox
postmaster: mail-ops@example.com

# this maps root to a real account
root:		server-ops@example.com

# address to report security problems
security:	security@example.com

# DNS administrator (DNS soa records should use this)
hostmaster:	hostmaster@example.com

# http/web service administrator
www:		root
webmaster:	root
# FTP administrator (especially anonymous FTP)
ftp:		root

virtual_mboxes file

For use with virtual_mailbox_domains and specified by virtual_mailbox_maps in main.cf - defines the location and type of storage (mbox or Maildir).

Example file format:

# EXAMPLE.COM DOMAIN virtual_mboxes file
# defines path to local account mail, added to virtual_mailbox_base to 
# create full path

# uses Maildir format (end slash is vital)
info@example.com example.com/info/Maildir/

# multiple entries may be defined for same account
# this is another way of doing aliasing and perhaps avoids defining a
# virtual_alias_domains entry
sales-info@example.com example.com/info/Maildir/
# here is another common example
jsmith@example.com example.com/jsmith/Maildir/
john.smith@example.com example.com/jsmith/Maildir/

# this format without a trailing slash uses mailbox format
sales@example.com exmple.com/sales
# mailbox and Maildir may be used on a mailbox-by-mailbox basis

# when file is updated run
[fc]postmap /etc/postfix/virtual_aliases
[bsd]postmap /usr/local/etc/postfix/virtual_aliases
# then 
postfix reload

virtual_aliases file

Defines the alias operation to be performed on a users mailbox - for use with virtual_alias_domains.

Example File format:

# maps to example.com to example.net which may be 
# local (a local virtual_mailbox_domain) or remote
joe@example.com joe@example.net

# maps to multiple delivery mailboxes
sales@example.com fred@example.com,bill@example.com

# maps to a local system mailbox
sharon@example.com sharon

# maps any other mailbox to any@example.com
@example.com any@example.com

# when file is updated run
[fc]postmap /etc/postfix/virtual_aliases
[bsd]postmap /usr/local/etc/postfix/virtual_aliases
# then 
postfix reload

Note: The installation option INST_BASE in FreeBSD changes the paths of all configuration files from/usr/local/etc/postix to /etc/postfix.

Add new Virtual Domain

Quick reminder how to add a new domain and users:

  1. add new domain name to virtual_mailbox_domains line of main.cf. If a second line is required to list domains, it MUST start with whitespace e.g. a space.
  2. add new accounts to virtual_mboxes file.
  3. postmap virtual_mboxes (updates .dat/.db/.dm file)
  4. postfix reload

GO UP Image

Add new user to Virtual Domain

Quick reminder how to add a new user to an existing domain:

  1. add new accounts to virtual_mboxes file.
  2. postmap virtual_mboxes (updates .dat/.db/.dm file)
  3. postfix reload

GO UP Image

Add new Forwarding/Alias Domain and Accounts

If you want to, for example, send mail addressed to user@example.com to anything@example.net or user@example.com to a local system mailbox, this requires a virtual_alias_domain.

Quick reminder how to add a new alias domain and users:

  1. add new domain name to virtual_alias_domains line. If a second line is required to list domains, it MUST start with whitespace e.g. a space.
  2. add alias description to virtual_aliases.
  3. postmap virtual_aliases (updates .dat/.db/.dbm file)
  4. postfix reload

GO UP Image

Listening on Alternative Ports

Postfix normally sends and receives on the standard SMTP port 25. Where this is blocked, port 587 (the message or submission port) or sometimes port 465 can be used. Port 587 normally is used for secure TLS/SSL authenticated access but this is not mandatory. To listen on port 587 (and port 25) edit master.cf as shown below. This file uses symbolic names as defined in /etc/services, if port 465 were being used the first entry would be changed from submission to 465 or find the relevant name in /etc/services for 465, either will work:

#
# SPECIFY ONLY PROGRAMS THAT ARE WRITTEN TO RUN AS POSTFIX DAEMONS.
# ALL DAEMONS SPECIFIED HERE MUST SPEAK A POSTFIX-INTERNAL PROTOCOL.
#
# DO NOT SHARE THE POSTFIX QUEUE BETWEEN MULTIPLE POSTFIX INSTANCES.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
# submission port normally commented out
submission inet n      -       n       -       -       smtpd
#	-o smtpd_etrn_restrictions=reject
#628      inet  n       -       n       -       -       qmqpd
pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
#qmgr     fifo  n       -       n       300     1       oqmgr
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
relay     unix  -       -       n       -       -       smtp
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache	  unix	-	-	n	-	1	scache

Sending on Other Ports

If mail is blocked on port 25 then you may want to send all mail on an alternate port, such as 587. There are two possible solutions. First use a relay host line in main.cf as shown below:

relayhost = name.of.host:587

The relay host will receive on port 587 and then send on, say, port 25. OR declare a transport map using this statememt in main.cf:

transport_maps = hash:/name/of/file

Create the file and populate with the host name and port number as shown below:

mail.example.com smtp:[mail.example.com]:587

See also 'man transport' for file format details.

GO UP Image

General Anti-Spam Policy

Postfix contains a lot of built-in anti-spam techniques that are remarkably effective and should always be invoked before getting to resource hungry techniques such as mail scanning, for example Amavis/Spamassassin. In general the following represents a priority order in terms of resources used versus effectiveness though local circumstances and policy will always dictate the actual order of checks:

Note: In the restrictions below (helo/sender/recipient) the first one that succeeds or fails stops processing so the order is VERY important.

  1. check senders helo/ehlo message
    smtpd_delay_reject = no # required for all restrictions
    smtpd_helo_required = yes
    # apply restrictions based on the helo/ehlo message
    # checks are done in order defined
    smtpd_helo_restrictions =
     permit_mynetworks
     reject_invalid_hostname
     reject_unknown_hostname # costs DNS access
     reject_non_fqdn_hostname # test before using
    # allow all other stuff through
     permit
    

    Notes:

    1. The last permit line above is not strictly necessary since by default that is what postfix does - however it does not hurt to be reminded.
  2. email sender address restrictions
    smtpd_delay_reject = no # required for restrictions but only once
    # apply restrictions based on the senders address
    # checks are done in order defined
    smtpd_sender_restrictions =
    # bypass checks on outgoing mail for locally originated mail
     permit_mynetworks
     reject_unknown_sender_domain # costs DNS access
     reject_non_fqdn_sender 
    # allow all other stuff through
     permit
    
  3. recipient (these checks apply to mail being relayed) address restrictions
    smtpd_delay_reject = no # required for restrictions but only once
    # apply restrictions based on the recipients address
    # checks are done in order defined
    smtpd_recipient_restrictions =
    
    # bypass all checks on outgoing mail from local addresses
     permit_mynetworks
    
    # reject if not full email address - test before using
    # many email clients don't sent FQDN
     reject_non_fqdn_recipient
    
    # next line rejects if the account/domain does not exist 
    # ALSO prevents OPEN RELAY - if missing RELAY is OPEN!! 
    # MUST appear before the check_recipient_access
     reject_unauth_destination
    
    # perform optional filtering access by recipient name
     check_recipient_access hash:/usr/local/etc/postfix/filter_stuff
    
    # allow all other stuff through
     permit 
    
  4. So far the actual resource use is relatively trivial. It starts to get heavier from here onwards but again in the order defined below.

  5. greylisting - read about the technique and why we use it - hugely effective (~90%) but some disadvantages. postgrey configuration.

  6. SPF - Read about the technique and why we've had a SPF Record since 2004. The last stats we read suggested that over 1 million domains are now carrying SPF records while primarily preventing identity theft it is a low cost method of reducing spam and in combination with greylisting is even more powerful. SPF configuration.

  7. Mail scanning with Amavis (Spamassassin) - this a powerful, but hungry, monster that will suck up resources. Use any other technique to get rid of the spam load then let this feature rip at anything that is left - you may not even need it. This is the reason we place amavisd/spamassassin last. Amavis (Spamassassin) configuration.

    In general we do not use virus scanners such as ClamAV so they are not mentioned here. Many people do perform virus scanning of mail. Our view is that since the viruses are sent by spammers, if we stop the spam we stop the viruses. The opposing view says viruses are usually attached to mail from well known (to each user) sources when they have been infected so you should always use virus scanning. Take your choice. It is relatively simple to add clamAV to an amavisd based configuration which is the necessary first step for both scanning (content and virus) techniques.

GO UP Image

Incoming Filters

If you are using any anti-spam technique chances are you will need a filter of some sort. You can declare incoming address filters to perform or limit any process. Filters can operate on the senders address (smtpd_sender_restrictions), helo protocol message (smtpd_helo_restrictions) or the recipients mail address in which case you will declare them using an smtpd_recipient_restrictions = clause as shown below:

# FILTERING and INCOMING Restrictions
# apply restrictions based on the recipients address
# checks are done in order defined
smtpd_recipient_restrictions =

# bypass checks on outgoing mail
 permit_mynetworks

# reject if not full email address
 reject_non_fqdn_recipient
# next line rejects if the account/domain does not exist 
# ALSO prevents OPEN RELAY - if missing RELAY is OPEN!! 
# MUST appear before the check_recipient_access
 reject_unauth_destination

# perform filter access by recipient name
 check_recipient_access hash:/usr/local/etc/postfix/filter_stuff

# allow all other stuff through
 permit 

Finally create the file filter_stuff - to define the actions based on recipient domains or mailbox address:

# general format is 
# name ACTION

# allows email to be piped to a script for this mailbox address only
sales@example.com FILTER script:dummy
# dummy is a keyword: script may be any value and is
# used to reference the filter details in master.cf

# no checks on this domain OR omit it 
# undefined local domains will
# bypass all checks defined in this file
example.net OK

# discard all mail for this domain
example.org DISCARD

Then postmap filter_stuff to create the .dat/.db/.dbm file and postfix reload.

There are many action types that may be added to this filter file type (see man 5 access) more are illustrated for piping to a scipt, postgrey and SPF below.

GO UP Image

Pipe Mail to Script

Note: This configuration change uses the filter technique since it is most unlikely that you want to deliver all mail to a script. Then again why not.

To pipe mail to a script, invoke a filter using either check_recipient_access or check_sender_access. We use check_recipient_access in the example below:

# FILTERING and INCOMING Restrictions
# apply restrictions based on the recipients address
# checks are done in order defined
smtpd_recipient_restrictions =

# bypass checks on outgoing mail
 permit_mynetworks

# reject if not full email address
 reject_non_fqdn_recipient
# next line rejects if the account/domain does not exist 
# ALSO prevents OPEN RELAY - if missing RELAY is OPEN!! 
# MUST appear before the check_recipient_access
 reject_unauth_destination

# perform filter access by recipient name
 check_recipient_access hash:/usr/local/etc/postfix/script_filter

# allow all other stuff through
 permit 

Create script_filter file to describe the actions such as shown in the example below:

# allows email to be piped to a script for this mailbox address only
sales@example.com FILTER script:dummy
# dummy is a keyword and must be present, script may be any value and is
# used to reference the filter details in master.cf

# second filter uses another script destination
# will reference use support in master.cf (see below)
info@example.com FILTER support:dummy

# no checks on next domain OR omit 
# since undefined local domains will bypass all actions 
# defined in this file
example.net OK

# when complete
postmap script_filter

We illustrate only the use of FILTER support:dummy in the file above as an example. Add to the end of master.cf as shown in the snippet below:

# this pipes mail to the defined script using the 
# left-hand support:dummy name from script_filter file example 
# it could have been filter, joe, bill or whatever
support 	unix	-	n	n	-	-	pipe
 flags=Rq user=www 
  argv=/usr/local/www/web/support/index.php -f  $(sender) -- $(recipient)
# above all on one line or use a continuation 
# line which MUST start with one or more spaces

# where: (see 'man pipe' for more info)
# flags=Rq
#       R = Prepend Return-Path header
#       q = quote white space fields in $sender and $recipient
# user= is mandatory and must be appropriate 
# example uses apache located script so runs with same user
# argv= is the script destination and any required parameters
# $(sender) replaced with sender address
# $(recipient) replaced with recipients address
# i.e. above uses a sendmail style interface

Issue 'postfix reload' to pick up the changes.

GO UP Image

Postgrey Grey Listing

Postfix has two grey listing capabilities. An out of the box feature called greylist.pl server and postgrey which typically must be separately installed - but is available in FreeBSD ports (mail/postgrey) and as an RPM for most Linux distributions.

Adding postgrey on FreeBSD (make install clean) will install/configure:

  1. [bsd] /usr/local/sbin/postgrey [application]
  2. [bsd] /usr/local/sbin/postgreyreport [reporting tool]
  3. [bsd] /usr/local/etc/rc.d/postgrey.sh [startup script]
  4. [bsd] /usr/local/etc/postfix/postgrey_whitelist_clients
  5. [bsd] /usr/local/etc/postfix/postgrey_whitelist_clients
  6. [bsd] creates a user and group entry for greylist
  7. [bsd] creates /var/db/greylist [for database]
  8. [bsd] creates /var/mail/greylist [for temporary mail]

The FreeBSD startup script (postgrey.sh) among a bunch of other parameters causes postgrey to run as a daemon but is not activated by default - test with the following:

/usr/local/etc/rc.d/postgrey rcvar
$postgrey_enable=NO
# to activate script add to /etc/rc.conf
postgrey_enable="YES"
# then start postgrey using
/usr/local/etc/rc.d/postgrey start

Postgrey supports a number of parameters which can be displayed using:

postgrey --help

Paramters are as shown below:

--help [or -h] displays help info
--version display version number and exit
--verbose [or -v] increase verbosity level
--syslog-facility=name syslog facility name to use (default is mail)
--quiet [or -q] decrease verbosity level
--pidfile=/path/to/pid default = /var/run/postgrey.pid
--inet=ip:port [or -u=] Defines the IP and port on which the postgrey will run. Optional ip and port. FreeBSD uses port 10023, Linux tends to use 6000. If no ip assumes localhost (127.0.0.1), for example, --inet=10023 is the same as --inet=127.0.0.1:10023
--daemonize [or -d] run as daemon, defined in standard FreeBSD startup script
--user=postgrey valid account name to run postgrey
--group=postgrey valid group name to run postgrey
--dbdir=/path/to/db Path to database directory. FreeBSD uses /var/db/postgrey. Default is linux standard (?) /var/spool/postfix/postgrey
--delay=seconds Time to wait before re-tried mail is allowed - a black-hole period. Default = 300 = 5 mins
--max-age=days Time in days to keep entry before grey listed again. Default = 35 days
--whitelist-clients=/path/to/file List of sender email address actions. Default for FreeBSD is /usr/local/etc/postfix/postgrey_whitelist_clients, for linux will be /etc/postfix/postgrey_whitelist_clients. Multiple instances are allowed to define multiple files, for example, global and local versions and by default postgrep will look for a file named postgrey_whitelist_clients.local. Note: location not affected by INST_BASE in FreeBSD install options. See below for file format description.
--whitelist-recipients=/path/to/file List of recipient email address actions. Default for FreeBSD is /usr/local/etc/postfix/postgrey_whitelist_recipients, for linux will normally be /etc/postfix/postgrey_whitelist_recipients. Multiple instances are allowed to define multiple files, for example, global and local versions. Note: location not affected by INST_BASE in FreeBSD install options. See below for file format details
--retry-window=days Default = 2 days. Allow this time before deleting unused greylist entry i.e. default waits for up to 2 days for smtp to retry sent mail. Appending 'h' to value defines time in hours, for example 48h = 2 days.
--auto-whitelist-clients=number Default = 5. The default automatically whitelists clients on receipt of 5 emails. To disable auto whitelisting completely use a value of 0.
--hostname=fqdn Default is value returned by 'hostname' command, an alternate host name can be supplied and should be the same as that which appears in myhostname= of main.cf file.
--unix=path Path to unix socket, unix OR inet must be present.
--listen-queue-size=number Allow 'number' of operations to be queued for the postgrey socket. Default is the max allowable value = 999.
--x-greylist-header=text Defines the mail header that will be added to the mail item. Default is X-Greylist: delayed %t seconds by postgrey-%v at %h; %d. (for %x values see note below table).
--greylist-text=text Text sent to user. Default gives the url of a site that will give additional information about greylisting. Text can be changed but will not accept whitespace. Easiest way is to edit the postgrey script. Look for where it accesses the variable greylist-text e.g. 'cat /usr/local/sbin/postgrey|grep greylist-text'.
--greylist-action=TYPE Return action to Postfix/Exim when greylisted. Default = DEFER_IF_PERMIT which tells posfix to continue and defer the mail if it would otherwise accept the message with 450 message. 451 always sends a temp fail to user. Check return actions allowed in postfix access(5) ('man 5 access'). Again the limitation here is not allowing white space in any supplied action.
--lookup-by-host Use all address bits when constructing triplet = single IP.
--lookup-by-subnet Default. Strip last 8 bits when constructing triplet = class C range of IPs equivalent to IP/24.
--privacy Store data using SHA1 hash - default is no.
--exim Default no, use only when running with Exim MTA

Note: In text fileds the following variables may be used %s - seconds remaining of greylist time (--delay=), %t - the value of the greylist blackhole period in seconds (--delay=), %r - the mail domain name, %v - postgrey version number, %d - the Time and Date, %h - hostname (--hostname= or default).

To make changes to the command line issued on startup - find the startup script on your system (normally [bsd] /usr/local/etc/rc.d/postgrey and [fc] /etc/rc.d/init.d/postgrey and edit. FreeBSD users can just add the following to /etc/rc.conf:

# add as many entries as you want
postgrey_flags="--auto-whitelist-clients=2 --max-age=60"

Postgrey Whitelist file Formats

The file postgrey_whilelist_clients contains a list of various domains, IPs and accounts that are either whitelisted by the user or that have proven to cause greylisting problems and bypasses postgrey processing to avoid the problems. Multiple --whitelist-client files may be defined and a file with .local suffix is also looked for local senders. File format:

# postgrey whitelist for mail client hostnames
# --------------------------------------------
# file is 
# [bsd] /usr/local/etc/postfix/postgrey_whitelist_clients or specify its path
# with --whitelist-clients=/path/to/file

# entries may be domain name, any part or a regular expression
# anything from this address
southwest.com

# subdomain
scd.yahoo.com

# full mail address
me@example.com

# regular expression
/^ms-smtp.*\.rr\.com$/

# IP address
192.168.2.234

# or IP range range 192.168.2.0 to 255
192.168.2

The file postgrey_whilelist_recipients contains a list of incoming mailboxes that need to bypass the delay process all for fairly obvious reasons since theoretically they are used for urgent communication - you take the hit with spam on these boxes. File format:

# postgrey whitelist for mail recipients
# --------------------------------------
# put this file in /etc/postfix or specify its path
# with --whitelist-recipients=xxx
# mail to any of these mailboxes in any hosted domain will
# bypass greylisting
postmaster@
abuse@
hostmaster@

To invoke postgrey from postfix will depend on whether you want all domains or a subset both methods are shown below. Add or edit the following lines in main.cf:

# all hosted domains will use greylist
smtpd_recipient_restrictions =
 permit_mynetworks
 .....
 # next line MUST appear before check_policy_service or relay is OPEN
 reject_unauth_destination
 # example shows FreeBSD default port may differ on Linux distros
 check_policy_service inet:127.0.0.1:10023
 permit
 ....

# To greylist only some hosted (recipient) domains define a 
# class using next line
smtpd_restriction_classes = greylist
# and the class action next
greylist = check_policy_access inet:127.0.0.1:10023

# now define the recipients
smtpd_recipient_restrictions =
 permit_mynetworks
 .....
 # next line MUST appear before check_recipient_access or relay is OPEN
 reject_unauth_destination
 # invoke postgrey filter
 check_recipient_access hash:/usr/local/etc/postfix/greylist_filter
 
 permit
 
# greylist_filter file contents

# only example.com and example.net will use greylisting
# they invoke the defined greylist class
example.com greylist
example.net greylist
# example.org will not use greylisting
example.org OK
# the above may also be omitted since by default 
# anything which is not met by conditions passes 
# without any actions

# selective greylisting based on senders address
# would use same class technique but 
# smptd_sender_restrictions = clause

Notes:

  1. Postgrey runs as a standalone daemon and is invoked with 'check_policy_access inet:127.0.0.1:10023' which contains enough information for postfix and therefore does not require an entry in master.cf.

GO UP Image

SPF Policy Server

Especially in conjunction with greylisting, SPF is a low-resource feature that can help reduce spam by validating the allowed sources of email from any given domain. Essentially it tries to reduce the spammers ability to forge addresses.

postfix comes with its own SPF policy daemon or you can use postfix-policyd-spf-perl which is available in FreeBSD ports (mail/postfix-policyd-spf) but it looks as if you need to do a source install for Fedora Core.

We chose to go with postfix-policyd-spf since the native version seems to require a rebuild.

Install the software using ports in FreeBSD (or use this howto for Fedora Core or any Linux distro).

Add the following line to the end of master.cf.

# all on one line OR make sure there is a whitespace 
# at the beginning of the continuation line
spf unix - n n -- spawn user=nobody
 argv=/usr/local/sbin/postfix-policyd-spf

Adding SPF to main.cf uses almost the same principles as postgrey:

# all hosted domains will use spf
smtpd_recipient_restrictions =
 permit mynetworks
 .....
 # next line MUST appear before check_policy_service or relay is OPEN
 reject_unauth_destination
 
 # example shows FreeBSD default port may differ on Linux distros
 check_policy_service inet:127.0.0.1:10023
 
 # if both greylisting and SPF do SPF second
 # since it will only work on successful results
 # if no greylisting remove line above will not present
 check_policy_service unix:private/spf
 
 permit
 ....

# OR
# To SPF check only some hosted (recipient) domains define a 
# class using next line
smtpd_restriction_classes = greylist, spf
# and the class actions
spf = check_policy_service unix:private/spf
greylist = check_policy_access inet:127.0.0.1:10023
# NOTE: only one smtpd_restriction_classes parameter is allowed
# to define all classes used. This example shows both greylist and 
# spf classes. If greylisting is not being used then use
# smtpd_restriction_classes = spf
# and the line beginning greylist above would not be present

# now define the policy filter
smtpd_recipient_restrictions =
 permit mynetworks
 .....
 # next line MUST appear before check_recipient_access or relay is OPEN
 reject_unauth_destination
 
 # postgrey - if not required remove this line
 check_recipient_access hash:/usr/local/etc/postfix/greylist_filter
 
 # invoke SPF filter - after postgrey if present
 check_recipient_access hash:/usr/local/etc/postfix/spf_filter
 
 permit
 
# spf_filter file contents
# only example.com and example.net will use spf
# they invoke the defined spf class
example.com spf
example.net spf
# example.org will not use greylisting
example.org OK
# the above may also be omitted since by default 
# anything which is not met by conditions passes 
# without any actions

# selective spf based on senders address
# would use same class technique but 
# smptd_sender_restrictions = clause

Notes:

  1. The minimalist documentation for postfix-policyd-spf is in [bsd] /usr/local/share/doc/postfix-policyd-spf/README.

  2. The documentation refers to some previous names for the script. The current name is as shown.

  3. The FreeBSD port for mail/postfix-policyd-spf uses an older vesion of libspf2 than if you only installed libspf2. We did a 'make deinstall' for libspf2 because of conflicts then re-ran 'make install clean' for postfix-policy-spf to fix the problem.

  4. Both the postfix and the minimal postfix-policyd-spf documentation show check_policy_access unix:private/policy. The name policy is like example.com it is illustrative - we use the more meaningful (in our eyes) spf. It can be any name you want as long as the SAME name is used in main.cf and master.cf.

  5. Unlike almost every other postfix statement you can have more than one check_recipient_access as long as each refers to a different file.

  6. Postfix-policyd-spf is spawned by postfix whenrequired hence it is defined in master.cf unlike postgrey. Postgrey runs as a standalone daemon and is invoked with 'check_policy_access inet:127.0.0.1:10023' which contains enough information for postfix and therefore does not require an entry in master.cf.

GO UP Image

(Amavisd) SpamAssassin

While everone focusses on spam-filters and anti-virus checks - they consume serious computing resources. They should be the last line of defence - not the first. See General Anti-Spam Policy.

There are a bunch of mail content scanning applications which can be quite confusing - well to us. Here's a short list to help wade your way through this stuff (you can spend the rest of your life in amavisd's config file):

  1. Amavisd-new - the daemon interface to postfix (and other MTAs) for various mail content scanners and filters such as spamassassin, clamAV etc. Amavisd controls what other tools you want to use (open source and commercial) using its extensive configuration file and handles when to call what tool and handles results to postfix.
  2. Spamassassin - mail content scanner - rates results based on points to decide if spam or not. Does not perform virus scanning. Spamassassin can also use other tools like Razor, Pyzor and dcc-client.
  3. ClamAV - virus scanner engine.
  4. Other specialised scanning tools for jpeg files and other stuff.

Chances are if you need something it's probably referenced in the amavisd.conf file. Read it carefully when you have a few spare days.

Amavisd on FreeBSD is installed from ports (security/amavisd-new-xxx and installs spamassassin and tons of other stuff) and in the case of Fedora Core you will need to install amavisd-new and spamassassin RPMs. To install amavsid and spamassassin follow this list:

  1. Create a basic amavisd.conf file in either /etc [fc] or /usr/local/etc [bsd] by copying the basic distribution file:

    cp amavisd.conf-dist amavisd.conf
    

    There are normally two other files amavisd.conf-default (defines all the parameters) and amavisd.conf-sample (defines some sample files).

  2. check and edit the following minimal variables in amavisd.conf:

    # these are negative values leave first commented if ClamAV is installed
    # if ClamAV not installed uncomment as shown
    @bypass_virus_checks_maps = (1);  # uncomment to DISABLE anti-virus code
    # @bypass_spam_checks_maps  = (1);  # uncomment to DISABLE anti-spam code
    
    # check if the installation has a user/group for either vscan [bsd] or amavis
    # use vipw  or similar to check if not create both a user and group for 
    # one or other
    $daemon_user  = 'vscan';     # (no default;  customary: vscan or amavis), -u
    $daemon_group = 'vscan';     # (no default;  customary: vscan or amavis), -g
    
    # define a domain here that can receive mail
    $mydomain = 'example.com';   # a convenient default for other settings
    
    # change this if you have particular reasons
    $MYHOME = '/home/var/amavis';   # a convenient default for other settings, -H
    
    # either chage this or make sure it exists
    $TEMPBASE = "$MYHOME/tmp";   # working directory, needs to exist
    
    # if you want to use quarantine define directory here else set to
    # '' = empty string
    $QUARANTINEDIR = '';  # 
    
    # logging options
    $log_level = 3;              # verbosity 0..5, -d
    $log_recip_templ = undef;    # disable by-recipient level-0 log entries
    $DO_SYSLOG = 1;              # log via syslogd (preferred)
    $syslog_facility = 'mail';   # Syslog facility as a string
    # e.g.: mail, daemon, user, local0, ... local7
    $syslog_priority = 'info';  # Syslog base (minimal) priority as a string,
    #  choose from: emerg, alert, crit, err, warning, notice, info, debug
    
    # make sure this is the same port as used in postfix main.cf
    $inet_socket_port = 10024;   # listen on this local TCP port(s) (see $protocol)
    
    # these should be a valid email address on your system
    $virus_admin               = "virusalert\@$mydomain";  # notifications recip.
    $mailfrom_notify_admin     = "virusalert\@$mydomain";  # notifications sender
    $mailfrom_notify_recip     = "virusalert\@$mydomain";  # notifications sender
    $mailfrom_notify_spamadmin = "spam.police\@$mydomain"; # notifications sender
    $mailfrom_to_quarantine = ''; # null return path; uses original sender if undef
    
    # again check this matches postfix master.cf
    $notify_method  = 'smtp:[127.0.0.1]:10025';
    $forward_method = 'smtp:[127.0.0.1]:10025';  # set to undef with milter!
    
    # we use discard could be 
    #  D_PASS - pass mail to postfix for user
    #  D_BOUNCE - message bounced to sender
    #  D_REJECT - reject with 550 or (554)
    $final_virus_destiny      = D_DISCARD;
    $final_banned_destiny     = D_DISCARD;
    $final_spam_destiny       = D_DISCARD;
    

    You might want to look at the other values - the file is well laid out - but since it's executable PERL watch the formatting!.

  3. There is a spamassassin config file in /etc/spamassassin/local.cf [fc] or /etc/mail/spamassassin/local.cf [bsd] which you can inspect but nothing vital to get a basic config working.

  4. You can now start amavisd using:

    [bsd]/usr/local/etc/rc.d/amavisd.sh start
    [fc]/etc/rc.d/init.d/amavisd start
    
    # confirm running with 
    ps ax|grep amavisd
    # if not check /var/log/maillog
    

    To start amavisd at boot time:

    [bsd] add to /etc/rc.conf
    amavisd_enable="YES"
    
    # linux[fc] place Kxxamavisd and Sxxamavisd link in rcy.d directory
    # xx is arbitrary and y is run level 
    ln /etc/rc.d/init.d/amavisdx /etc/rc.d/rc5.d/K70amavisd
    ln /etc/rc.d/init.d/amavisd /etc/rc.d/rc5.d/S70amavisd
    
    
  5. To call amavisd from postfix add to end of master.cf as shown in the snippet below:

    Watch that the port number matches that defined by $inet_socket_port = 10024; in amavisd.conf. The values shown are FreeBSD defaults.

    # amavis filtering
    smtp-amavis	unix - -	-	-	2	smtp
     -o smtp_date_done_timeout=1200
     -o disable_dns_lookups=yes
    127.0.0.1:10025 inet	n	-	-	-	-	smtpd
     -o content_filter=
     -o local_recipient_maps=
     -o relay_recipient_maps=
     -o smtpd_restriction_classes=
     -o smtpd_client_restrictions=
     -o smtpd_helo_restrictions=
     -o smtpd_sender_restrictions=
     -o smtpd_recipient_restrictions=permit_mynetworks,reject
     -o mynetworks=127.0.0.0/8
     -o strict_rfc821_envelopes=yes 
    
    
  6. Add this in suitable place in postfix main.cf (again watch port number).

    # FILTERING and INCOMING Restrictions
    # AMAVIS FILTERING configuration
    content_filter=smtp-amavis:[127.0.0.1]:10024
    
  7. Now spend some serious time looking at the various setting in amavisd.conf and spamassassin's local.cf files to tweak the various parameters.

GO UP Image

SASL

SASL is a method of negotiating what form of authentication is required when accepting, and relaying, client mail. Postfix advertises a list of available methods using AUTH responses. Postfix supports two SASL methods: The Cyrus SASL library and Dovecot's SASL feature. Since we use Dovecot it makes configuration trivial - assuming your dovecot installation supports SASL. To configure postfix for SASL (the SASL methods advertised by Postfix are defined in the dovecot.conf file, postfix just passes and accepts data) make the changes shown in main.cf:

# main.cf
...
# turn on sasl and use the dovecot version
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot

# this next adds to the normal postfix mail storage path of
# [bsd] /var/spool/postfix and has a corresponding entry for dovecot
smtpd_sasl_path = private/auth

# depending on how dovecot is configured this stops postfix advertising
# anonymous login
smtpd_sasl_options = noanonymous

# allows a non-standard format of AUTH when dealing with
# older MS software
broken_sasl_auth_clients = yes

# now permit sasl authenticated relaying
# under smtpd_recipient_restrictions add in the order 
# required 
smtpd_recipient_restrictions =
 permit mynetworks
 ...
 permit_sasl_authenticated
 
 # next line MUST appear or relay is OPEN
 ...
 reject_unauth_destination
 

GO UP Image

Backup (Secondary) Mail Server

The world finds your mail server for inward bound mail by using a DNS query to find one or more MX (Mail Exchanger) Resource Records as shown below:

# fragment of zone file for example.com
....
# mail exchanger/mail server RR for example.com

       IN   MX   10 mail.example.com.

If this server (mail.example.com) is not available or busy then sensible (standard compliant) mail software will continue to retry, using a backoff algiorithm of some sort, over an extended period of time - typically from 12 to 48 hours. If however the mail server is still not available at the end of this extended period then an undeliverable notice is returned to the sender who must then take action to resend the message. To minimize problems it is possible to configure one or more backup (or secondary) mail servers which can accept mail in the event the primary mail server is busy or not available for a prolonged period of time. The role of a secondary or backup mail server is to accept the mail and continually try to forward (or relay) it to the primary mail server (see also notes on postfix realying).

Backup mail servers are defined in the DNS zone file and may be in the same domain as the main mail server or any other domain as required and shown below:

# fragment of zone file for example.com
....
# mail exchanger/mail server RR for example.com
# The value 10 in this case is the preference value
# low numbers mean most preferred and are 
# relative to all other preference values
       IN   MX   10 mail.example.com.
# secondary or backup mail server for example.com
# in this case it is shown being supplied by another domain
       IN   MX   20 mail.example.net.

In the above example we assume that mail.example.net (the backup mail server) is running postfix and would be configured with following additions to the main.cf file:

# main.cf
...
# define the domains that are valid relay destinations
relay_domains = $mydestination backed-updomain.name
permit_mx_backup_networks = backed-updomain.name

smtpd_recipient_restrictions =
 ...
# enable the backup feature
 permit_mx_backup
 reject_unauth_destination

# optional - allows the primary server
# to be out-of-service for up to 30 days
# before mail is rejected undeliverable
# NOTE: this parameter affects all mail retention 
#       times not just for backup servers
maximal_queue_lifetime = 30d

# defines the transfort maps to allow mail to be routed
# to the primary mail server(s)
# (optional - if not present the primary
# DNS MX RR is used to route) 
transport_maps = hash:/path/to/map/file

The file format used by transport_maps is:

# generic format of transport maps file
# domain.name protocol:destination.host.name
# usage illustration
example.com smtp:mail.example.com
# or if hosted by an external service
example.com smtp:mail.example.net

# note: the mail host may or may not be the same
# as that defined in the primary DNS MX record 

Cautionary Note: You cannot, in the ordinary sense of the word read your mail from a backup mail server. Instead the backup mail server's role is to continue to try and forward (relay) your mail at the earliest opportunity. If you use an extended timeout parameter (maximal_queue_lifetime=) of, say, 30 days then assuming your mail servers are out for an extended period of time the effect will be that when, say a customer, sends you an email it appears to be accepted but you do not respond. An undeliverable message is received perhaps 30 days later which, as we all know, is essentially meaningless. It may be better to notify customers early that you are having problems by having mail be rejected normally on the default 5 day period (or lower) even from the backup server. Finally the maximal_queue_lifetime= parameter affects all mail queues not just for backup systems.

GO UP Image



Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.

Tech

tech home
audio stuff
web stuff
dom stuff

css stuff
language stuff
regex stuff
rfc stuff


protocol stuff
cable stuff
lan wiring
rs232 wiring
dec > hex > bin
character sets
data rate stuff
mechanical stuff
howto stuff
survival stuff
wireless stuff
pc stuff
electronic stuff
tech links
open guides
RSS Feed Icon RSS Feed

If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox

web zytrax.com

Share Page

share page via facebook tweet this page submit page to stumbleupon submit page to reddit.com

Page Features

Page comment feature Send to a friend feature print this page Decrease font size Increase font size

Standards

General

ISO (International)
ANSI (US)
DIN (Germany)
ETSI (EU)
BSI (UK)
AFNOR (France)

Telecom

TIA (US)
EIA/ECIA (US)
ITU (International)
IEEE (US)
ETSI (EU)
OFTEL (UK)

Internet

IETF
IETF-RFCs
IANA
ICANN
W3C

Electronics

JEDEC
EIA (US)

Display full width page Full width page

Print this page Print this page

SPF Record Conformant Domain Logo

Copyright © 1994 - 2014 ZyTrax, Inc.
All rights reserved. Legal and Privacy
site by zytrax
Hosted by super.net.sg
web-master at zytrax
Page modified: September 16 2013.