Dividing postfix in two instances [UPDATED 2007/11/25]

[UPDATE 2007/11/25]: IP on /etc/postfix/main.cf was wrong. It has been changed from 88.88.88.3 to 88.88.88.2. This ip refers to first instance server.

This article is based on this article

Postfix has a problem when you need to know if mails are inbound or outbound. The only way to differentiate them is by separating traffic in two different servers. Someone could think “why should I separate traffic inbound and outbound?”.

My reason to separate postfix traffic was to avoid outgoing mails to be scanned by the anti-spam filter. This can be done in two ways: cheap or expensive. The way I'm gonna show is the cheapest one. That is by separating traffic in to instances in the same server which is cheaper than doing it on a separate server machines.

I'm gonna use Debian Etch System as example.

PREPARING NETWORK

First of all we need two IP address, one for inbound mails and the other for outbound mails, that is one IP for each postfix instance.

There are two ways of doing it. Configuring a virtual interface or a new real interface.

This configuration can be found in /etc/network/interfaces. Be careful if you manage this configuration remotely, if you apply an incorrect configuration your machine can be disconnected and you cannot access.

Here is an hypothetic example of virtual way:

#Here we've got only one physical interface on the server,
#but we create a virtual interface to be able to us the second IP

auto eth0
iface eth0 inet static
address 88.88.88.2
netmask 255.255.255.248
gateway 88.88.88.1

auto eth0:1
iface eth0:1 inet static
address 88.88.88.3
netmask 255.255.255.248

This is real way:

#Here we've got two real interfaces in the server.

auto eth0
iface eth0 inet static
address 88.88.88.2
netmask 255.255.255.248
gateway 88.88.88.1

auto eth1
iface eth1 inet static
address 88.88.88.3
netmask 255.255.255.248

If you've got a DNS server add new entry for the second instance or to /etc/hosts file for example:

88.88.88.2 instance1.domain.com

88.88.88.3 instance2.domain.com

CREATING A SECOND INSTANCE FOR OUTBOUND MAILS

When we've got networking configuration done then we gonna create the second postfix instance. I supose you already have one instance running. If there's no one running yet then I recommend you to read this article before.

Copy your existing postfix configuration folder:

mail:/root# cp -rp /etc/postfix /etc/postfix-out

Modify or add the following line to /etc/postfix-out/main.cf:

queue_directory = /var/spool/postfix-out

Create this new spool folder and verify your configuration:

mail:/root# mkdir /var/spool/postfix-out
mail:/root# postfix -c /etc/postfix-out check

If your postfix is chrooted then you must copy the following folders:

mail:/root# cp -rp /var/spool/postfix/etc /var/spool/postfix-out
mail:/root# cp -rp /var/spool/postfix/usr /var/spool/postfix-out
mail:/root# cp -rp /var/spool/postfix/lib /var/spool/postfix-out

CONFIGURING INSTANCES

Now we gonna tell first instance that there's another one, edit /etc/postfix/main.cf and add the following line:

alternate_config_directories = /etc/postfix-out

At this point we need to separate postfix instances so they don't collide:

Edit /etc/postfix/main.cf and /etc/postfix-out/main.cf and add or edit the following lines:

#/etc/postfix/main.cf
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) INSTANCE 1
#(Edit if you want, it's useful for testing
#if the instance is listening where is suppose to be)
myhostname = instance1.domain.com #(won't change)
inet_interfaces = instance1.domain.com #(add)
smtp_bind_address = 88.88.88.2 #(add) This refers to the IP we use to comunicate with outside world

Replace all mentions to “instance1.domain.com”, you may set before reading this manual, for new instance name “instance2.domain.com”. Remove lines refering to mail fiters like “content_filter = amavis:[127.0.0.1]:10024″ in the following file:

#/etc/postfix-out/main.cf
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) INSTANCE 2 # (The same as the other one)
myhostname = instance2.domain.com #(edit)
inet_interfaces = instance2.domain.com #(add)
smtp_bind_address = 88.88.88.3 #(add) This is the outside world server, this will be the sender.

After that modify /etc/postfix*/master.cf on both instance:

The first one (/etc/postfix/master.cf) may look something like that at the begining:

smtp inet n – – – – smtpd -o content_filter=spamassassin

Edit it so it looks like that:

88.88.88.2:smtp inet n – – – – smtpd -o content_filter=spamassassin

The second one(/etc/postfix-out/master.cf) looks the same but we must remove anti-spam part, because we are doing it to avoid outgoing mail to be scanned:

88.88.88.3:smtp inet n – – – – smtpd

SMTP AUTHENTICATION

In my case I authenticate users using saslauth, if it's your case you must change some files:

First stop this daemon

mail:/root# /etc/init.d/saslauthd stop

Edit /etc/default/saslauthd. This file may contain a line like that:

PARAMS=”-m /var/spool/postfix/var/run/saslauthd -r”

We replace for:

PARAMS=”-m /var/spool/postfix-out/var/run/saslauthd -r”

Edit /etc/init.d/saslauthd file and find this line:


PIDFILE=”/var/spool/postfix/var/run/saslauthd/saslauthd.pid”

Replace for:

PIDFILE=”/var/spool/postfix-out/var/run/saslauthd/saslauthd.pid”

We are telling saslauthd to authenticate users using the second instance

Finally start it again

mail:/root# /etc/init.d/saslauthd start

STARTING POSTFIX INSTANCES AND TESTING THEM

mail:/root# /etc/init.d/postfix restart
mail:/root# postfix -c /etc/postfix-out start

To test if it works as it's expected try this:

mail:/root# telnet instance1.domain.com 25
Trying 88.88.88.2…
Connected to instance1.domain.com.
Escape character is '^]'.
220 instance1.domain.com ESMTP Postfix (Debian/GNU) INSTANCE 1
(control+])
telnet>quit

mail:/root# telnet instance2.domain.com 25
Trying 88.88.88.3…
Connected to instance2.domain.com.
Escape character is '^]'.
220 instance2.domain.com ESMTP Postfix (Debian/GNU) INSTANCE 2
(control+])
telnet>quit

You can also see if instances are running by typing this:

mail:/root# netstat -ln | grep :25
tcp 0 0 88.88.88.2:25 0.0.0.0:* LISTEN
tcp 0 0 88.88.88.3:25 0.0.0.0:* LISTEN

INSTALLING POSTFIX STARTUP SCRIPT

I prepared a startup script to control both instances at the same time. You should place it in /etc/init.d. I recommend you do a backup of the original before installing the new one.

Download the startup script compressed in BZIP2 or GZIP

Download one of them

mail:/root# wget http://www.forniol.cat/manuals/postfix/postfix-script-two-instances.bz2
mail:/root# wget http://www.forniol.cat/manuals/postfix/postfix-script-two-instances.gz

Extract, backup the old one and install new.

mail:/root# bunzip2 postfix-script-two-instances.bz2
mail:/root# mv /etc/init.d/postfix /etc/init.d/postfix.back
mail:/root# mv postfix-script-two-instances /etc/init.d/postfix
mail:/root# chmod 755 /etc/init.d/postfix

Your system is ready to run.

There is a little issue I can't solve. That is separate logs on each instance. In the guide I linked at the beginning says “syslog_facility” directive should be changed. If anyone know how it works his contribution will be wellcome.