Installation:FreeBSD:Postfix

From PMWH2 - PHPMyWebHosting's official wiki
Revision as of 16:51, 13 February 2006 by Chris (talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
up

Needed Packages

On FreeBSD (5.3) you will need to install the following ports:

  • postfix
  • pam-mysql
  • cyrus-sasl2-saslauthd
  • amavisd-new, zoo, lha, unarj, unzip (if you want virus scanning)
  • postgrey

You will also need very basic knowledge of "ee", the easy editor.

Installation

To install the packages on FreeBSD 5.3, you have to do the following:

At first we start it of with postfix. There are a couple directories in /usr/ports/mail, as of today (12/26/2004), the postfix directory contains Postfix v2.x and that's what we want.

After you started the installation with the "make" and the port downloaded all necessary software, it will present you with a couple options to install Postfix with. Make sure you use SASL2 and TLS. Choose whatever else you deem necessary, but then you are a little on your own. ;-) So for example if you want SPF, you may choose it here (didn't work for me though).

cd /usr/ports/mail/postfix
make WITH_MYSQL=YES WITH_MYSQL_VER=40
make install
make clean

Pam_mysql has broken support of MYSQL 4.1.x we have to use WITH_MYSQL_VER=40 instead of 41

Since PMWH encrypts your users password when storing them in MySQL, we have to use PAM instead of auxprob's SQL plugin. While SASLv1 requires only PAM, with SASLv2, PAM and saslauthd are required to authorize your users on SMTP against a SQL database (MySQL, PgSQL).

cd /usr/ports/security/pam-mysql
make
make install
make clean
cd /usr/ports/security/cyrus-sasl2-saslauthd
make
make install
make clean

To enable saslauthd, add the following line into /etc/rc.conf :

ee /etc/rc.conf
saslauthd_enable="YES"

To test:

cd /usr/local/etc/rc.d/
./saslauthd.sh rcvar

If you want amavisd-new, you'll continue with the following helper tools:

cd /usr/ports/archivers/zoo
make
make install
make clean

(Continue with the same steps for unarj, unzip and lha.)

Then, for amavisd-new (drop WITH_MYSQL if you don't want it):

cd /usr/ports/security/amvisd-new
make WITH_MYSQL
make install
make clean

If you installed amavisd-new, go /usr/local/etc/amavisd.conf have a look at the following lines:

$max_servers = ...;
$sa_local_tests_only = 1;
$sa_mail_body_size_limit = 32*1024;

$max_servers is another one of those that you need to tune. At least imho. Depending on your mail traffic you might want to decrease or increase it.

$sa_local_tests_only is by default set to '0'. I set it to '1' cause remote tests can really slow down the whole process of delivery. Especially when there is unforseen DNS problems and so on. I would suggest that when necessary setup a gateway that does those kind of checks before mail actually hits your mailserver.

The $sa_mail_body_size_limit is far too big. I decreased it and I recommend it to you as well, because otherwise amavisd will slowly but surely "kill" your entire server. Once again this setting should be subject to your very personal needs. Hardware plays an important role here. If you have the resources, go for it. Anyway, just have it on your list for later on!

Then go into /etc/rc.conf and add the following line:

amavisd_enable="YES"

Save, and test with:

cd /usr/local/etc/rc.d
./amavisd rcvar

If it's enabled, to start it with:

./amavisd start

If you want postgrey (more information), do the following:

cd /usr/ports/mail/postgrey
make WITH_BDB_VER=41
make install
make clean

In my case (Celeron, 1.7 Ghz, 1 GB RAM) it took a while to build BDB, so relax and get a coffee.

To enable postgrey on startup, add the following line to /etc/rc.conf

postgrey_enable="YES"

To test:

cd /usr/local/etc/rc.d
./postgrey.sh rcvar

The port ("postgrey") installs whitelist files into /usr/local/etc/postfix/

ls -l /usr/local/etc/postfix/postgrey*

Have a look at the sample files and adjust them as needed.

So for example, the default configuration uses 300 seconds (5 minutes) to temporary block emails and creates a window of 48 hours if one came through. While this works out in some cases, recently spamers have gotten more and more around this by sending multiple emails and so on. Therefor I found values of 15 minutes and 12 hour windows to be more acceptable.

To start postgrey, do:

./postgrey.sh start

To make postfix talk to postgrey, enter the following in postfix's main.cf:

check_policy_service inet:127.0.0.1:10023

Right where it reads:

smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   check_policy_service inet:127.0.0.1:10023


Please do not just copy and paste those instructions in your term. Keep in mind to think before you install. For example, it can be quite useful to cvsup your ports collecting. Perl might need an upgrade (postgrey requires min. of 5.6). Or, if a port is already installed, then you will only need an upgrade (if one is available).

Once that each port is done installing it will list installed binaries, libs and configuration files. ;-)

Please create a new systemuser named "vmail" to your system.

On FreeBSD (follow the step by step instructions):

adduser -E -w no

(-E tells adduser to lock the account after creation.)

If this is the first time that you use "adduser", it will run through the initial adduser-setup first and save your choices to /etc/adduser.conf. Bear in mind, in case you get confused.

After the creation, type this to get uid and gid of the vmail user, we will need those values in Postfix' main.cf.

bash #> id vmail
uid=1005(vmail) gid=1005(vmail) Gruppen=1005(vmail)
bash #>
id vmail

Postfix configuration

First, you have to configure postfix to connect to mysql database which is installed via phpmywebhosting.

I configured Postfix to not run in chroot on FreeBSD. Do accomplish this, do the following:

ee /usr/local/etc/postfix/master.cf

And change all "y" in the column "chroot" to "n".

All you need to do is symlink the postfix executable in rc.d

cd /usr/local/etc/rc.d
ln -s /usr/local/sbin/postfix postfix.sh

Make sure you add the following lines in /etc/rc.conf to disable sendmail completely:

sendmail_enable="NONE"

Add those lines to /etc/periodic.conf to disable sendmail's crontabs:

daily_clean_hoststat_enable="NO"
daily_status_mail_rejects_enable="NO"
daily_status_include_submit_mailq="NO"
daily_submit_queuerun="NO"

This enables postfix on startup. Since FreeBSD will start scripts in alphabetical order, we won't have to worry about that. MySQL will always start before Postfix when the system boots.

Now make sure that you have Postfix set up properly. These directives should be set in the file main.cf. Please make sure to change the values that are printed in strong letters to your personal needs.

For FreeBSD, you will find the files in "/usr/local/etc/postfix", instead of "/etc/postfix" on Debian/GNU. Make sure that you adjust the paths to the MySQL files if you are on FreeBSD, the examples below are for Debian/GNU.

FreeBSD: /usr/local/etc/postfix/main.cf

# basic settings
command_directory = /usr/sbin
daemon_directory = /usr/lib/postfix
program_directory = /usr/lib/postfix 
myorigin = [your domain] 
mydomain = [your domain]
myhostname = [hostname.your domain]
mydestination = $myhostname, localhost.$mydomain, $mydomain, $transport_maps
mynetworks = [local IP address range]

# virtual domain and delivery settings
virtual_mailbox_limit = 10000000
virtual_mailbox_base = /home/vmail/
virtual_uid_maps = static:[VMAIL-UID]
virtual_gid_maps = static:[VMAIL-UID]
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-maps.cf
alias_maps = mysql:/etc/postfix/mysql-aliases.cf
transport_maps = mysql:/etc/postfix/mysql-transport.cf
virtual_maps = mysql:/etc/postfix/mysql-virtual.cf

# define which email is accepted for delivery only 
# alias_maps means: addresses in the MySQL aliase table
# virtual_mailbox_maps: addresses in the MySQL virtual table
# unix:passwd.byname: addresses of local users in /etc/passwd (optional)
local_recipient_maps = $alias_maps $virtual_mailbox_maps unix:passwd.byname

# settings for authenticated SMTP
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_relay_domains
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes

# some other options
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) # or FreeBSD ;-)
setgid_group = postdrop
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no
relayhost =  
mailbox_size_limit = 0
recipient_delimiter = +

message_size_limit = 10000000

As you can see we will not be querying the MySQL database according to definitions in /usr/local/etc/postfix/mysql-aliases.cf.

For this to work you need to create these files first. They define how Postfix accesses the database and how you named the fields. Just copy and paste them:

Here is the following set of files in a tar.gz. A little perl script called fill.pl will ask you for the needed values and fill the files with the correct values. To use it, just do

bash #> tar xvfz portfix-mysql.tar.gz
bash #> cd postfix
bash #> ./fill.pl
What is the name of the database admin user? [postfix database name, e.g. vmail]
What is his password?                        [another secret from above]
What is the database hostname?               localhost [or IP address]
bash #> cp mysql-* /etc/postfix/
bash #>

Copy those files to /usr/local/etc/postfix and start/restart postfix with:

postfix restart

FreeBSD: /usr/local/etc/postfix/mysql-virtual-maps.cf

user = [database admin user]
password = [database admin password]
dbname = provider
table = users
select_field = maildir
where_field = email
additional_conditions = and postfix = 'y'
hosts = [database server hostname]

FreeBSD: /usr/local/etc/postfix/mysql-aliases.cf

user = [database admin user]
password = [database admin password]
dbname = provider
table = alias
select_field = destination
where_field = alias
hosts = [database server hostname]

FreeBSD: /usr/local/etc/postfix/mysql-transport.cf

user = [database admin user]
password = [database admin password]
dbname = provider
table = transport
select_field = destination
where_field = domain
hosts = [database server hostname]

FreeBSD: /usr/local/etc/postfix/mysql-virtual.cf

user = [database admin user]
password = [database admin password]
dbname = provider
table = virtual
select_field = destination
where_field = email
hosts = [database server hostname]

Now we configure postfix to understand authenticated SMTP.

Imagine your users fetch their email using POP3. Now they need a way to send mails via your mail server. For security reasons Postfix allows users in the local (=trusted) network to send emails. (You obviously want this security if you don't want to work as an open relay for spammers.) My suggestion is that your users use authenticated SMTP. This means that their email clients provide a username and password to the mail server to make them "trusted". Most email cilents have this feature included.

Setting authenticated SMTP isn't that complicated. The only pitfall is that Debian runs Postfix in a chroot'ed environment by default. ("chroot'ed" means that Debian pretends that the "/var/spool/postfix" directory is pretended to be "/" - so Postfix cannot move out of this secure subdirectory. Anyone who finds a security problem and messes with Postfix can only do harm to that very subdirectory and not screw your whole system)

There may be different ways to use authentication with SMTP. I decided to use PAM (pluggable authentication modules). The authentication configuration is usually stored in "/etc/pam.d". As Postfix runs chroot'ed the configuration is searched for in "/var/spool/postfix/etc/pam.d". Just go there and put the following lines in a file called "smtp" (the backslashes show that all declarations are to be written in a single line):

Since we decided to install Postfix un-chrooted, we won't have to worry about accessing files in /etc/pam.d. Just create the following files.

FreeBSD: /etc/pam.d/smtp

auth required pam_mysql.so user=[database admin user] passwd=[database admin password] host=[database server hostname] \
       db=provider table=users usercolumn=email passwdcolumn=password crypt=1
account sufficient pam_mysql.so user=[database admin user] passwd=[database admin password] host=[database server hostname] \
       db=provider table=users usercolumn=email passwdcolumn=password crypt=1

For security reasons we change the ownership and permissions of that file. So it only can be read by root and postfix:

#> chown root:postfix /etc/pam.d/smtp
#> chmod 660 /etc/pam.d/smtp

You might have to create the sasl directory: /usr/local/etc/postfix/sasl/smtpd.conf

pwcheck_method: saslauthd
mech_list: plain login

I'm not a PAM guru and this took me a while to figure out (,btw: BIG SHOUTOUTS TO postfixbuch-users ML), but those are the steps to get it working with SASLv2 on FreeBSD.

Add the following line to /etc/rc.conf

saslauthd_enable="YES"

Test with:

cd /usr/local/etc/rc.d
./saslauthd.sh rcvar

If all went well, start it off:

./saslauthd.sh start

In my case saslauthd was configured to use PAM. So if your case is different and saslauthd does not know about PAM, make sure you have this line in /usr/local/etc/rc.d/saslauthd.sh:

saslauthd_flags=${saslauthd_flags:-"-a pam"}
Virus filtering

Now that you operate your own professional email server you may offer your users a little more service: scanning incoming emails for viruses. Good news: it is perfectly easy to install. Bad news: it will most likely mean you have to spend money because good antivirus software does not come for free (yet).

Let's get to work. First make sure you installed the amavisd-new package. Amavis is a piece of software that gets all emails forwarded, scans them using an external virus scanner and re-injects them into your mail system. It is important to note that Amavis does not include a virus scanner - it is just an interface between Postfix and your favorite virus scanner. So make sure you have a virus scanner already installed and keep it up-to-date.

Now please take a look at the /etc/amavis/amavisd.conf (FreeBSD 5.3: /usr/local/etc/amavisdconf) file. All configuration you find here are well explained and should be easy to edit. Make sure that you configure at least one virus scanner in the first part of the file and have the following options set:

FreeBSD: /usr/local/etc/amavisd.conf

$forward_method = 'smtp:127.0.0.1:10025'
$inet_socket_port = 10024;

To get clamav, a free virus scanner, run the following command on

#> cd /usr/ports/security/clamav
#> make
#> make install
#> make clean

Restart the amavisd:

cd /usr/local/etc/rc.d/
./amavisd.sh restart

amavisd-new has a lot, lot more options to use other scanners. Most of them are "free" for uncommercial use, but closed source. So make up your mind if you want them or not. If you decide to install another, you just have to uncomment the designated part in amavisd.conf - in most cases.

The last thing to do is tell Postfix that you want to have all your emails scanned. First edit /usr/local/etc/postfix/main.cf and add the following line:

content_filter = smtp-amavis:[127.0.0.1]:10024

Now you have told Postfix that you want to use the "content_filter = smtp-amavis:[127.0.0.1]:10024" transport method on all emails. You may also consider setting "soft_bounce = yes" temporarily to make sure emails do not get bounced when something goes wrong. Emails will stay in your mail queue if you set this to true.

Finally tell Postfix what you mean by "content_filter = smtp-amavis:[127.0.0.1]:10024". Add this section to the master.cf

/usr/local/etc/postfix/master.cf

smtp-amavis unix -      -       n     -       2  smtp
   -o smtp_data_done_timeout=1200
   -o disable_dns_lookups=yes

127.0.0.1:10025 inet n  -       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

Thinks to keep in mind:

Amavisd gets only 2 processes to handle all your incoming email. While this setting is alright if you run a rather small mailserver, you might have to tune it when email starts being delayed. A good sign for misconfiguration of the amavisd-postfix duo are emails that get delayed hours and come in late (doh!), a jammed queue, warnings in /var/log/maillog and (of course) clients who complain. :-)

(It can not be stressed enough that you are not supposed to copy everything from this HOWTO without knowing what you do. For one, I could have made an error and even more important, you will have no clue what is the problem when your mailserver does not work as expected.)

Restart Postfix (postfix reload) and you are set. You may want to watch the log file (tail -f /var/log/maillog) and send a test mail. You should find a line like "X-Virus-Scanned: by AMaViS snapshot-20020222" in the email header. To make sure that your system handles infected emails correctly you may want to attach 'eicar.com'. Eicar is not a virus but a well-known (to virus scanners) signature to test if your virus recognition works. When you send this "infected" email to yourself you will receive an alert from Amavis with subject "VIRUS IN YOUR MAIL".

A last word to explain how Amavis works. Postfix receives your mail and pipes the email as defined in your "vscan" transport method into the amavis tool. Amavis will then use the configured virus scanner to scan all attachments. If the attachments are archives it will even use the archive tools to unpack them. After scanning the files it will contact Postfix on localhost's port 10025 and re-inject the email into the delivery process. But this time it sets the "content_filter" option to nothing and thus bypasses the content scanning this time. You will also see this behaviour in your /var/log/mail.log file. First you will see a "relay=vscan" and then a "relay=local".

Amavisd can also be quite intense. Don't shoot me, but after all it's "just" Perl. ;-) Keep in mind.

In case you are not authorized, make sure you tail the auth.log (probably to be found in /var/log) and also use "postfix check" to see if you have any issues open. So for example, if your permissions are screwed up and postfix can not find something, it will most likely tell you.

Open issues

If you have been successful in one of the following issues then please tell us so we can include the parts here:

  • Enforcing quotas during delivery
  • how to integrate postgrey with the Debian/GNU installation