postfix / postscreen and dns blacklist fun

I decided to stop using my hacky perl script for Postfix policyd stuff as it’s ages since I wrote any perl … and instead use postscreen the other day.

Postscreen setup – was fairly easy – there’s a load of config below.

Gotchas – spamhaus doesn’t like you if you might be sending your DNS through a public resolver (E.g. 8.8.8.8) – so you need to do an =127.0.0.[1..11] to it.

It also logs quite a lot.

Current Postfix postscreen main.cf config :

postscreen_access_list = permit_mynetworks, cidr:/etc/postfix/postscreen_access.cidr
postscreen_dnsbl_threshold = 2
postscreen_dnsbl_sites = zen.spamhaus.org=127.0.0.[2..11]*2
       bl.spamcop.net*1 
       b.barracudacentral.org=127.0.0.2*1
       bl.spameatingmonkey.net*1
       bl.mailspike.net*1
       tor.ahnl.org*1
       dnsbl.justspam.org=127.0.0.2*1
       bip.virusfree.cz*1
       spam.dnsbl.sorbs.net=127.0.0.6*1

postscreen_greet_action = enforce
postscreen_greet_wait = 5s
postscreen_greet_ttl = 2d

postscreen_blacklist_action = drop
postscreen_dnsbl_ttl = 2h

SMTP Auth whitelisting …

My server allows people to send out authenticated on port 25, but postscreen doesn’t seem to be aware of this when it runs; so such people may be blocked by their IP being in a DNS Blacklist … and therefore need explicitly whitelisting via a dovecot postlogin script (example below) which if used, requires the postscreen_access_list to change to be something like :

postscreen_access_list = permit_mynetworks
	cidr:/etc/postfix/postscreen_access.cidr
	mysql:/etc/postfix/mysql/check_mail_log.cf

and /etc/postfix/mysql/check_mail_log.cf looks like :

user = mail_log
password = something
hosts = 127.0.0.1
dbname = mail_log
query = SELECT 'permit' FROM mail_log WHERE ip_address = '%s' UNION SELECT 'dunno' LIMIT 1 ;

The dovecot config change(s) are – in /etc/dovecot/dovecot.conf

....
service pop3 {
	executable = pop3 postlogin
}
service imap {
	executable = imap postlogin
}

service postlogin {
	executable = script-login /etc/dovecot/postlogin.sh
	user = $default_internal_user
	unix_listener postlogin {
	}
}
....

and /etc/dovecot/postlogin.sh looks a bit like :

#!/bin/bash

if [ "x${IP}" != "x" ]; then
	if [ ! "$IP" = "127.0.0.1" ]; then
		echo "INSERT INTO mail_log (username, ip_address) VALUES ('$USER', '$IP')" | mysql --defaults-extra-file=/etc/dovecot/mysql.cnf mail_log
	fi
fi

exec "$@"

exit 0

The /etc/dovecot/postlogin.sh will need to be executable.

/etc/dovecot/mysql.cnf just looks like a normal MySQL cnf file –

[client]
user = mail_log
password = something
database = mail_log

CREATE TABLE `mail_log` (
  `username` varchar(255) NOT NULL,
  `ip_address` varchar(255) NOT NULL,
  `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY `mlip` (`ip_address`(191)),
  KEY `dt_idx` (`dt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

and that being the SQL schema.

Ideally I suppose you’d add a cron job to prune entries in mail_log older than a set time, and probably have a unique key on username with some sort of “INSERT INTO x ON DUPLICATE … ” change to the postlogin.sh script above.

Postfix – qshape

Somehow I’ve only just found out about ‘qshape’.

It’s a nice little tool to help show what’s going on, on a postfix based mail server.

You can summarise by sender (-s) and choose the queue …. which is a bit easier than trying to spot patterns in the ‘mailq’ output.

Postfixadmin – setup/install guide for virtual mail users on Postfix

This is a re-hash of the various guides I’ve made over the years detailing how to setup a virtual mail server (i.e. one that can handle multiple domains/users).

This guide is based on release 2.3 of Postfixadmin. It’s about the only open source project I contribute to regularly – so I ought to at least make an effort and document it 🙂

Requirements:

  • Linux Server (Debian, Ubuntu, CentOS, SuSE) or FreeBSD etc
  • PostgreSQL or MySQL database
  • PHP 5.2.x or greater
  • Postfix
  • Courier / Cyrus / Dovecot (as appropriate) (I only use Courier, so am of little help with the others).

Postfixadmin Installation

This assumes version 2.3 or above.

dpkg -i postfixadmin-xxxxx.deb

There are also rpm’s around somewhere for SuSE/RH, a port in FreeBSD or you can install from source.

Using the .deb, the database should be created for you, along with some configuration options being filled in within config.inc.php.

  1. Visit setup.php – it will prompt you to create a setup_password, which needs putting into the config.inc.php file
  2. After editing config.inc.php, re-visit setup.php and follow it through – this will create the admin user and setup the initial DB structure
  3. Your database should now be installed
  4. You may wish to edit other config.inc.php settings (e.g. to turn vacation support on/off or to turn xmlrpc support on/off).

If you perform an upgrade of Postfixadmin in the future, all upgrades to the database should be handled automatically through use of ‘upgrade.php’.

Postfix configuration

There are a few changes that need making to Postfix, firstly – it’s necessary to tell it to use a relational database for various lookups (e.g. aliases and mailboxes); it’s also necessary to configure it to support vacation/auto-reply emails – if you require this functionality.

In my case, I run Postfix on Debian Lenny – other platforms may vary slightly. To attempt at being ‘tidy’ the configuration files for PostgreSQL live in /etc/postfix/pgsql.

(If you’re security concious, especially when you own Daisy slots or any online betting site, then you might want to ensure the database ‘postfix’ user only has read permissions)

Note: I’ve not used the proper alias domains stuff yet – if you wish to use it, check the supplied documentation with Postfixadmin (POSTFIX_CONF.txt)

File: relay_domains.cf

user = postfix
password = something
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = true

File: virtual_alias_maps.cf

user = postfix
password = something
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = true

File: virtual_domains_maps.cf

user = postfix
password = something
hosts = localhost
dbname = postfix
#query = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = false and active = true

File: virtual_mailbox_limits.cf

# Used for QUOTA!
user = postfix
password = something
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s'

(Note: I’ve never used quota support, so I can’t guarantee the above is correct)

File: virtual_mailbox_maps.cf

user = postfix
password = something
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true

To /etc/postfix/main.cf add the following :

relay_domains = <whatever may have been here before> proxy:pgsql:/etc/postfix/pgsql/relay_domains.cf
virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_maps.cf
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/pgsql/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_mailbox_maps.cf
virtual_mailbox_base = /var/mail/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 8
virtual_transport = virtual
virtual_uid_maps = static:8
virtual_gid_maps = static:8
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
# this is only needed if you want vacation support -
transport_maps = hash:/etc/postfix/transport

Adding the 'proxy:' to the various lookup lines should improve performance/scalability.

Courier configuration

Courier needs configuring to know how to authorise clients and where to find mailboxes on disk.

/etc/courier/authdaemonrc :

– Enable the appropriate module – e.g.

authmodulelist=”authpgsql”

And then in ‘authpgsqlrc’ contains :

PGSQL_HOST        localhost
PGSQL_PORT        5432
PGSQL_USERNAME        postfix
PGSQL_PASSWORD        something
PGSQL_DATABASE         postfix
PGSQL_USER_TABLE    mailbox
PGSQL_CRYPT_PWFIELD    password
PGSQL_UID_FIELD        ‘8’
PGSQL_GID_FIELD        ‘8’
PGSQL_LOGIN_FIELD    username
PGSQL_HOME_FIELD    ‘/var/mail/vmail’
PGSQL_NAME_FIELD    name
PGSQL_MAILDIR_FIELD    maildir
PGSQL_QUOTA_FIELD    quota

(As you can see, I’ve elected to store the mail under /var/mail/vmail with file ownerships set to 8:8. Your installation may differ – but obviously ensure this is kept in sync with Postfix’s main.cf).

This would probably be a good time to test the system to ensure authentication works correctly – create a virtual mailbox through Postfixadmin and tail -f /var/log/mail.log and see if you can login via pop3/imap etc.

SMTP Authentication

This is often useful to allow remote clients to relay through the server – assuming they can prove who they are!

Postfix can use SASL for authentication  – this requires SASL to be told to use imap to perform the authentication checks.

File: /etc/sasl/smtpd.conf
pwcheck_method: saslauthd
saslauthd_path: /var/run/saslauthd/mux
log_level: 3
mech_list: PLAIN LOGIN
auxprop_plugin: rimap

On Debian, I have sasl2-bin, libsasl2-modules and libsasl7 packages installed.

You’ll need to edit /etc/default/saslauthd and ensure it has :

OPTIONS=”-c -r  -O localhost -m /var/spool/postfix/var/run/saslauthd”

You may also need to explicitly create the above path.

Create /etc/postfix/sasl/smtpd.conf with :

pwcheck_method: saslauthd
saslauthd_path: /var/run/saslauthd/mux
log_level: 3
mech_list: PLAIN LOGIN
auxprop_plugin: rimap

And ensure /etc/postfix/main.cf has :

smtpd_sasl_authenticated_header = yes
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes

And smtpd_sender_restrictions contains ‘permit_sasl_authenticated’

Squirrelmail-postfixadmin

If you wish to allow your users to change their passwords/forwarding settings or vacation/auto-reply settings, a postfixadmin plugin is available for squirrelmail (squirrelmail-postfixadmin). You can download it from https://github.com/postfixadmin/postfixadmin/tree/master/ADDITIONS/squirrelmail-plugin

The latest version of the plugin works over XMLRPC and requires very minimal configuration – you’ll need to edit the config file within the plugin to specify the XMLRPC interface URL (http://server/postfixadmin/xmlrpc.php). It’s also necessary to edit the Postfixadmin config.inc.php file to explicitly enable the xmlrpc interface.

Note, when your users go to use the postfixadmin-squirrelmail plugin they will be prompted to enter their mailbox password.